PyDiffGame 1.0.0__tar.gz → 2.0.1__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.
- pydiffgame-2.0.1/.github/workflows/python-publish.yml +132 -0
- pydiffgame-2.0.1/.github/workflows/tests.yml +51 -0
- pydiffgame-2.0.1/.gitignore +26 -0
- pydiffgame-2.0.1/.pre-commit-config.yaml +29 -0
- pydiffgame-2.0.1/CLAUDE.md +32 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/CODE_OF_CONDUCT.md +1 -1
- pydiffgame-2.0.1/CONTRIBUTING.md +67 -0
- pydiffgame-2.0.1/PKG-INFO +421 -0
- pydiffgame-2.0.1/README.md +362 -0
- pydiffgame-2.0.1/docs/README.md +362 -0
- pydiffgame-2.0.1/images/readme/masses_cost.png +0 -0
- pydiffgame-2.0.1/images/readme/masses_game_vs_lqr.png +0 -0
- pydiffgame-2.0.1/images/readme/masses_schematic.png +0 -0
- pydiffgame-2.0.1/pyproject.toml +94 -0
- pydiffgame-2.0.1/requirements.txt +8 -0
- pydiffgame-2.0.1/src/PyDiffGame/__init__.py +50 -0
- pydiffgame-2.0.1/src/PyDiffGame/_typing.py +25 -0
- pydiffgame-2.0.1/src/PyDiffGame/base.py +468 -0
- pydiffgame-2.0.1/src/PyDiffGame/comparison.py +121 -0
- pydiffgame-2.0.1/src/PyDiffGame/continuous.py +223 -0
- pydiffgame-2.0.1/src/PyDiffGame/discrete.py +211 -0
- pydiffgame-2.0.1/src/PyDiffGame/examples/InvertedPendulumComparison.py +232 -0
- pydiffgame-2.0.1/src/PyDiffGame/examples/MassesWithSpringsComparison.py +119 -0
- pydiffgame-2.0.1/src/PyDiffGame/examples/PVTOL.py +216 -0
- pydiffgame-2.0.1/src/PyDiffGame/examples/PVTOLComparison.py +117 -0
- pydiffgame-2.0.1/src/PyDiffGame/examples/QuadRotorControl.py +638 -0
- pydiffgame-2.0.1/src/PyDiffGame/lqr.py +30 -0
- pydiffgame-2.0.1/src/PyDiffGame/objective.py +108 -0
- pydiffgame-2.0.1/src/PyDiffGame/plotting.py +98 -0
- pydiffgame-2.0.1/tests/conftest.py +9 -0
- pydiffgame-2.0.1/tests/test_discrete.py +50 -0
- pydiffgame-2.0.1/tests/test_examples.py +75 -0
- pydiffgame-2.0.1/tests/test_game.py +45 -0
- pydiffgame-2.0.1/tests/test_lqr.py +66 -0
- pydiffgame-2.0.1/tests/test_objective.py +45 -0
- pydiffgame-2.0.1/tests/test_simulation.py +60 -0
- pydiffgame-2.0.1/tools/bump_version.py +78 -0
- pydiffgame-2.0.1/tools/generate_readme_figures.py +336 -0
- pydiffgame-2.0.1/uv.lock +1298 -0
- pydiffgame-1.0.0/.github/workflows/python-publish.yml +0 -70
- pydiffgame-1.0.0/CONTRIBUTING.md +0 -18
- pydiffgame-1.0.0/PKG-INFO +0 -306
- pydiffgame-1.0.0/README.md +0 -292
- pydiffgame-1.0.0/docs/README.md +0 -277
- pydiffgame-1.0.0/pyproject.toml +0 -26
- pydiffgame-1.0.0/requirements.txt +0 -6
- pydiffgame-1.0.0/src/PyDiffGame/ContinuousPyDiffGame.py +0 -275
- pydiffgame-1.0.0/src/PyDiffGame/DiscretePyDiffGame.py +0 -359
- pydiffgame-1.0.0/src/PyDiffGame/LQR.py +0 -73
- pydiffgame-1.0.0/src/PyDiffGame/Objective.py +0 -62
- pydiffgame-1.0.0/src/PyDiffGame/PyDiffGame.py +0 -1273
- pydiffgame-1.0.0/src/PyDiffGame/PyDiffGameLQRComparison.py +0 -169
- pydiffgame-1.0.0/src/PyDiffGame/__init__.py +0 -0
- pydiffgame-1.0.0/src/PyDiffGame/examples/InvertedPendulumComparison.py +0 -257
- pydiffgame-1.0.0/src/PyDiffGame/examples/MassesWithSpringsComparison.py +0 -218
- pydiffgame-1.0.0/src/PyDiffGame/examples/PVTOL.py +0 -222
- pydiffgame-1.0.0/src/PyDiffGame/examples/PVTOLComparison.py +0 -111
- pydiffgame-1.0.0/src/PyDiffGame/examples/QuadRotorControl.py +0 -548
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/CITATIONS.bib +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/LICENSE +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/_config.yml +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/images/Logo_ISTRC_Green_English.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/images/logo.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/images/logo_abc.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/2/2-players_large_1.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/2/2-players_large_2.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/2/LQR_large_1.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/2/LQR_large_2.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/2/two_masses_tikz.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/4/4-players_large_1.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/4/4-players_large_2.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/4/LQR_large_1.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/4/LQR_large_2.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/8/8-players_large_1.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/8/8-players_large_2.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/8/LQR_large_1.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/8/LQR_large_2.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL/PVTOL1.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL/PVTOL10.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL/PVTOL100.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL/PVTOL1000.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL0001.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL001.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL01.png +0 -0
- {pydiffgame-1.0.0 → pydiffgame-2.0.1}/src/PyDiffGame/examples/figures/PVTOL1.png +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Publishes the package to PyPI and creates the matching GitHub Release,
|
|
2
|
+
# auto-incrementing the version each run.
|
|
3
|
+
#
|
|
4
|
+
# Flow (just run it — Actions -> Upload Python Package -> Run workflow):
|
|
5
|
+
# 1. bump-version : increment the version (carry-at-9 via tools/bump_version.py),
|
|
6
|
+
# commit it back to master.
|
|
7
|
+
# 2. release-build : build the dists from the bumped master.
|
|
8
|
+
# 3. pypi-publish : upload to PyPI via Trusted Publishing (OIDC, no tokens).
|
|
9
|
+
# 4. github-release: create the v<version> GitHub Release with notes + dists.
|
|
10
|
+
#
|
|
11
|
+
# Versions roll over at 9: 2.0.9 -> 2.1.0, 2.9.9 -> 3.0.0.
|
|
12
|
+
|
|
13
|
+
name: Upload Python Package
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
bump-version:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
permissions:
|
|
25
|
+
contents: write
|
|
26
|
+
outputs:
|
|
27
|
+
version: ${{ steps.bump.outputs.version }}
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v5
|
|
30
|
+
with:
|
|
31
|
+
ref: master
|
|
32
|
+
|
|
33
|
+
- name: Increment the version (carry-at-9)
|
|
34
|
+
id: bump
|
|
35
|
+
run: |
|
|
36
|
+
new="$(python3 tools/bump_version.py)"
|
|
37
|
+
echo "version=$new" >> "$GITHUB_OUTPUT"
|
|
38
|
+
echo "Bumped to $new"
|
|
39
|
+
|
|
40
|
+
- name: Commit and push the bump
|
|
41
|
+
run: |
|
|
42
|
+
git config user.name "github-actions[bot]"
|
|
43
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
44
|
+
git add pyproject.toml src/PyDiffGame/__init__.py
|
|
45
|
+
git commit -m "chore: bump version to ${{ steps.bump.outputs.version }} [skip ci]"
|
|
46
|
+
git push origin HEAD:master
|
|
47
|
+
|
|
48
|
+
release-build:
|
|
49
|
+
needs: bump-version
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v5
|
|
53
|
+
with:
|
|
54
|
+
ref: master # the bumped commit
|
|
55
|
+
|
|
56
|
+
- name: Install uv
|
|
57
|
+
uses: astral-sh/setup-uv@v6
|
|
58
|
+
|
|
59
|
+
- name: Build release distributions
|
|
60
|
+
run: uv build
|
|
61
|
+
|
|
62
|
+
- name: Upload distributions
|
|
63
|
+
uses: actions/upload-artifact@v5
|
|
64
|
+
with:
|
|
65
|
+
name: release-dists
|
|
66
|
+
path: dist/
|
|
67
|
+
|
|
68
|
+
pypi-publish:
|
|
69
|
+
needs:
|
|
70
|
+
- release-build
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
permissions:
|
|
73
|
+
# IMPORTANT: this permission is mandatory for trusted publishing
|
|
74
|
+
id-token: write
|
|
75
|
+
|
|
76
|
+
environment:
|
|
77
|
+
name: pypi
|
|
78
|
+
url: https://pypi.org/project/PyDiffGame/
|
|
79
|
+
|
|
80
|
+
steps:
|
|
81
|
+
- name: Retrieve release distributions
|
|
82
|
+
uses: actions/download-artifact@v5
|
|
83
|
+
with:
|
|
84
|
+
name: release-dists
|
|
85
|
+
path: dist/
|
|
86
|
+
|
|
87
|
+
# Authentication is via PyPI Trusted Publishing (OIDC) — no token needed.
|
|
88
|
+
# Trusted publisher on PyPI: owner krichelj, repo PyDiffGame,
|
|
89
|
+
# workflow python-publish.yml, environment pypi.
|
|
90
|
+
- name: Publish release distributions to PyPI
|
|
91
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
92
|
+
with:
|
|
93
|
+
packages-dir: dist/
|
|
94
|
+
# Don't fail if this version is already on PyPI (idempotent re-runs).
|
|
95
|
+
skip-existing: true
|
|
96
|
+
|
|
97
|
+
github-release:
|
|
98
|
+
needs:
|
|
99
|
+
- bump-version
|
|
100
|
+
- pypi-publish
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
permissions:
|
|
103
|
+
# Needed to create the release and its tag.
|
|
104
|
+
contents: write
|
|
105
|
+
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@v5
|
|
108
|
+
with:
|
|
109
|
+
ref: master
|
|
110
|
+
|
|
111
|
+
- name: Retrieve release distributions
|
|
112
|
+
uses: actions/download-artifact@v5
|
|
113
|
+
with:
|
|
114
|
+
name: release-dists
|
|
115
|
+
path: dist/
|
|
116
|
+
|
|
117
|
+
- name: Create or update the GitHub Release
|
|
118
|
+
env:
|
|
119
|
+
GH_TOKEN: ${{ github.token }}
|
|
120
|
+
VERSION: ${{ needs.bump-version.outputs.version }}
|
|
121
|
+
run: |
|
|
122
|
+
tag="v${VERSION}"
|
|
123
|
+
echo "Releasing ${tag}"
|
|
124
|
+
if gh release view "$tag" >/dev/null 2>&1; then
|
|
125
|
+
echo "Release ${tag} already exists - refreshing its assets."
|
|
126
|
+
gh release upload "$tag" dist/* --clobber
|
|
127
|
+
else
|
|
128
|
+
gh release create "$tag" dist/* \
|
|
129
|
+
--title "$tag" \
|
|
130
|
+
--generate-notes \
|
|
131
|
+
--target master
|
|
132
|
+
fi
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master, main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: tests-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
name: Python ${{ matrix.python-version }}
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v5
|
|
27
|
+
|
|
28
|
+
- name: Install uv
|
|
29
|
+
uses: astral-sh/setup-uv@v6
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: true
|
|
32
|
+
|
|
33
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
34
|
+
run: uv python install ${{ matrix.python-version }}
|
|
35
|
+
|
|
36
|
+
- name: Sync the environment (locked)
|
|
37
|
+
run: uv sync --extra dev --python ${{ matrix.python-version }} --frozen
|
|
38
|
+
|
|
39
|
+
- name: Lint with ruff
|
|
40
|
+
run: uv run ruff check src/PyDiffGame tests --exclude src/PyDiffGame/examples
|
|
41
|
+
|
|
42
|
+
- name: Check formatting with ruff
|
|
43
|
+
run: uv run ruff format --check src/PyDiffGame tests
|
|
44
|
+
|
|
45
|
+
- name: Type-check with mypy
|
|
46
|
+
run: uv run mypy src/PyDiffGame --exclude 'examples'
|
|
47
|
+
|
|
48
|
+
- name: Run the test suite
|
|
49
|
+
env:
|
|
50
|
+
MPLBACKEND: Agg
|
|
51
|
+
run: uv run pytest -q
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv*/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
|
|
16
|
+
# Test / coverage
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.ruff_cache/
|
|
22
|
+
|
|
23
|
+
# OS / editors
|
|
24
|
+
.DS_Store
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Pre-commit hooks for PyDiffGame.
|
|
2
|
+
# Install once with: pre-commit install
|
|
3
|
+
# Run on everything: pre-commit run --all-files
|
|
4
|
+
repos:
|
|
5
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
6
|
+
rev: v5.0.0
|
|
7
|
+
hooks:
|
|
8
|
+
- id: trailing-whitespace
|
|
9
|
+
- id: end-of-file-fixer
|
|
10
|
+
- id: check-yaml
|
|
11
|
+
- id: check-toml
|
|
12
|
+
- id: check-added-large-files
|
|
13
|
+
- id: check-merge-conflict
|
|
14
|
+
|
|
15
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
16
|
+
rev: v0.8.4
|
|
17
|
+
hooks:
|
|
18
|
+
# Linter (with autofix), then the black-compatible formatter.
|
|
19
|
+
- id: ruff
|
|
20
|
+
args: [--fix]
|
|
21
|
+
- id: ruff-format
|
|
22
|
+
|
|
23
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
24
|
+
rev: v1.13.0
|
|
25
|
+
hooks:
|
|
26
|
+
- id: mypy
|
|
27
|
+
files: ^src/PyDiffGame/
|
|
28
|
+
exclude: ^src/PyDiffGame/examples/
|
|
29
|
+
additional_dependencies: [numpy]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# PyDiffGame — repository guide for Claude
|
|
2
|
+
|
|
3
|
+
## Python tooling (uv-first)
|
|
4
|
+
- Use **uv** for everything; pip is only a documented fallback.
|
|
5
|
+
- `uv sync --extra dev`, `uv run pytest`, `uv run ruff check`, `uv run ruff format`,
|
|
6
|
+
`uv run mypy src/PyDiffGame`, `uv build`.
|
|
7
|
+
- Keep the quality gates green before committing: ruff format, ruff check, mypy on
|
|
8
|
+
`src/PyDiffGame`, and the pytest suite — all via `uv run`.
|
|
9
|
+
|
|
10
|
+
## Versioning (carry-at-9)
|
|
11
|
+
- The version is `X.Y.Z` with single-digit components that roll over at 9:
|
|
12
|
+
`2.0.9 -> 2.1.0`, `2.9.9 -> 3.0.0` (the major keeps growing).
|
|
13
|
+
- Increment **only** via `tools/bump_version.py`, which updates the version in both
|
|
14
|
+
`pyproject.toml` and `src/PyDiffGame/__init__.py`. Never hand-edit version strings.
|
|
15
|
+
- The version is bumped **automatically** by the publish workflow on each release, so
|
|
16
|
+
do not bump it in ordinary PRs — the release run does it.
|
|
17
|
+
|
|
18
|
+
## Releasing
|
|
19
|
+
- `Actions -> Upload Python Package -> Run workflow` (on `master`). The workflow
|
|
20
|
+
auto-increments the version, commits it to `master`, builds with `uv build`,
|
|
21
|
+
publishes to PyPI via Trusted Publishing (OIDC, no tokens), and creates the matching
|
|
22
|
+
`v<version>` GitHub Release with notes and the built dists attached. It is idempotent
|
|
23
|
+
(`skip-existing`).
|
|
24
|
+
|
|
25
|
+
## Docs
|
|
26
|
+
- `README.md` is the single canonical readme and is also the PyPI long-description
|
|
27
|
+
(`pyproject.toml: readme = "README.md"`), so its image/file links must be **absolute**
|
|
28
|
+
(`raw.githubusercontent.com/.../master/...` for images, `github.com/.../blob/master/...`
|
|
29
|
+
for files) so they render on PyPI.
|
|
30
|
+
- Keep `docs/README.md` identical to `README.md`.
|
|
31
|
+
- README figures are generated from the live solver:
|
|
32
|
+
`uv run python tools/generate_readme_figures.py`.
|
|
@@ -60,7 +60,7 @@ representative at an online or offline event.
|
|
|
60
60
|
|
|
61
61
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
62
|
reported to the community leaders responsible for enforcement at
|
|
63
|
-
.
|
|
63
|
+
skricheli2@gmail.com.
|
|
64
64
|
All complaints will be reviewed and investigated promptly and fairly.
|
|
65
65
|
|
|
66
66
|
All community leaders are obligated to respect the privacy and security of the
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Contribution Guidelines
|
|
2
|
+
|
|
3
|
+
This repo is part of a research conducted at Ben Gurion University,
|
|
4
|
+
and is thus open source. We would love to receive your input!
|
|
5
|
+
|
|
6
|
+
Please ensure your pull request adheres to the following guidelines:
|
|
7
|
+
|
|
8
|
+
- Search previous suggestions before making a new one, as yours may be a duplicate.
|
|
9
|
+
- Make an individual pull request for each suggestion.
|
|
10
|
+
- New categories or improvements to the existing categorization are welcome.
|
|
11
|
+
- Check your spelling and grammar.
|
|
12
|
+
- Make sure your text editor is set to remove trailing whitespace.
|
|
13
|
+
- The pull request and commit should have a useful title.
|
|
14
|
+
|
|
15
|
+
## Development setup
|
|
16
|
+
|
|
17
|
+
PyDiffGame requires **Python >= 3.11** and uses [uv](https://docs.astral.sh/uv/)
|
|
18
|
+
for environment and dependency management. Install uv, sync the locked
|
|
19
|
+
development environment, and enable the pre-commit hooks so the code-quality
|
|
20
|
+
tools run automatically on every commit:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# install uv: https://docs.astral.sh/uv/getting-started/installation/
|
|
24
|
+
uv sync --extra dev
|
|
25
|
+
uv run pre-commit install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`uv sync` creates the virtual environment and installs the exact, locked
|
|
29
|
+
dependencies. Run the tooling through `uv run`:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv run ruff format src/PyDiffGame tests # auto-format (black-compatible)
|
|
33
|
+
uv run ruff check src/PyDiffGame tests # lint
|
|
34
|
+
uv run mypy src/PyDiffGame # type-check
|
|
35
|
+
uv run pytest # test suite
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Continuous integration runs the formatter check, the linter, the type checker
|
|
39
|
+
and the full suite (all via uv) across Python 3.11–3.14, so please make sure
|
|
40
|
+
they pass locally.
|
|
41
|
+
|
|
42
|
+
## Releasing
|
|
43
|
+
|
|
44
|
+
Publishing a new version is a single automated step — just run the publish
|
|
45
|
+
workflow: **Actions -> Upload Python Package -> Run workflow** (on `master`).
|
|
46
|
+
|
|
47
|
+
The run automatically:
|
|
48
|
+
|
|
49
|
+
1. **Increments the version** with `tools/bump_version.py`, which rolls each
|
|
50
|
+
component over at 9 (`2.0.9 -> 2.1.0`, `2.9.9 -> 3.0.0`), updating both
|
|
51
|
+
`pyproject.toml` and `src/PyDiffGame/__init__.py`, and commits the bump to
|
|
52
|
+
`master`.
|
|
53
|
+
2. Builds the distributions with `uv build`.
|
|
54
|
+
3. Uploads them to PyPI via
|
|
55
|
+
[Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC — no
|
|
56
|
+
tokens or secrets).
|
|
57
|
+
4. Creates a `v<version>` GitHub Release with auto-generated notes and the built
|
|
58
|
+
wheels/sdist attached.
|
|
59
|
+
|
|
60
|
+
You normally never edit the version by hand. To bump it locally (e.g. to test),
|
|
61
|
+
run `uv run python tools/bump_version.py` (`--dry-run` to preview, `--current`
|
|
62
|
+
to print the current version). The PyPI upload is idempotent (`skip-existing`),
|
|
63
|
+
so re-running the workflow is safe.
|
|
64
|
+
|
|
65
|
+
Thank you for your contribution!
|
|
66
|
+
|
|
67
|
+
Joshua Shay Kricheli
|