Development
===========
Setup, tooling, and workflow for developing the KPI Calculator.
Setup
-----
.. code-block:: bash
git clone https://github.com/Project-OMOTES/kpi-calculator.git
cd kpi-calculator
pip install uv
uv sync --all-extras
This installs all runtime and development dependencies using `UV `_.
Pre-commit Hooks
----------------
The project uses `pre-commit `_ to run checks automatically on every
commit. Install the hooks once after cloning:
.. code-block:: bash
uv run pre-commit install
The hooks configured in ``.pre-commit-config.yaml`` run on every ``git commit``:
- **ruff** — linting with auto-fixes, then a strict pass to catch unfixable violations
- **ruff-format** — code formatting
- **mypy** — static type checking on ``src/kpicalculator/``
- **pre-commit-hooks** — trailing whitespace, YAML/TOML validity, merge conflict markers, debug statements
- **pytest** — full test suite
If a hook fails, the commit is aborted. Fix the reported issues and commit again. To run hooks
manually without committing:
.. code-block:: bash
uv run pre-commit run --all-files
Code Quality
------------
To run linting, formatting, or type checking independently:
.. code-block:: bash
uv run ruff check src/ unit_test/ # lint (matches CI)
uv run ruff check --fix src/ unit_test/ # lint with auto-fix
uv run ruff format src/ unit_test/ # format
uv run mypy src/kpicalculator # type check
The project uses `Ruff `_ for both linting and formatting, and mypy for static type checking. All three checks are enforced in CI on every push and pull request.
``uv run check.py`` is a shorthand for ``uv run pre-commit run --all-files``, which runs the
full hook suite (ruff, mypy, pytest, and file checks) in one command. Run this before opening
a pull request.
Pass ``--full`` to also run pylint code analysis (duplicate code, complexity, too-many-locals)
after the pre-commit suite:
.. code-block:: bash
uv run check.py --full
Testing
-------
.. code-block:: bash
uv run pytest unit_test/
With coverage:
.. code-block:: bash
uv run pytest --cov=src/kpicalculator --cov-report term-missing --cov-fail-under 80 unit_test/
The minimum coverage threshold is configured via ``--cov-fail-under`` in ``pyproject.toml`` and enforced in CI. Test data lives in ``unit_test/data/`` and includes ESDL files and XML time series.
Building Documentation
----------------------
Documentation dependencies are declared in the ``docs`` group in ``pyproject.toml`` and are
included when you run ``uv sync --all-extras``. To build the HTML docs locally:
.. code-block:: bash
uv run sphinx-build doc doc/_build/html
Then open ``doc/_build/html/index.html`` in a browser.
Documentation dependencies are declared in the ``docs`` optional dependency group in
``pyproject.toml``. ReadTheDocs installs them via ``.readthedocs.yaml``
(``extra_requirements: docs``). When adding a Sphinx extension, add it there.
Analysis Tools
--------------
The ``analysis`` dependency group (installed with ``uv sync --all-extras``) provides tools for
deeper code investigation that are not part of the standard pre-commit or CI pipeline.
**Duplicate code and complexity analysis** with `Pylint `_:
.. code-block:: bash
uv run check.py --full
Runs pylint with duplicate code detection, too-many-branches, too-many-statements, and
too-many-locals checks. Use this before major refactors or releases to surface extraction
opportunities. Findings require human judgement — not every finding warrants a change.
**Cyclomatic complexity** with `Radon `_:
.. code-block:: bash
uv run radon cc src/ --min C --show-complexity
Reports functions rated C or above. Use when a function feels hard to test or understand.
Ruff's C901 rule (max-complexity=12) is the enforced gate; radon is a supplementary view.
**Dead code detection** with `Vulture `_:
.. code-block:: bash
uv run vulture src/kpicalculator/
Vulture reports attributes, functions, and classes that appear to have no callers. Has a high
false-positive rate for this codebase (Pydantic validators, public API methods) — review
findings carefully before acting on them.
**Dependency vulnerability scanning** with `pip-audit `_:
.. code-block:: bash
uv run pip-audit --skip-editable
The ``--skip-editable`` flag excludes the local ``kpi-calculator`` package itself from the audit
(it is not on PyPI and cannot be looked up). ``pip-audit`` checks all installed dependencies
against the `OSV `_ vulnerability database and reports CVEs with fix versions.
Run this periodically or before a release to confirm no production dependencies carry known
vulnerabilities.
CI/CD
-----
The GitHub Actions workflow (``.github/workflows/ci.yml``) runs the full validation pipeline on every push and pull request. Releases are published to PyPI automatically when a GitHub Release is created from a version tag.
Security scanning (``uv run bandit -r src/``) is also part of the CI pipeline. The ``security/`` package handles input validation (path traversal prevention) and credential management (environment variables for InfluxDB). See ``input_validator.py`` and ``credential_manager.py``.