gridpf 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. gridpf-0.1.0/.github/workflows/ci.yml +120 -0
  2. gridpf-0.1.0/.github/workflows/release.yml +76 -0
  3. gridpf-0.1.0/.gitignore +95 -0
  4. gridpf-0.1.0/.pre-commit-config.yaml +40 -0
  5. gridpf-0.1.0/CHANGELOG.md +23 -0
  6. gridpf-0.1.0/LICENSE +93 -0
  7. gridpf-0.1.0/Makefile +83 -0
  8. gridpf-0.1.0/PKG-INFO +171 -0
  9. gridpf-0.1.0/README.md +120 -0
  10. gridpf-0.1.0/build_cython.py +236 -0
  11. gridpf-0.1.0/gridpf/__init__.py +60 -0
  12. gridpf-0.1.0/gridpf/__pyinstaller/__init__.py +5 -0
  13. gridpf-0.1.0/gridpf/__pyinstaller/hook-gridpf.py +5 -0
  14. gridpf-0.1.0/gridpf/_engine.py +452 -0
  15. gridpf-0.1.0/gridpf/_version.py +24 -0
  16. gridpf-0.1.0/gridpf/algebra/__init__.py +1 -0
  17. gridpf-0.1.0/gridpf/algebra/jacobian.py +115 -0
  18. gridpf-0.1.0/gridpf/algebra/sbus.py +151 -0
  19. gridpf-0.1.0/gridpf/algebra/ybus.py +139 -0
  20. gridpf-0.1.0/gridpf/contract/__init__.py +67 -0
  21. gridpf-0.1.0/gridpf/contract/runtime.py +49 -0
  22. gridpf-0.1.0/gridpf/contract/serialize.py +71 -0
  23. gridpf-0.1.0/gridpf/contract/types.py +202 -0
  24. gridpf-0.1.0/gridpf/contract/validate.py +117 -0
  25. gridpf-0.1.0/gridpf/contract/version.py +93 -0
  26. gridpf-0.1.0/gridpf/py.typed +0 -0
  27. gridpf-0.1.0/gridpf/solvers/__init__.py +1 -0
  28. gridpf-0.1.0/gridpf/solvers/dc_pf.py +101 -0
  29. gridpf-0.1.0/gridpf/solvers/gauss_seidel.py +152 -0
  30. gridpf-0.1.0/gridpf/solvers/newton_raphson.py +201 -0
  31. gridpf-0.1.0/gridpf/solvers/q_lims.py +226 -0
  32. gridpf-0.1.0/gridpf.egg-info/PKG-INFO +171 -0
  33. gridpf-0.1.0/gridpf.egg-info/SOURCES.txt +49 -0
  34. gridpf-0.1.0/gridpf.egg-info/dependency_links.txt +1 -0
  35. gridpf-0.1.0/gridpf.egg-info/entry_points.txt +2 -0
  36. gridpf-0.1.0/gridpf.egg-info/requires.txt +31 -0
  37. gridpf-0.1.0/gridpf.egg-info/top_level.txt +1 -0
  38. gridpf-0.1.0/pyproject.toml +194 -0
  39. gridpf-0.1.0/setup.cfg +4 -0
  40. gridpf-0.1.0/tests/conftest.py +122 -0
  41. gridpf-0.1.0/tests/test_contract.py +111 -0
  42. gridpf-0.1.0/tests/test_gauss_seidel.py +141 -0
  43. gridpf-0.1.0/tests/test_load_voltage.py +122 -0
  44. gridpf-0.1.0/tests/test_newton_raphson.py +166 -0
  45. gridpf-0.1.0/tests/test_numpy_only_runtime.py +143 -0
  46. gridpf-0.1.0/tests/test_q_lims.py +283 -0
  47. gridpf-0.1.0/tests/test_robustness.py +84 -0
  48. gridpf-0.1.0/tests/test_sbus.py +77 -0
  49. gridpf-0.1.0/tests/test_solve.py +116 -0
  50. gridpf-0.1.0/tests/test_version.py +17 -0
  51. gridpf-0.1.0/tests/test_ybus.py +257 -0
@@ -0,0 +1,120 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ci-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ lint:
14
+ name: Lint (pre-commit)
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.11"
21
+ # Runs every hook from .pre-commit-config.yaml (ruff, ruff-format,
22
+ # whitespace/eof/yaml/toml checks). The commit-msg-stage commitizen
23
+ # hook is skipped automatically in --all-files mode.
24
+ - uses: pre-commit/action@v3.0.1
25
+
26
+ typecheck:
27
+ name: Type check (mypy)
28
+ runs-on: ubuntu-latest
29
+ # Required gate: mypy must be clean before merge (see branch protection).
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ with:
33
+ fetch-depth: 0 # setuptools_scm needs full history + tags for the version
34
+ - uses: actions/setup-python@v5
35
+ with:
36
+ python-version: "3.11"
37
+ - run: pip install -e ".[dev]"
38
+ - run: mypy gridpf
39
+
40
+ test:
41
+ name: Test (Python ${{ matrix.python-version }})
42
+ runs-on: ubuntu-latest
43
+ strategy:
44
+ fail-fast: false
45
+ matrix:
46
+ python-version: ["3.10", "3.11", "3.12"]
47
+ steps:
48
+ - uses: actions/checkout@v4
49
+ with:
50
+ fetch-depth: 0 # setuptools_scm needs full history + tags for the version
51
+ - uses: actions/setup-python@v5
52
+ with:
53
+ python-version: ${{ matrix.python-version }}
54
+ - run: pip install -e ".[test]"
55
+ - run: pytest tests/ --cov=gridpf --cov-report=xml --cov-report=term
56
+ - uses: actions/upload-artifact@v4
57
+ if: matrix.python-version == '3.11'
58
+ with:
59
+ name: coverage-xml
60
+ path: coverage.xml
61
+
62
+ build:
63
+ name: Build (sdist + wheel)
64
+ runs-on: ubuntu-latest
65
+ needs: [lint, typecheck, test]
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ with:
69
+ fetch-depth: 0
70
+ - uses: actions/setup-python@v5
71
+ with:
72
+ python-version: "3.11"
73
+ - run: pip install build
74
+ - run: python -m build
75
+ - run: pipx run twine check dist/*
76
+ # Release readiness: the distributable wheel must install into a clean
77
+ # environment and actually solve a real case — not merely pass metadata
78
+ # checks. Run from /tmp so `import gridpf` resolves to the INSTALLED
79
+ # wheel, not the source tree in the workspace.
80
+ - name: Smoke-test built wheel in a clean environment
81
+ run: |
82
+ python -m venv /tmp/smoke-env
83
+ /tmp/smoke-env/bin/pip install --upgrade pip
84
+ /tmp/smoke-env/bin/pip install "$(ls dist/*.whl)"
85
+ cd /tmp
86
+ /tmp/smoke-env/bin/python - <<'PY'
87
+ import numpy as np
88
+ import gridpf
89
+ from gridpf import PFInput, PFOptions, solve
90
+
91
+ print("gridpf version:", gridpf.__version__)
92
+ # Минимальная 2-узловая сеть: slack(0) — PQ(1) с нагрузкой 0.5+j0.2 p.u.
93
+ z = 0.02 + 0.06j
94
+ net = PFInput(
95
+ n_bus=2, n_branch=1,
96
+ bus_ids=np.array([10, 11], dtype=np.int64),
97
+ bus_vn_kv=np.array([110.0, 110.0]),
98
+ bus_type=np.array([2, 0], dtype=np.int8),
99
+ slack_idx=0,
100
+ branch_ids=np.array([100], dtype=np.int64),
101
+ from_idx=np.array([0], dtype=np.int64),
102
+ to_idx=np.array([1], dtype=np.int64),
103
+ branch_r=np.array([z.real]), branch_x=np.array([z.imag]),
104
+ branch_g=np.zeros(1), branch_b=np.zeros(1),
105
+ branch_g_from=np.zeros(1), branch_b_from=np.zeros(1),
106
+ branch_g_to=np.zeros(1), branch_b_to=np.zeros(1),
107
+ tap_ratio=np.array([1.0]), phase_shift=np.zeros(1),
108
+ bus_g_shunt=np.zeros(2), bus_b_shunt=np.zeros(2),
109
+ bus_p_injection=np.array([0.0, -0.5]),
110
+ bus_q_injection=np.array([0.0, -0.2]),
111
+ )
112
+ res = solve(net, PFOptions())
113
+ assert res.converged, "PF failed to converge on the 2-bus smoke case"
114
+ print(f"wheel smoke OK - converged={res.converged} "
115
+ f"it_nr={res.iterations_nr} |V|={np.abs(res.V).round(4).tolist()}")
116
+ PY
117
+ - uses: actions/upload-artifact@v4
118
+ with:
119
+ name: dist
120
+ path: dist/*
@@ -0,0 +1,76 @@
1
+ name: Release
2
+
3
+ # Publish to PyPI when a version tag is pushed.
4
+ #
5
+ # Versioning is handled by setuptools_scm (the tag IS the version) and tags are
6
+ # created from Conventional Commits with `cz bump` (run locally, then
7
+ # `git push --follow-tags`). This workflow only builds and publishes.
8
+ #
9
+ # Publishing uses PyPI Trusted Publishing (OIDC) — no API token in secrets.
10
+ # One-time setup on PyPI: add this repository as a trusted publisher for the
11
+ # `gridpf` project, workflow `release.yml`, environment `pypi`.
12
+
13
+ on:
14
+ push:
15
+ tags:
16
+ - "v*"
17
+
18
+ jobs:
19
+ build:
20
+ name: Build distributions
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+ - uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.11"
29
+ - run: pip install build
30
+ - run: python -m build
31
+ - run: pipx run twine check dist/*
32
+ - uses: actions/upload-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/*
36
+
37
+ publish:
38
+ name: Publish to PyPI
39
+ needs: build
40
+ runs-on: ubuntu-latest
41
+ environment: pypi
42
+ permissions:
43
+ id-token: write # required for Trusted Publishing (OIDC)
44
+ steps:
45
+ - uses: actions/download-artifact@v4
46
+ with:
47
+ name: dist
48
+ path: dist
49
+ - uses: pypa/gh-action-pypi-publish@release/v1
50
+
51
+ github-release:
52
+ name: GitHub Release
53
+ # Independent of PyPI publish: depends only on a good build, so a GitHub
54
+ # Release (with attached artifacts) is created even if the PyPI step is
55
+ # not yet wired (e.g. before the trusted publisher is configured). Re-run
56
+ # the publish job separately once PyPI is set up.
57
+ needs: build
58
+ runs-on: ubuntu-latest
59
+ permissions:
60
+ contents: write # create the release + upload assets
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+ with:
64
+ fetch-depth: 0 # full history so --generate-notes can diff against the previous tag
65
+ - uses: actions/download-artifact@v4
66
+ with:
67
+ name: dist
68
+ path: dist
69
+ - name: Create GitHub Release with auto-generated notes
70
+ env:
71
+ GH_TOKEN: ${{ github.token }}
72
+ run: |
73
+ gh release create "${GITHUB_REF_NAME}" \
74
+ --title "${GITHUB_REF_NAME}" \
75
+ --generate-notes \
76
+ dist/*
@@ -0,0 +1,95 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Unit test / coverage reports
34
+ htmlcov/
35
+ .tox/
36
+ .nox/
37
+ .coverage
38
+ .coverage.*
39
+ .cache
40
+ coverage.xml
41
+ *.cover
42
+ .hypothesis/
43
+ .pytest_cache/
44
+ cover/
45
+
46
+ # Environments
47
+ .env
48
+ .venv
49
+ env/
50
+ venv/
51
+ ENV/
52
+ env.bak/
53
+ venv.bak/
54
+
55
+ # mypy / ruff / pytype caches
56
+ .mypy_cache/
57
+ .dmypy.json
58
+ dmypy.json
59
+ .pyre/
60
+ .pytype/
61
+ .ruff_cache/
62
+
63
+ # IDE / OS
64
+ .idea/
65
+ .vscode/
66
+ *.swp
67
+ *.swo
68
+ *~
69
+ .DS_Store
70
+ Thumbs.db
71
+
72
+ # Sensitive
73
+ .env*
74
+ secrets.json
75
+ credentials.json
76
+ *.key
77
+ *.pem
78
+ *.p12
79
+ private_key*
80
+ id_rsa*
81
+ id_dsa*
82
+ id_ecdsa*
83
+ id_ed25519*
84
+
85
+ # setuptools_scm generated version file
86
+ gridpf/_version.py
87
+
88
+ # Local settings and Claude memory (not committed)
89
+ .claude/
90
+
91
+ # One-off debug scripts
92
+ scripts/
93
+
94
+ # Local-only specs / extracted material
95
+ .specs/
@@ -0,0 +1,40 @@
1
+ # Pre-commit hooks for gridpf.
2
+ #
3
+ # Install:
4
+ # .venv/bin/pip install pre-commit
5
+ # .venv/bin/pre-commit install
6
+ #
7
+ # The same hooks run in CI (.github/workflows/ci.yml -> pre-commit/action).
8
+ # The ruff version here must match the pin in pyproject.toml ([dev]), otherwise
9
+ # the local hook and CI may diverge on rules.
10
+
11
+ exclude: '^(tests/test_data/|\.venv/|build/|dist/)'
12
+
13
+ repos:
14
+ - repo: https://github.com/pre-commit/pre-commit-hooks
15
+ rev: v6.0.0
16
+ hooks:
17
+ - id: trailing-whitespace
18
+ - id: end-of-file-fixer
19
+ - id: check-yaml
20
+ - id: check-toml
21
+ - id: check-json
22
+ - id: check-merge-conflict
23
+ - id: check-added-large-files
24
+ args: ['--maxkb=3000']
25
+ - id: mixed-line-ending
26
+ args: ['--fix=lf']
27
+ - id: debug-statements
28
+
29
+ - repo: https://github.com/astral-sh/ruff-pre-commit
30
+ rev: v0.15.12
31
+ hooks:
32
+ - id: ruff
33
+ args: [--fix]
34
+ - id: ruff-format
35
+
36
+ - repo: https://github.com/commitizen-tools/commitizen
37
+ rev: v4.10.0
38
+ hooks:
39
+ - id: commitizen
40
+ stages: [commit-msg]
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+ Releases are cut from Conventional Commits via `cz bump`; the git tag is the
8
+ authoritative version (`setuptools_scm`).
9
+
10
+ ## [Unreleased]
11
+
12
+ ### Added
13
+
14
+ - Initial public release: pure-Python Power Flow engine (`gridpf`) extracted from
15
+ the eris-pf adapter.
16
+ - Opaque per-unit data contract `PFInput` / `PFOptions` / `PFResult`
17
+ (`gridpf.contract`), versioned (`CONTRACT_VERSION`) with `.npz` serialization.
18
+ - Model-free `solve(net, options, *, init_v=None)`: Gauss-Seidel warm-start +
19
+ Newton-Raphson with optional Q-limit outer loop, DC and soft fallbacks,
20
+ polynomial voltage-dependent load (СХН), warm-start, and controllable-bus
21
+ setpoints (`bus_v_set` / `bus_va_set`) clamped over the start vector.
22
+ - Power-flow numerics adapted from pandapower / PYPOWER (BSD 3-Clause; see
23
+ LICENSE).
gridpf-0.1.0/LICENSE ADDED
@@ -0,0 +1,93 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Evgeny Istomin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ================================================================================
24
+ THIRD-PARTY SOFTWARE NOTICES
25
+ ================================================================================
26
+
27
+ This project contains code adapted from the open-source projects listed below.
28
+ The adapted code retains the original copyright notice as required by its
29
+ license.
30
+
31
+ --------------------------------------------------------------------------------
32
+ pandapower / PYPOWER
33
+ --------------------------------------------------------------------------------
34
+
35
+ The power-flow numerics are adapted from pandapower, which in turn bundles
36
+ PYPOWER (a port of MATPOWER, PSERC). Both are distributed under the BSD 3-Clause
37
+ License (full text below).
38
+
39
+ Copyright (c) 2016-2025 by University of Kassel and Fraunhofer Institute for
40
+ Energy Economics and Energy System Technology (IEE), Kassel. All rights
41
+ reserved. (pandapower)
42
+
43
+ Copyright (c) 1996-2015, PSERC, and individual contributors (PYPOWER / MATPOWER).
44
+
45
+ Upstream: https://github.com/e2nIEE/pandapower
46
+ https://github.com/rwl/PYPOWER
47
+
48
+ Files adapted from pandapower / PYPOWER into this project:
49
+
50
+ pandapower/pypower/makeYbus.py
51
+ -> gridpf/algebra/ybus.py (Ybus / Yf / Yt assembly)
52
+ pandapower/pypower/dSbus_dV.py
53
+ -> gridpf/algebra/jacobian.py (power-mismatch Jacobian blocks)
54
+ pandapower/pypower/newtonpf.py
55
+ -> gridpf/solvers/newton_raphson.py (Newton-Raphson iteration)
56
+ pandapower/pypower/gausspf.py
57
+ -> gridpf/solvers/gauss_seidel.py (Gauss-Seidel warm-start)
58
+ pandapower/pypower/dcpf.py
59
+ -> gridpf/solvers/dc_pf.py (DC power-flow warm-start)
60
+
61
+ Adaptation summary: the PYPOWER layer (ppc_conversion, idx_bus, idx_brch,
62
+ ppoption) was removed; the code operates on this project's own opaque per-unit
63
+ contract (gridpf/contract/types.py::PFInput) instead of the PYPOWER case format,
64
+ and carries no print side effects.
65
+
66
+ BSD 3-Clause License
67
+ ....................
68
+
69
+ Redistribution and use in source and binary forms, with or without
70
+ modification, are permitted provided that the following conditions are met:
71
+
72
+ 1. Redistributions of source code must retain the above copyright notice,
73
+ this list of conditions and the following disclaimer.
74
+
75
+ 2. Redistributions in binary form must reproduce the above copyright notice,
76
+ this list of conditions and the following disclaimer in the documentation
77
+ and/or other materials provided with the distribution.
78
+
79
+ 3. Neither the name of the copyright holder nor the names of its
80
+ contributors may be used to endorse or promote products derived from this
81
+ software without specific prior written permission.
82
+
83
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
84
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
85
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
86
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
87
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
88
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
89
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
90
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
91
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
92
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
93
+ POSSIBILITY OF SUCH DAMAGE.
gridpf-0.1.0/Makefile ADDED
@@ -0,0 +1,83 @@
1
+ # Makefile for gridpf
2
+
3
+ VENV := .venv
4
+ PYTHON := python3
5
+ ifeq ($(OS),Windows_NT)
6
+ VENV_BIN := $(VENV)/Scripts
7
+ else
8
+ VENV_BIN := $(VENV)/bin
9
+ endif
10
+ VENV_PYTHON := $(VENV_BIN)/python
11
+ VENV_PIP := $(VENV_BIN)/pip
12
+
13
+ HAS_VENV := $(shell test -d $(VENV) && echo 1 || echo 0)
14
+
15
+ .PHONY: help venv check-venv install install-dev test test-cov lint format type-check clean build setup
16
+
17
+ venv:
18
+ @echo "Creating virtual environment..."
19
+ $(PYTHON) -m venv $(VENV)
20
+ $(VENV_PIP) install --upgrade pip setuptools wheel
21
+ @echo "Activate it: source $(VENV_BIN)/activate"
22
+
23
+ check-venv:
24
+ ifeq ($(HAS_VENV),0)
25
+ @echo "Virtual environment not found. Create it: make venv"
26
+ @exit 1
27
+ endif
28
+
29
+ install: check-venv
30
+ $(VENV_PIP) install -e .
31
+
32
+ install-dev: check-venv
33
+ $(VENV_PIP) install -e ".[dev,test]"
34
+ $(VENV_BIN)/pre-commit install
35
+
36
+ test: check-venv
37
+ $(VENV_BIN)/pytest tests/ -v
38
+
39
+ test-cov: check-venv
40
+ $(VENV_BIN)/pytest tests/ -v --cov=gridpf --cov-report=html --cov-report=term
41
+
42
+ lint: check-venv
43
+ $(VENV_BIN)/ruff check gridpf tests
44
+ $(VENV_BIN)/ruff format --check gridpf tests
45
+
46
+ format: check-venv
47
+ $(VENV_BIN)/ruff format gridpf tests
48
+ $(VENV_BIN)/ruff check --fix gridpf tests
49
+
50
+ type-check: check-venv
51
+ $(VENV_BIN)/mypy gridpf
52
+
53
+ clean:
54
+ rm -rf build/ dist/ *.egg-info
55
+ rm -rf .coverage htmlcov/ .pytest_cache/ .mypy_cache/ .ruff_cache/
56
+ find . -type d -name __pycache__ -not -path './.venv/*' -exec rm -rf {} +
57
+ find . -type f -name "*.pyc" -not -path './.venv/*' -delete
58
+
59
+ build: check-venv
60
+ $(VENV_PYTHON) -m build
61
+
62
+ check: format lint type-check test
63
+ @echo "All checks passed."
64
+
65
+ setup:
66
+ @$(MAKE) venv
67
+ @$(MAKE) install-dev
68
+ @echo "Environment ready. Activate it: source $(VENV_BIN)/activate"
69
+
70
+ help:
71
+ @echo "Available targets:"
72
+ @echo " make setup Full setup for a new developer"
73
+ @echo " make venv Create the virtual environment"
74
+ @echo " make install Install the package"
75
+ @echo " make install-dev Install with dev/test extras and pre-commit hooks"
76
+ @echo " make test Run the test suite"
77
+ @echo " make test-cov Run tests with a coverage report"
78
+ @echo " make lint Style check (ruff)"
79
+ @echo " make format Auto-format"
80
+ @echo " make type-check Type check (mypy)"
81
+ @echo " make check format + lint + type-check + test"
82
+ @echo " make clean Remove temporary files"
83
+ @echo " make build Build the package"