geodesiq 0.1.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.
Files changed (57) hide show
  1. geodesiq-0.1.1/.github/workflows/ci.yml +162 -0
  2. geodesiq-0.1.1/.github/workflows/publish.yml +101 -0
  3. geodesiq-0.1.1/.github/workflows/release.yml +125 -0
  4. geodesiq-0.1.1/.gitignore +218 -0
  5. geodesiq-0.1.1/CHANGELOG.md +21 -0
  6. geodesiq-0.1.1/CONTRIBUTING.md +70 -0
  7. geodesiq-0.1.1/LICENSE +504 -0
  8. geodesiq-0.1.1/PKG-INFO +117 -0
  9. geodesiq-0.1.1/README.md +84 -0
  10. geodesiq-0.1.1/benchmarks/__init__.py +1 -0
  11. geodesiq-0.1.1/benchmarks/_models.py +126 -0
  12. geodesiq-0.1.1/benchmarks/interactive_benchmark_explorer.ipynb +98 -0
  13. geodesiq-0.1.1/benchmarks/interactive_benchmark_plot_selector.py +749 -0
  14. geodesiq-0.1.1/benchmarks/results/README.md +11 -0
  15. geodesiq-0.1.1/benchmarks/results/benchmark_history.parquet +0 -0
  16. geodesiq-0.1.1/benchmarks/results/benchmark_history.parquet.lock +0 -0
  17. geodesiq-0.1.1/benchmarks/run_benchmarks.py +410 -0
  18. geodesiq-0.1.1/dev/BoundaryCondition.ipynb +199 -0
  19. geodesiq-0.1.1/dev/ComplexHamiltonian.ipynb +198 -0
  20. geodesiq-0.1.1/dev/DiabaticEvolution.ipynb +343 -0
  21. geodesiq-0.1.1/dev/DynamicsTrial.ipynb +521 -0
  22. geodesiq-0.1.1/dev/Fidelity4ls.ipynb +490 -0
  23. geodesiq-0.1.1/dev/Flags.ipynb +134 -0
  24. geodesiq-0.1.1/dev/LZ_adiabatic.ipynb +242 -0
  25. geodesiq-0.1.1/dev/PlotTensor.ipynb +302 -0
  26. geodesiq-0.1.1/dev/PulseClassMethods.ipynb +413 -0
  27. geodesiq-0.1.1/dev/bump_version.py +175 -0
  28. geodesiq-0.1.1/dev/pulse_data.csv +1001 -0
  29. geodesiq-0.1.1/dev/pulse_data.npy +0 -0
  30. geodesiq-0.1.1/dev/pulse_data.txt +1001 -0
  31. geodesiq-0.1.1/docs/api.md +43 -0
  32. geodesiq-0.1.1/examples/dqd_model.ipynb +539 -0
  33. geodesiq-0.1.1/examples/landau_zener.ipynb +485 -0
  34. geodesiq-0.1.1/examples/many_body.ipynb +462 -0
  35. geodesiq-0.1.1/images/geodesiq_logo.png +0 -0
  36. geodesiq-0.1.1/images/geodesiq_logo.svg +21 -0
  37. geodesiq-0.1.1/pyproject.toml +124 -0
  38. geodesiq-0.1.1/src/geodesiq/__init__.py +17 -0
  39. geodesiq-0.1.1/src/geodesiq/_meta.py +3 -0
  40. geodesiq-0.1.1/src/geodesiq/_utils.py +182 -0
  41. geodesiq-0.1.1/src/geodesiq/about.py +60 -0
  42. geodesiq-0.1.1/src/geodesiq/controlmodel.py +1177 -0
  43. geodesiq-0.1.1/src/geodesiq/dynamics.py +181 -0
  44. geodesiq-0.1.1/src/geodesiq/exceptions.py +51 -0
  45. geodesiq-0.1.1/src/geodesiq/pulses.py +321 -0
  46. geodesiq-0.1.1/src/geodesiq/py.typed +0 -0
  47. geodesiq-0.1.1/src/geodesiq/warnings.py +22 -0
  48. geodesiq-0.1.1/tests/test_about.py +34 -0
  49. geodesiq-0.1.1/tests/test_bump_version.py +58 -0
  50. geodesiq-0.1.1/tests/test_dynamics.py +242 -0
  51. geodesiq-0.1.1/tests/test_exceptions.py +15 -0
  52. geodesiq-0.1.1/tests/test_flags.py +254 -0
  53. geodesiq-0.1.1/tests/test_model.py +1075 -0
  54. geodesiq-0.1.1/tests/test_pulses.py +302 -0
  55. geodesiq-0.1.1/tests/test_regressions.py +134 -0
  56. geodesiq-0.1.1/tests/test_utils.py +23 -0
  57. geodesiq-0.1.1/tests/test_warnings.py +18 -0
@@ -0,0 +1,162 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ dev, main ]
6
+
7
+ pull_request:
8
+ branches: [ main ]
9
+ types: [ opened, synchronize, reopened, ready_for_review ]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ concurrency:
15
+ group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ validate-pr-source:
20
+ name: Only dev may target main
21
+ if: github.event_name == 'pull_request'
22
+ runs-on: ubuntu-latest
23
+
24
+ steps:
25
+ - name: Validate source branch
26
+ env:
27
+ HEAD_BRANCH: ${{ github.head_ref }}
28
+ run: |
29
+ if [ "$HEAD_BRANCH" != "dev" ]; then
30
+ echo "Pull requests to main must come from dev, not $HEAD_BRANCH."
31
+ exit 1
32
+ fi
33
+
34
+ quality:
35
+ name: Lint and type check
36
+ runs-on: ubuntu-latest
37
+
38
+ steps:
39
+ - uses: actions/checkout@v7
40
+
41
+ - uses: actions/setup-python@v6
42
+ with:
43
+ python-version: "3.14"
44
+
45
+ - name: Install uv
46
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
47
+ with:
48
+ enable-cache: true
49
+
50
+ - name: Sync environment
51
+ run: uv sync --only-group lint
52
+
53
+ - name: Lint
54
+ run: uv run ruff check .
55
+
56
+ - name: Type check
57
+ run: uv run mypy src
58
+
59
+ # - name: Check formatting
60
+ # run: uv run ruff format --check .
61
+
62
+ quick-test:
63
+ name: Quick tests
64
+ if: github.event_name == 'push'
65
+ runs-on: ubuntu-latest
66
+
67
+ steps:
68
+ - uses: actions/checkout@v7
69
+
70
+ - uses: actions/setup-python@v6
71
+ with:
72
+ python-version: "3.14"
73
+
74
+ - name: Install uv
75
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
76
+ with:
77
+ enable-cache: true
78
+
79
+ - name: Sync environment
80
+ run: uv sync --only-group test
81
+
82
+ - name: Run tests
83
+ run: uv run pytest -q
84
+
85
+ compatibility-tests:
86
+ name: ${{ matrix.os }} / Python ${{ matrix.python-version }}
87
+ if: github.event_name == 'pull_request'
88
+ needs: validate-pr-source
89
+ runs-on: ${{ matrix.os }}
90
+
91
+ strategy:
92
+ fail-fast: false
93
+ matrix:
94
+ os: [ ubuntu-latest, macos-latest, windows-latest ]
95
+ python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
96
+
97
+ steps:
98
+ - uses: actions/checkout@v7
99
+
100
+ - uses: actions/setup-python@v6
101
+ with:
102
+ python-version: ${{ matrix.python-version }}
103
+
104
+ - name: Install uv
105
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
106
+ with:
107
+ enable-cache: true
108
+ cache-suffix: ${{ matrix.os }}-py${{ matrix.python-version }}
109
+
110
+ - name: Sync environment
111
+ run: uv sync --only-group test
112
+
113
+ - name: Run full test suite
114
+ run: uv run pytest
115
+
116
+ build-package:
117
+ name: Build package
118
+ if: github.event_name == 'pull_request'
119
+ needs: validate-pr-source
120
+ runs-on: ubuntu-latest
121
+
122
+ steps:
123
+ - uses: actions/checkout@v7
124
+
125
+ - uses: actions/setup-python@v6
126
+ with:
127
+ python-version: "3.14"
128
+
129
+ - name: Install uv
130
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
131
+ with:
132
+ enable-cache: true
133
+
134
+ - name: Sync environment
135
+ run: uv sync --only-group build
136
+
137
+ - name: Build distributions
138
+ run: uv run python -m build
139
+
140
+ - name: Check distributions
141
+ run: uv run twine check --strict dist/*
142
+
143
+ pr-gate:
144
+ name: PR gate
145
+ if: always() && github.event_name == 'pull_request'
146
+ needs: [ validate-pr-source, quality, compatibility-tests, build-package ]
147
+ runs-on: ubuntu-latest
148
+
149
+ steps:
150
+ - name: Verify all required checks passed
151
+ env:
152
+ SOURCE_RESULT: ${{ needs.validate-pr-source.result }}
153
+ QUALITY_RESULT: ${{ needs.quality.result }}
154
+ TEST_RESULT: ${{ needs.compatibility-tests.result }}
155
+ BUILD_RESULT: ${{ needs.build-package.result }}
156
+ run: |
157
+ for result in "$SOURCE_RESULT" "$QUALITY_RESULT" "$TEST_RESULT" "$BUILD_RESULT"; do
158
+ if [ "$result" != "success" ]; then
159
+ echo "A required PR job did not succeed: $result"
160
+ exit 1
161
+ fi
162
+ done
@@ -0,0 +1,101 @@
1
+ name: Publish
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows: [ "Release" ]
6
+ types: [ completed ]
7
+ branches: [ main ]
8
+
9
+ permissions: { }
10
+
11
+ concurrency:
12
+ group: publish-pypi
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ build:
17
+ if: >-
18
+ github.event.workflow_run.conclusion == 'success' &&
19
+ github.event.workflow_run.head_branch == 'main'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+
25
+ steps:
26
+ - uses: actions/checkout@v7
27
+ with:
28
+ ref: ${{ github.event.workflow_run.head_sha }}
29
+ fetch-depth: 0
30
+
31
+ - uses: actions/setup-python@v6
32
+ with:
33
+ python-version: "3.10"
34
+
35
+ - name: Install uv
36
+ uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
37
+ with:
38
+ enable-cache: true
39
+
40
+ - name: Sync build environment
41
+ run: uv sync --only-group build
42
+
43
+ - name: Verify the GitHub release exists for this commit
44
+ env:
45
+ GH_TOKEN: ${{ github.token }}
46
+ EXPECTED_SHA: ${{ github.event.workflow_run.head_sha }}
47
+ run: |
48
+ VERSION=$(python - <<'PY'
49
+ import pathlib
50
+ import re
51
+
52
+ content = pathlib.Path("src/geodesiq/_meta.py").read_text(encoding="utf-8")
53
+ match = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', content)
54
+ if not match:
55
+ raise SystemExit("Could not find package version")
56
+ print(match.group(1))
57
+ PY
58
+ )
59
+
60
+ TAG="v${VERSION}"
61
+ git fetch --tags origin
62
+ TAG_SHA=$(git rev-list -n 1 "$TAG")
63
+
64
+ if [ "$TAG_SHA" != "$EXPECTED_SHA" ]; then
65
+ echo "Tag $TAG points to $TAG_SHA, expected $EXPECTED_SHA."
66
+ exit 1
67
+ fi
68
+
69
+ gh release view "$TAG" >/dev/null
70
+
71
+ - name: Build distributions
72
+ run: uv run python -m build
73
+
74
+ - name: Check distributions
75
+ run: uv run twine check --strict dist/*
76
+
77
+ - name: Upload distributions
78
+ uses: actions/upload-artifact@v4
79
+ with:
80
+ name: python-distributions
81
+ path: dist/
82
+ if-no-files-found: error
83
+
84
+ publish:
85
+ name: Publish to PyPI
86
+ needs: build
87
+ runs-on: ubuntu-latest
88
+ environment: pypi
89
+ permissions:
90
+ contents: read
91
+ id-token: write
92
+
93
+ steps:
94
+ - name: Download distributions
95
+ uses: actions/download-artifact@v5
96
+ with:
97
+ name: python-distributions
98
+ path: dist/
99
+
100
+ - name: Publish to PyPI
101
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,125 @@
1
+ name: Release
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows: [ "CI" ]
6
+ types: [ completed ]
7
+ branches: [ main ]
8
+
9
+ permissions: { }
10
+
11
+ concurrency:
12
+ group: release-main
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ release:
17
+ if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' && github.event.workflow_run.head_branch == 'main' }}
18
+ runs-on: ubuntu-latest
19
+ permissions:
20
+ contents: write
21
+
22
+ steps:
23
+ - uses: actions/checkout@v7
24
+ with:
25
+ ref: ${{ github.event.workflow_run.head_sha }}
26
+ fetch-depth: 0
27
+
28
+ - uses: actions/setup-python@v6
29
+ with:
30
+ python-version: "3.14"
31
+
32
+ - name: Read version from package
33
+ id: version
34
+ run: |
35
+ python - <<'PY'
36
+ import os
37
+ import pathlib
38
+ import re
39
+
40
+ meta_file = pathlib.Path("src/geodesiq/_meta.py")
41
+ content = meta_file.read_text(encoding="utf-8")
42
+
43
+ match = re.search(
44
+ r'__version__\s*=\s*["\']([^"\']+)["\']',
45
+ content,
46
+ )
47
+
48
+ if not match:
49
+ raise SystemExit(
50
+ "Could not find __version__ in src/geodesiq/_meta.py"
51
+ )
52
+
53
+ version = match.group(1)
54
+
55
+ with open(
56
+ os.environ["GITHUB_OUTPUT"],
57
+ "a",
58
+ encoding="utf-8",
59
+ ) as output:
60
+ output.write(f"version={version}\n")
61
+ output.write(f"tag=v{version}\n")
62
+ PY
63
+
64
+ - name: Fail if tag already exists
65
+ env:
66
+ TAG: ${{ steps.version.outputs.tag }}
67
+ run: |
68
+ git fetch --tags origin
69
+
70
+ if git ls-remote \
71
+ --exit-code \
72
+ --tags origin \
73
+ "refs/tags/${TAG}" >/dev/null 2>&1
74
+ then
75
+ echo "Tag ${TAG} already exists."
76
+ echo "Bump __version__ before merging to main."
77
+ exit 1
78
+ fi
79
+
80
+ - name: Extract release notes from changelog
81
+ env:
82
+ VERSION: ${{ steps.version.outputs.version }}
83
+ run: |
84
+ python - <<'PY'
85
+ import os
86
+ import pathlib
87
+ import re
88
+
89
+ version = os.environ["VERSION"]
90
+
91
+ changelog = pathlib.Path("CHANGELOG.md").read_text(
92
+ encoding="utf-8"
93
+ )
94
+
95
+ pattern = re.compile(
96
+ rf"^## \[{re.escape(version)}\][^\n]*\n"
97
+ rf"(?P<body>.*?)(?=^## \[|\Z)",
98
+ re.MULTILINE | re.DOTALL,
99
+ )
100
+
101
+ match = pattern.search(changelog)
102
+
103
+ if not match:
104
+ raise SystemExit(
105
+ f"Could not find CHANGELOG entry for version {version}"
106
+ )
107
+
108
+ notes = match.group("body").strip()
109
+
110
+ pathlib.Path("release_notes.md").write_text(
111
+ notes + "\n",
112
+ encoding="utf-8",
113
+ )
114
+ PY
115
+
116
+ - name: Create GitHub release and tag
117
+ env:
118
+ GH_TOKEN: ${{ github.token }}
119
+ TAG: ${{ steps.version.outputs.tag }}
120
+ SHA: ${{ github.event.workflow_run.head_sha }}
121
+ run: |
122
+ gh release create "$TAG" \
123
+ --target "$SHA" \
124
+ --title "$TAG" \
125
+ --notes-file release_notes.md
@@ -0,0 +1,218 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
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
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+ #poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ #pdm.lock
116
+ #pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ #pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # SageMath parsed files
135
+ *.sage.py
136
+
137
+ # Environments
138
+ .env
139
+ .envrc
140
+ .venv
141
+ env/
142
+ venv/
143
+ ENV/
144
+ env.bak/
145
+ venv.bak/
146
+
147
+ # Spyder project settings
148
+ .spyderproject
149
+ .spyproject
150
+
151
+ # Rope project settings
152
+ .ropeproject
153
+
154
+ # mkdocs documentation
155
+ /site
156
+
157
+ # mypy
158
+ .mypy_cache/
159
+ .dmypy.json
160
+ dmypy.json
161
+
162
+ # Pyre type checker
163
+ .pyre/
164
+
165
+ # pytype static type analyzer
166
+ .pytype/
167
+
168
+ # Cython debug symbols
169
+ cython_debug/
170
+
171
+ # PyCharm
172
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
175
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
176
+ .idea/
177
+
178
+ # Abstra
179
+ # Abstra is an AI-powered process automation framework.
180
+ # Ignore directories containing user credentials, local state, and settings.
181
+ # Learn more at https://abstra.io/docs
182
+ .abstra/
183
+
184
+ # Visual Studio Code
185
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
+ # you could uncomment the following to ignore the entire vscode folder
189
+ .vscode/
190
+
191
+ # Ruff stuff:
192
+ .ruff_cache/
193
+
194
+ # PyPI configuration file
195
+ .pypirc
196
+
197
+ # Cursor
198
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
+ # refer to https://docs.cursor.com/context/ignore-files
201
+ .cursorignore
202
+ .cursorindexingignore
203
+
204
+ # Marimo
205
+ marimo/_static/
206
+ marimo/_lsp/
207
+ __marimo__/
208
+
209
+ # uv files
210
+ uv.lock
211
+
212
+ # JupyterLab
213
+ .jupyterlab
214
+
215
+ # MacOS
216
+ .DS_Store
217
+
218
+ */.coverage
@@ -0,0 +1,21 @@
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 and the project follows Semantic Versioning.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.1] - 2026-07-10
10
+
11
+ ### Fixed
12
+
13
+ - `hbar` validation was too strict.
14
+ - Fix CI to publish the release
15
+
16
+ ## [0.1.0] - 2026-06-19
17
+
18
+ ### Added
19
+
20
+ - Initial release of the project. This version includes the basic functionality and features as outlined in the project
21
+ proposal.
@@ -0,0 +1,70 @@
1
+ # Contributing
2
+
3
+ Thanks for contributing to `geodesiq`.
4
+
5
+ ## Development setup
6
+
7
+ 1. Create a branch from `dev`.
8
+ 2. Commit your changes there.
9
+ 3. Open a pull request into `dev`.
10
+ 4. Once `dev` is stable, maintainers open a pull request from `dev` into `main`.
11
+
12
+ Direct pushes to `main` are not allowed.
13
+ Only `dev` is merged into `main` (no feature branch PRs directly into `main`).
14
+
15
+ Automation flow:
16
+ - CI runs on pushes to `dev` and PRs targeting `dev`.
17
+ - Release runs only when a PR from `dev` into `main` is merged.
18
+ - Publish runs only after a successful `Release` workflow from `main`.
19
+
20
+ To recreate the development environment, run:
21
+ ```bash
22
+ uv sync --group dev
23
+ ```
24
+
25
+ If you do not use `uv`, create a virtual environment and install equivalent dev dependencies from `pyproject.toml`.
26
+
27
+ ## Run quality checks
28
+
29
+ ```bash
30
+ uv run pytest
31
+ uv run ruff check .
32
+ uv run mypy
33
+ uv run python -m build
34
+ uv run python -m twine check dist/*
35
+ ```
36
+
37
+ ## Pull request guidelines
38
+
39
+ - Keep PRs focused and small when possible.
40
+ - Add or update tests for behavior changes.
41
+ - Update `README.md` and `CHANGELOG.md` when user-facing behavior changes.
42
+ - Ensure all checks pass before requesting review.
43
+
44
+ ## Release notes
45
+
46
+ - Add entries to the `[Unreleased]` section in `CHANGELOG.md`.
47
+ - At release time, move those entries under a versioned heading.
48
+
49
+ ## Bumping the version
50
+
51
+ Use the `dev/bump_version.py` script to update the version consistently across all project files (`src/geodesiq/_meta.py` and `CHANGELOG.md`).
52
+
53
+ **Bump by increment type:**
54
+ ```bash
55
+ python dev/bump_version.py --patch # e.g. 0.1.0 → 0.1.1
56
+ python dev/bump_version.py --minor # e.g. 0.1.1 → 0.2.0
57
+ python dev/bump_version.py --major # e.g. 0.2.0 → 1.0.0
58
+ ```
59
+
60
+ **Set an explicit version:**
61
+ ```bash
62
+ python dev/bump_version.py 1.2.3
63
+ ```
64
+
65
+ The script accepts PEP 440 versions, rejects non-increasing versions, validates the changelog, supports dry runs, and updates `_meta.py` and `CHANGELOG.md` with rollback protection.
66
+
67
+ After the version bump is merged into `main`, create and push the matching tag:
68
+
69
+ After running the script, commit the changes, push to `dev`, and open a pull request into `main` to trigger the release workflow.
70
+