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.
- django_phase-0.1.0/.ambient-package-update/metadata.py +45 -0
- django_phase-0.1.0/.ambient-package-update/templates/snippets/content.tpl +46 -0
- django_phase-0.1.0/.ambient-package-update/templates/snippets/tagline.tpl +2 -0
- django_phase-0.1.0/.editorconfig +17 -0
- django_phase-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +34 -0
- django_phase-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- django_phase-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
- django_phase-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- django_phase-0.1.0/.github/workflows/ci.yml +11 -0
- django_phase-0.1.0/.github/workflows/quality-gate.yml +94 -0
- django_phase-0.1.0/.github/workflows/release.yml +136 -0
- django_phase-0.1.0/.gitignore +165 -0
- django_phase-0.1.0/.pre-commit-config.yaml +60 -0
- django_phase-0.1.0/.readthedocs.yaml +33 -0
- django_phase-0.1.0/CHANGES.md +11 -0
- django_phase-0.1.0/CODE_OF_CONDUCT.md +132 -0
- django_phase-0.1.0/CONTRIBUTING.md +57 -0
- django_phase-0.1.0/LICENSE.md +21 -0
- django_phase-0.1.0/MANIFEST.in +4 -0
- django_phase-0.1.0/PKG-INFO +188 -0
- django_phase-0.1.0/README.md +122 -0
- django_phase-0.1.0/SECURITY.md +18 -0
- django_phase-0.1.0/docs/Makefile +20 -0
- django_phase-0.1.0/docs/conf.py +76 -0
- django_phase-0.1.0/docs/features/changelog.rst +1 -0
- django_phase-0.1.0/docs/features/motivation.md +74 -0
- django_phase-0.1.0/docs/features/refused_actions.md +75 -0
- django_phase-0.1.0/docs/features/setup.md +15 -0
- django_phase-0.1.0/docs/features/usage.md +135 -0
- django_phase-0.1.0/docs/index.rst +20 -0
- django_phase-0.1.0/docs/make.bat +35 -0
- django_phase-0.1.0/manage.py +23 -0
- django_phase-0.1.0/phase/__init__.py +3 -0
- django_phase-0.1.0/phase/apps.py +9 -0
- django_phase-0.1.0/phase/checks.py +57 -0
- django_phase-0.1.0/phase/exceptions.py +96 -0
- django_phase-0.1.0/phase/fields.py +174 -0
- django_phase-0.1.0/phase/mixins/__init__.py +0 -0
- django_phase-0.1.0/phase/mixins/phase_guard.py +64 -0
- django_phase-0.1.0/phase/transitions.py +16 -0
- django_phase-0.1.0/pyproject.toml +278 -0
- django_phase-0.1.0/scripts/unix/install_requirements.sh +3 -0
- django_phase-0.1.0/scripts/unix/publish_to_pypi.sh +4 -0
- django_phase-0.1.0/scripts/windows/install_requirements.ps1 +2 -0
- django_phase-0.1.0/scripts/windows/publish_to_pypi.ps1 +3 -0
- django_phase-0.1.0/settings.py +20 -0
- django_phase-0.1.0/testapp/__init__.py +0 -0
- django_phase-0.1.0/testapp/models.py +45 -0
- django_phase-0.1.0/tests/__init__.py +0 -0
- django_phase-0.1.0/tests/test_checks.py +113 -0
- django_phase-0.1.0/tests/test_exceptions.py +97 -0
- django_phase-0.1.0/tests/test_fields.py +285 -0
- django_phase-0.1.0/tests/test_phase_guard.py +144 -0
- django_phase-0.1.0/tests/test_signals.py +112 -0
- 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,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,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,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
|