django-phase 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 (55) hide show
  1. django_phase-0.1.0/.ambient-package-update/metadata.py +45 -0
  2. django_phase-0.1.0/.ambient-package-update/templates/snippets/content.tpl +46 -0
  3. django_phase-0.1.0/.ambient-package-update/templates/snippets/tagline.tpl +2 -0
  4. django_phase-0.1.0/.editorconfig +17 -0
  5. django_phase-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +34 -0
  6. django_phase-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  7. django_phase-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  8. django_phase-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +20 -0
  9. django_phase-0.1.0/.github/workflows/ci.yml +11 -0
  10. django_phase-0.1.0/.github/workflows/quality-gate.yml +94 -0
  11. django_phase-0.1.0/.github/workflows/release.yml +136 -0
  12. django_phase-0.1.0/.gitignore +165 -0
  13. django_phase-0.1.0/.pre-commit-config.yaml +60 -0
  14. django_phase-0.1.0/.readthedocs.yaml +33 -0
  15. django_phase-0.1.0/CHANGES.md +11 -0
  16. django_phase-0.1.0/CODE_OF_CONDUCT.md +132 -0
  17. django_phase-0.1.0/CONTRIBUTING.md +57 -0
  18. django_phase-0.1.0/LICENSE.md +21 -0
  19. django_phase-0.1.0/MANIFEST.in +4 -0
  20. django_phase-0.1.0/PKG-INFO +188 -0
  21. django_phase-0.1.0/README.md +122 -0
  22. django_phase-0.1.0/SECURITY.md +18 -0
  23. django_phase-0.1.0/docs/Makefile +20 -0
  24. django_phase-0.1.0/docs/conf.py +76 -0
  25. django_phase-0.1.0/docs/features/changelog.rst +1 -0
  26. django_phase-0.1.0/docs/features/motivation.md +74 -0
  27. django_phase-0.1.0/docs/features/refused_actions.md +75 -0
  28. django_phase-0.1.0/docs/features/setup.md +15 -0
  29. django_phase-0.1.0/docs/features/usage.md +135 -0
  30. django_phase-0.1.0/docs/index.rst +20 -0
  31. django_phase-0.1.0/docs/make.bat +35 -0
  32. django_phase-0.1.0/manage.py +23 -0
  33. django_phase-0.1.0/phase/__init__.py +3 -0
  34. django_phase-0.1.0/phase/apps.py +9 -0
  35. django_phase-0.1.0/phase/checks.py +57 -0
  36. django_phase-0.1.0/phase/exceptions.py +96 -0
  37. django_phase-0.1.0/phase/fields.py +174 -0
  38. django_phase-0.1.0/phase/mixins/__init__.py +0 -0
  39. django_phase-0.1.0/phase/mixins/phase_guard.py +64 -0
  40. django_phase-0.1.0/phase/transitions.py +16 -0
  41. django_phase-0.1.0/pyproject.toml +278 -0
  42. django_phase-0.1.0/scripts/unix/install_requirements.sh +3 -0
  43. django_phase-0.1.0/scripts/unix/publish_to_pypi.sh +4 -0
  44. django_phase-0.1.0/scripts/windows/install_requirements.ps1 +2 -0
  45. django_phase-0.1.0/scripts/windows/publish_to_pypi.ps1 +3 -0
  46. django_phase-0.1.0/settings.py +20 -0
  47. django_phase-0.1.0/testapp/__init__.py +0 -0
  48. django_phase-0.1.0/testapp/models.py +45 -0
  49. django_phase-0.1.0/tests/__init__.py +0 -0
  50. django_phase-0.1.0/tests/test_checks.py +113 -0
  51. django_phase-0.1.0/tests/test_exceptions.py +97 -0
  52. django_phase-0.1.0/tests/test_fields.py +285 -0
  53. django_phase-0.1.0/tests/test_phase_guard.py +144 -0
  54. django_phase-0.1.0/tests/test_signals.py +112 -0
  55. django_phase-0.1.0/tests/test_transitions.py +39 -0
@@ -0,0 +1,45 @@
1
+ from ambient_package_update.metadata.author import PackageAuthor
2
+ from ambient_package_update.metadata.constants import (
3
+ DEPLOYMENT_STATUS_BETA,
4
+ DEV_DEPENDENCIES,
5
+ LICENSE_MIT,
6
+ SUPPORTED_DJANGO_VERSIONS,
7
+ SUPPORTED_PYTHON_VERSIONS,
8
+ )
9
+ from ambient_package_update.metadata.maintainer import PackageMaintainer
10
+ from ambient_package_update.metadata.package import PackageMetadata
11
+ from ambient_package_update.metadata.readme import ReadmeContent
12
+
13
+ METADATA = PackageMetadata(
14
+ package_name="django_phase",
15
+ module_name="phase",
16
+ github_package_group="beyonder-deutschland",
17
+ authors=[
18
+ PackageAuthor(
19
+ name="Beyonder Deutschland",
20
+ email="hello@beyonder.de",
21
+ ),
22
+ ],
23
+ maintainer=PackageMaintainer(name="Beyonder Deutschland", url="https://beyonder.de/", email="hello@beyonder.de"),
24
+ licenser="Beyonder Deutschland GmbH",
25
+ license=LICENSE_MIT,
26
+ license_year=2026,
27
+ development_status=DEPLOYMENT_STATUS_BETA,
28
+ has_migrations=False,
29
+ main_branch="main",
30
+ claim=(
31
+ "Race-safe state machines for Django models: a protected PhaseField and transitions as one conditional UPDATE"
32
+ ),
33
+ readme_content=ReadmeContent(uses_internationalisation=False),
34
+ dependencies=[
35
+ f"Django>={SUPPORTED_DJANGO_VERSIONS[0]}",
36
+ ],
37
+ supported_django_versions=SUPPORTED_DJANGO_VERSIONS,
38
+ supported_python_versions=SUPPORTED_PYTHON_VERSIONS,
39
+ optional_dependencies={
40
+ "dev": [
41
+ *DEV_DEPENDENCIES,
42
+ ],
43
+ },
44
+ ruff_ignore_list=[],
45
+ )
@@ -0,0 +1,46 @@
1
+ ## Features
2
+
3
+ * Declare the allowed transitions once, as a table on the field
4
+ * Assigning the phase directly raises; only `move()` changes it
5
+ * `move()` writes phase and further fields in **one** conditional `UPDATE`, so of two concurrent transitions from the
6
+ same phase exactly one succeeds
7
+ * Every `save()` is guarded against a stale phase, so it can't silently undo a concurrent transition
8
+ * Migrations see a plain `CharField` and never import `phase`
9
+ * System checks catch a missing mixin, a second phase field or one inherited from a concrete parent model
10
+ * `PhaseGuardError` gives refused actions a stable `code` for machines and a `detail` for humans
11
+ * Overrides no private Django method
12
+
13
+ ```python
14
+ from django.db import models
15
+ from django.utils import timezone
16
+
17
+ from phase.fields import PhaseField
18
+ from phase.mixins.phase_guard import PhaseGuardMixin
19
+ from phase.transitions import move
20
+
21
+
22
+ class Order(PhaseGuardMixin, models.Model):
23
+ class Status(models.TextChoices):
24
+ OPEN = "open"
25
+ PAID = "paid"
26
+ SHIPPED = "shipped"
27
+ CANCELLED = "cancelled"
28
+
29
+ status = PhaseField(
30
+ max_length=10,
31
+ choices=Status.choices,
32
+ default=Status.OPEN,
33
+ transitions={
34
+ Status.OPEN: (Status.PAID, Status.CANCELLED),
35
+ Status.PAID: (Status.SHIPPED,),
36
+ },
37
+ )
38
+ paid_at = models.DateTimeField(null=True, blank=True)
39
+
40
+
41
+ order = Order.objects.create()
42
+ move(obj=order, to=Order.Status.PAID, paid_at=timezone.now())
43
+
44
+ order.status = Order.Status.OPEN # raises ProtectedPhaseFieldError
45
+ move(obj=order, to=Order.Status.OPEN) # raises IllegalPhaseTransitionError
46
+ ```
@@ -0,0 +1,2 @@
1
+ Race-safe state machines for Django models: a protected `PhaseField`, transitions as one conditional `UPDATE`, and
2
+ guards that tell humans and machines why an action was refused.
@@ -0,0 +1,17 @@
1
+ # http://editorconfig.org
2
+
3
+ root = true
4
+
5
+ [*]
6
+ charset = utf-8
7
+ end_of_line = lf
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.{py,rst,ini}]
12
+ indent_style = space
13
+ indent_size = 4
14
+
15
+ [*.yml]
16
+ indent_style = space
17
+ indent_size = 2
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report a problem to help us improve
4
+ title: ''
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Describe the bug
10
+
11
+ A clear and concise description of what the bug is.
12
+
13
+ ## To reproduce
14
+
15
+ Steps to reproduce the behavior:
16
+
17
+ 1. ...
18
+ 2. ...
19
+ 3. ...
20
+
21
+ ## Expected behavior
22
+
23
+ A clear and concise description of what you expected to happen.
24
+
25
+ ## Environment
26
+
27
+ - `django-phase` version:
28
+ - Python version:
29
+ - Django version:
30
+ - Operating system:
31
+
32
+ ## Additional context
33
+
34
+ Add any other context, tracebacks, or screenshots about the problem here.
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Security vulnerability
4
+ url: https://github.com/beyonder-deutschland/django-phase/security/advisories/new
5
+ about: Please report security issues privately via a security advisory, not as a public issue.
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Is your feature request related to a problem?
10
+
11
+ A clear and concise description of what the problem is. Ex. I'm always
12
+ frustrated when [...]
13
+
14
+ ## Describe the solution you'd like
15
+
16
+ A clear and concise description of what you want to happen.
17
+
18
+ ## Describe alternatives you've considered
19
+
20
+ A clear and concise description of any alternative solutions or features you've
21
+ considered.
22
+
23
+ ## Additional context
24
+
25
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,20 @@
1
+ ## Description
2
+
3
+ Please include a summary of the change and which issue is fixed (if any).
4
+
5
+ Fixes #(issue)
6
+
7
+ ## Type of change
8
+
9
+ - [ ] Bug fix (non-breaking change which fixes an issue)
10
+ - [ ] New feature (non-breaking change which adds functionality)
11
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
12
+ - [ ] Documentation update
13
+
14
+ ## Checklist
15
+
16
+ - [ ] My code follows the style guidelines of this project (linting passes)
17
+ - [ ] I have added tests that prove my fix is effective or that my feature works
18
+ - [ ] I have updated the documentation where necessary
19
+ - [ ] I have added an entry to `CHANGES.md`
20
+ - [ ] I have bumped the version in `phase/__init__.py`
@@ -0,0 +1,11 @@
1
+ name: Unit tests
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ jobs:
10
+ ci:
11
+ uses: ./.github/workflows/quality-gate.yml
@@ -0,0 +1,94 @@
1
+ name: CI jobs
2
+
3
+ on:
4
+ workflow_call:
5
+
6
+ jobs:
7
+ linting:
8
+ runs-on: ubuntu-24.04
9
+ steps:
10
+ - uses: actions/checkout@v7
11
+
12
+ - name: Set up Python 3.15
13
+ uses: actions/setup-python@v7
14
+ with:
15
+ python-version: "3.15"
16
+
17
+ - name: Install required packages
18
+ run: pip install pre-commit
19
+
20
+ - name: Run pre-commit hooks
21
+ run: pre-commit run --all-files
22
+
23
+ tests:
24
+ name: Python ${{ matrix.python-version }}, django ${{ matrix.django-version }}
25
+ runs-on: ubuntu-24.04
26
+ strategy:
27
+ matrix:
28
+ python-version: ['3.11', '3.12', '3.13', '3.14', '3.15', ]
29
+ django-version: ['52', '60', '61', ]
30
+
31
+ # Exclude Python/Django combinations that are not supported upstream.
32
+ exclude:
33
+ - python-version: '3.15'
34
+ django-version: 52
35
+ - python-version: '3.11'
36
+ django-version: 60
37
+ - python-version: '3.15'
38
+ django-version: 60
39
+ - python-version: '3.11'
40
+ django-version: 61
41
+
42
+ steps:
43
+ - uses: actions/checkout@v7
44
+ - name: setup python
45
+ uses: actions/setup-python@v7
46
+ with:
47
+ python-version: ${{ matrix.python-version }}
48
+ - name: Install uv
49
+ uses: astral-sh/setup-uv@v10.3.0
50
+ with:
51
+ cache-suffix: ${{ github.ref_type }}
52
+ - name: Install tox
53
+ run: uv pip install --system tox tox-uv
54
+ - name: Run Tests
55
+ env:
56
+ TOXENV: django${{ matrix.django-version }}
57
+ run: tox
58
+ - name: Upload coverage data
59
+ uses: actions/upload-artifact@v7
60
+ with:
61
+ name: coverage-data-${{ matrix.python-version }}-${{ matrix.django-version }}
62
+ path: '${{ github.workspace }}/.coverage'
63
+ include-hidden-files: true
64
+ if-no-files-found: error
65
+
66
+ coverage:
67
+ name: Coverage
68
+ runs-on: ubuntu-24.04
69
+ needs: tests
70
+ steps:
71
+ - uses: actions/checkout@v7
72
+
73
+ - uses: actions/setup-python@v7
74
+ with:
75
+ python-version: '3.15'
76
+
77
+ - name: Install dependencies
78
+ run: python -m pip install --upgrade coverage[toml]
79
+
80
+ - name: Download data
81
+ uses: actions/download-artifact@v8
82
+ with:
83
+ path: ${{ github.workspace }}/coverage-reports
84
+ pattern: coverage-data-*
85
+ merge-multiple: false
86
+
87
+ - name: Combine coverage and fail if it's <100.0%
88
+ run: |
89
+ python -m coverage combine coverage-reports/*/.coverage
90
+ python -m coverage xml
91
+ python -m coverage html --skip-covered --skip-empty
92
+ python -m coverage report --fail-under=100.0
93
+ echo "## Coverage summary" >> $GITHUB_STEP_SUMMARY
94
+ python -m coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
@@ -0,0 +1,136 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ # Restrictive default — each job declares only what it needs
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ ci:
14
+ uses: ./.github/workflows/quality-gate.yml
15
+
16
+ check-branch:
17
+ name: Verify tag is on main
18
+ runs-on: ubuntu-24.04
19
+ outputs:
20
+ on-main: ${{ steps.check.outputs.on-main }}
21
+ steps:
22
+ - uses: actions/checkout@v7
23
+ with:
24
+ fetch-depth: 0
25
+ - name: Check if tag is on main
26
+ id: check
27
+ run: |
28
+ git fetch origin main
29
+ if git merge-base --is-ancestor "${{ github.sha }}" origin/main; then
30
+ echo "on-main=true" >> $GITHUB_OUTPUT
31
+ else
32
+ echo "Tag is not on main, skipping release." >&2
33
+ echo "on-main=false" >> $GITHUB_OUTPUT
34
+ fi
35
+
36
+ build:
37
+ name: Build distribution packages
38
+ runs-on: ubuntu-24.04
39
+ needs: [ci, check-branch]
40
+ if: needs.check-branch.outputs.on-main == 'true'
41
+ permissions:
42
+ contents: read
43
+ steps:
44
+ - uses: actions/checkout@v7
45
+
46
+ - name: Set up Python 3.15
47
+ uses: actions/setup-python@v7
48
+ with:
49
+ python-version: "3.15"
50
+
51
+ - name: Install uv
52
+ uses: astral-sh/setup-uv@v10.3.0
53
+
54
+ - name: Build packages
55
+ run: uv build
56
+
57
+ - name: Upload distribution packages
58
+ uses: actions/upload-artifact@v7
59
+ with:
60
+ name: dist
61
+ path: dist/
62
+ if-no-files-found: error
63
+
64
+ sign:
65
+ name: Sign distribution packages
66
+ runs-on: ubuntu-24.04
67
+ needs: build
68
+ permissions:
69
+ id-token: write # required for Sigstore OIDC signing
70
+ contents: read
71
+ steps:
72
+ - name: Download distribution packages
73
+ uses: actions/download-artifact@v8
74
+ with:
75
+ name: dist
76
+ path: dist/
77
+
78
+ - name: Sign packages with Sigstore
79
+ uses: sigstore/gh-action-sigstore-python@v3.5.0
80
+ with:
81
+ inputs: >-
82
+ ./dist/*.tar.gz
83
+ ./dist/*.whl
84
+
85
+ - name: Upload signed distribution packages
86
+ uses: actions/upload-artifact@v7
87
+ with:
88
+ name: dist-signed
89
+ path: dist/
90
+ if-no-files-found: error
91
+
92
+ github-release:
93
+ name: Create GitHub Release
94
+ runs-on: ubuntu-24.04
95
+ needs: sign
96
+ permissions:
97
+ contents: write # required to create GitHub releases
98
+ steps:
99
+ - name: Download signed distribution packages
100
+ uses: actions/download-artifact@v8
101
+ with:
102
+ name: dist-signed
103
+ path: dist/
104
+
105
+ - name: Create GitHub Release
106
+ env:
107
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
108
+ run: |
109
+ shopt -s failglob
110
+ gh release create "${{ github.ref_name }}" \
111
+ --repo "${{ github.repository }}" \
112
+ --generate-notes \
113
+ dist/*
114
+
115
+ publish-pypi:
116
+ name: Publish to PyPI
117
+ runs-on: ubuntu-24.04
118
+ needs: sign
119
+ environment: pypi
120
+ permissions:
121
+ id-token: write # required for PyPI Trusted Publisher OIDC auth
122
+ contents: read
123
+ steps:
124
+ - name: Download signed distribution packages
125
+ uses: actions/download-artifact@v8
126
+ with:
127
+ name: dist-signed
128
+ path: dist/
129
+
130
+ - name: Remove Sigstore bundles (PyPI only accepts .whl and .tar.gz)
131
+ run: rm dist/*.sigstore.json
132
+
133
+ - name: Publish to PyPI
134
+ uses: pypa/gh-action-pypi-publish@release/v1
135
+ # Sigstore attestations are generated and uploaded to PyPI automatically
136
+ # when using Trusted Publishing — no extra configuration needed.
@@ -0,0 +1,165 @@
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
+ # 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
+ *.pot
56
+
57
+ # Django stuff:
58
+ *.log
59
+ local_settings.py
60
+ db.sqlite3
61
+ db.sqlite3-journal
62
+
63
+ # Flask stuff:
64
+ instance/
65
+ .webassets-cache
66
+
67
+ # Scrapy stuff:
68
+ .scrapy
69
+
70
+ # Sphinx documentation
71
+ docs/_build/
72
+
73
+ # PyBuilder
74
+ .pybuilder/
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # uv
85
+ # This is a library, so consumers never install from the lockfile. Not committing it avoids
86
+ # lockfile churn in every maintenance release.
87
+ uv.lock
88
+
89
+ # pdm
90
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
91
+ #pdm.lock
92
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
93
+ # in version control.
94
+ # https://pdm.fming.dev/#use-with-ide
95
+ .pdm.toml
96
+
97
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
98
+ __pypackages__/
99
+
100
+ # Celery stuff
101
+ celerybeat-schedule
102
+ celerybeat.pid
103
+
104
+ # SageMath parsed files
105
+ *.sage.py
106
+
107
+ # Environments
108
+ .env
109
+ .venv
110
+ env/
111
+ venv/
112
+ ENV/
113
+ env.bak/
114
+ venv.bak/
115
+
116
+ # Spyder project settings
117
+ .spyderproject
118
+ .spyproject
119
+
120
+ # Rope project settings
121
+ .ropeproject
122
+
123
+ # mkdocs documentation
124
+ /site
125
+
126
+ # mypy
127
+ .mypy_cache/
128
+ .dmypy.json
129
+ dmypy.json
130
+
131
+ # Pyre type checker
132
+ .pyre/
133
+
134
+ # pytype static type analyzer
135
+ .pytype/
136
+
137
+ # Cython debug symbols
138
+ cython_debug/
139
+
140
+ # PyCharm
141
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
142
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
143
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
144
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
145
+ .idea/
146
+
147
+ # Deprecated dependency files
148
+ requirements.txt
149
+
150
+ # sphinx build folder
151
+ _build
152
+
153
+ # Compiled source #
154
+ ###################
155
+ *.com
156
+ *.class
157
+ *.dll
158
+ *.exe
159
+ *.o
160
+
161
+ # Test databases
162
+ *.sqlite
163
+
164
+ # AI
165
+ .claude/
@@ -0,0 +1,60 @@
1
+ # you find the full pre-commit-tools docu under:
2
+ # https://pre-commit.com/
3
+
4
+ repos:
5
+ - repo: https://github.com/astral-sh/ruff-pre-commit
6
+ rev: v0.17.1
7
+ hooks:
8
+ # Run the Ruff formatter.
9
+ - id: ruff-format
10
+ # Run the Ruff linter.
11
+ - id: ruff-check
12
+ args: [--fix, --exit-non-zero-on-fix]
13
+
14
+ - repo: https://github.com/adamchainz/blacken-docs
15
+ rev: 1.20.0
16
+ hooks:
17
+ - id: blacken-docs
18
+ args: [--line-length, "120"]
19
+ additional_dependencies:
20
+ - black==26.10.1
21
+ files: '(?:README\.md|\.ambient-package-update\/templates\/snippets\/.*\.tpl|docs\/.*\.(?:md|rst))'
22
+
23
+ - repo: https://github.com/asottile/pyupgrade
24
+ rev: v3.22.0
25
+ hooks:
26
+ - id: pyupgrade
27
+ args: [ --py311-plus ]
28
+
29
+ - repo: https://github.com/adamchainz/django-upgrade
30
+ rev: 1.33.0
31
+ hooks:
32
+ - id: django-upgrade
33
+ args: [--target-version, "5.2"]
34
+
35
+ - repo: https://github.com/adamchainz/djade-pre-commit
36
+ rev: 1.10.0
37
+ hooks:
38
+ - id: djade
39
+ args: [--target-version, "5.2"]
40
+ exclude: |
41
+ (?x)^(
42
+ charts/.*
43
+ |.*\.py
44
+ )$
45
+
46
+ - repo: https://github.com/pre-commit/pre-commit-hooks
47
+ rev: v6.0.0
48
+ hooks:
49
+ - id: check-ast
50
+ - id: check-builtin-literals
51
+ - id: check-case-conflict
52
+ - id: check-docstring-first
53
+ - id: check-executables-have-shebangs
54
+ - id: check-json
55
+ - id: check-merge-conflict
56
+ - id: check-toml
57
+ - id: end-of-file-fixer
58
+ - id: fix-byte-order-marker
59
+ - id: mixed-line-ending
60
+ - id: trailing-whitespace
@@ -0,0 +1,33 @@
1
+ # .readthedocs.yaml
2
+ # Read the Docs configuration file
3
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4
+
5
+ # Required
6
+ version: 2
7
+
8
+ # Set the OS, Python version and other tools you might need
9
+ build:
10
+ os: ubuntu-24.04
11
+ tools:
12
+ python: "3.14"
13
+
14
+ # Build documentation in the "docs/" directory with Sphinx
15
+ sphinx:
16
+ configuration: docs/conf.py
17
+
18
+ # Optionally build your docs in additional formats such as PDF and ePub
19
+ # formats:
20
+ # - pdf
21
+ # - epub
22
+
23
+ # Optional but recommended, declare the Python requirements required
24
+ # to build your documentation.
25
+ # Read the Docs supports uv natively, so we let it sync the project with the
26
+ # "dev" extra (which contains the documentation dependencies).
27
+ # See https://docs.readthedocs.com/platform/en/stable/config-file/v2.html#python-install
28
+ python:
29
+ install:
30
+ - method: uv
31
+ command: sync
32
+ extras:
33
+ - dev