ghome-local-api 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 (34) hide show
  1. ghome_local_api-0.1.0/.editorconfig +12 -0
  2. ghome_local_api-0.1.0/.github/actions/install-deps/action.yml +24 -0
  3. ghome_local_api-0.1.0/.github/dependabot.yml +34 -0
  4. ghome_local_api-0.1.0/.github/labeler.yml +40 -0
  5. ghome_local_api-0.1.0/.github/labels.yml +93 -0
  6. ghome_local_api-0.1.0/.github/release-drafter.yml +55 -0
  7. ghome_local_api-0.1.0/.github/workflows/ci.yml +111 -0
  8. ghome_local_api-0.1.0/.github/workflows/labeler.yml +22 -0
  9. ghome_local_api-0.1.0/.github/workflows/manage-labels.yml +25 -0
  10. ghome_local_api-0.1.0/.github/workflows/publish.yml +68 -0
  11. ghome_local_api-0.1.0/.github/workflows/release-drafter.yml +22 -0
  12. ghome_local_api-0.1.0/.github/zizmor.yml +4 -0
  13. ghome_local_api-0.1.0/.gitignore +17 -0
  14. ghome_local_api-0.1.0/.kodiak.toml +11 -0
  15. ghome_local_api-0.1.0/.pre-commit-config.yaml +80 -0
  16. ghome_local_api-0.1.0/CONTRIBUTING.md +80 -0
  17. ghome_local_api-0.1.0/LICENSE +22 -0
  18. ghome_local_api-0.1.0/PKG-INFO +167 -0
  19. ghome_local_api-0.1.0/README.md +145 -0
  20. ghome_local_api-0.1.0/codecov.yml +20 -0
  21. ghome_local_api-0.1.0/dprint.json +23 -0
  22. ghome_local_api-0.1.0/ghome_local_api/__init__.py +66 -0
  23. ghome_local_api-0.1.0/ghome_local_api/client.py +481 -0
  24. ghome_local_api-0.1.0/ghome_local_api/const.py +34 -0
  25. ghome_local_api-0.1.0/ghome_local_api/exceptions.py +112 -0
  26. ghome_local_api-0.1.0/ghome_local_api/models.py +372 -0
  27. ghome_local_api-0.1.0/ghome_local_api/py.typed +0 -0
  28. ghome_local_api-0.1.0/pyproject.toml +231 -0
  29. ghome_local_api-0.1.0/tests/__init__.py +1 -0
  30. ghome_local_api-0.1.0/tests/conftest.py +8 -0
  31. ghome_local_api-0.1.0/tests/fake_device.py +228 -0
  32. ghome_local_api-0.1.0/tests/test_client.py +826 -0
  33. ghome_local_api-0.1.0/tests/test_models.py +415 -0
  34. ghome_local_api-0.1.0/uv.lock +1429 -0
@@ -0,0 +1,12 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ trim_trailing_whitespace = true
7
+ charset = utf-8
8
+ indent_style = space
9
+ indent_size = 4
10
+
11
+ [*.{json,md,yaml,yml}]
12
+ indent_size = 2
@@ -0,0 +1,24 @@
1
+ name: "Common steps to install and cache dependencies"
2
+ description: "Install uv, Python and the project dependencies"
3
+
4
+ inputs:
5
+ python-version:
6
+ description: "Python version to set up"
7
+ required: true
8
+
9
+ runs:
10
+ using: "composite"
11
+ steps:
12
+ - name: Install uv
13
+ uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
14
+ # enable-cache stays at its default, "auto": the cache is on for CI and
15
+ # off for release events, so release builds don't restore a cache.
16
+ with:
17
+ python-version: ${{ inputs.python-version }}
18
+ # Different jobs on the same Python version still compute the
19
+ # same key and race to save it, so add the job name too.
20
+ cache-suffix: ${{ github.job }}
21
+
22
+ - name: Install dependencies with uv
23
+ shell: bash
24
+ run: uv sync
@@ -0,0 +1,34 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: uv
4
+ directory: "/"
5
+ # Never raise floors in pyproject.toml: the runtime floors follow Home
6
+ # Assistant's pins, and a newer floor would stop ghome-local-api installing there.
7
+ versioning-strategy: lockfile-only
8
+ schedule:
9
+ interval: weekly
10
+ # A release has a week to be yanked before it is proposed here.
11
+ cooldown:
12
+ default-days: 7
13
+ labels:
14
+ - "dependencies"
15
+ - package-ecosystem: pre-commit
16
+ directory: "/"
17
+ schedule:
18
+ interval: weekly
19
+ cooldown:
20
+ default-days: 7
21
+ labels:
22
+ - "dependencies"
23
+ - package-ecosystem: github-actions
24
+ directories:
25
+ # Workflows in .github/workflows
26
+ - "/"
27
+ # Composite actions are not covered by "/" and must be listed explicitly
28
+ - "/.github/actions/*"
29
+ schedule:
30
+ interval: weekly
31
+ cooldown:
32
+ default-days: 7
33
+ labels:
34
+ - "dependencies"
@@ -0,0 +1,40 @@
1
+ # Schema reference: https://github.com/actions/labeler#match-object
2
+ # Options inside `all` are AND-ed. The dependency rule needs every change to be
3
+ # inside its listed files; the GitHub structure and documentation rules can
4
+ # also match mixed changes. Pull requests touching Python source need a manual
5
+ # type label. Dependabot labels its own pull requests, so its branches are
6
+ # skipped here.
7
+
8
+ dependencies:
9
+ - all:
10
+ - head-branch: ["^(?!dependabot/)"]
11
+ - changed-files:
12
+ # A dependency update only: nothing outside these files changed.
13
+ - any-glob-to-any-file: "uv.lock"
14
+ # One combined pattern: any-glob-to-all-files asks whether a
15
+ # single glob matches every changed file, so a list of two would
16
+ # never match the usual pair.
17
+ - any-glob-to-all-files: "{uv.lock,pyproject.toml}"
18
+
19
+ github structure:
20
+ - all:
21
+ - head-branch: ["^(?!dependabot/)"]
22
+ - changed-files:
23
+ - any-glob-to-any-file: ".github/**/*"
24
+ - all-globs-to-all-files: "!**/*.py"
25
+
26
+ documentation:
27
+ - all:
28
+ - head-branch: ["^(?!dependabot/)"]
29
+ - changed-files:
30
+ - any-glob-to-any-file: "**/*.md"
31
+ - all-globs-to-all-files:
32
+ - "!**/*.py"
33
+ - "!.github/**/*"
34
+
35
+ test:
36
+ - all:
37
+ - head-branch: ["^(?!dependabot/)"]
38
+ - changed-files:
39
+ - any-glob-to-any-file: "tests/**/*"
40
+ - all-globs-to-all-files: "!ghome_local_api/**/*"
@@ -0,0 +1,93 @@
1
+ ---
2
+ # Labels names are important as they are used by Release Drafter to decide
3
+ # regarding where to record them in changelog or if to skip them.
4
+ #
5
+ # The repository labels will be automatically configured using this file and
6
+ # the GitHub Action https://github.com/marketplace/actions/github-labeler.
7
+ - name: automerge
8
+ description: Automatically merge by Kodiak
9
+ color: d4c5f9
10
+
11
+ - name: breaking
12
+ description: Breaking change. Used for major release bump
13
+ color: b60205
14
+
15
+ - name: bug
16
+ description: Something isn't working
17
+ color: d73a4a
18
+
19
+ - name: dependencies
20
+ description: Pull requests that update a dependency file
21
+ color: 0366d6
22
+
23
+ - name: documentation
24
+ description: Improvements or additions to documentation
25
+ color: 0075ca
26
+
27
+ - name: duplicate
28
+ description: This issue or pull request already exists
29
+ color: cfd3d7
30
+
31
+ - name: feature
32
+ description: New feature or request
33
+ color: a2eeef
34
+
35
+ - name: github structure
36
+ description: Pull requests that update Github actions/workflow code
37
+ color: "000000"
38
+
39
+ - name: good first issue
40
+ description: Good for newcomers
41
+ color: 7057ff
42
+
43
+ - name: help wanted
44
+ description: Extra attention is needed
45
+ color: 008672
46
+
47
+ - name: invalid
48
+ description: This doesn't seem right
49
+ color: e4e669
50
+
51
+ # major/minor/patch describe the dependency's version jump on Dependabot PRs.
52
+ # They do not affect this project's version: release bumps are driven by the
53
+ # "breaking" and "feature" labels, see release-drafter.yml.
54
+ - name: major
55
+ description: Semver-major dependency update
56
+ color: 16970B
57
+
58
+ - name: minor
59
+ description: Semver-minor dependency update
60
+ color: 16970B
61
+
62
+ - name: patch
63
+ description: Semver-patch dependency update
64
+ color: 16970B
65
+
66
+ - name: performance
67
+ description: Performance
68
+ color: "016175"
69
+
70
+ # Leaves a pull request out of the release notes
71
+ - name: skip-release
72
+ description: Skip release
73
+ color: "000000"
74
+
75
+ - name: question
76
+ description: Further information is requested
77
+ color: d876e3
78
+
79
+ - name: refactoring
80
+ description: Refactoring
81
+ color: ef67c4
82
+
83
+ - name: removal
84
+ description: Removals and Deprecations
85
+ color: 9ae7ea
86
+
87
+ - name: test
88
+ description: Changing tests
89
+ color: b1fc6f
90
+
91
+ - name: wontfix
92
+ description: This will not be worked on
93
+ color: ffffff
@@ -0,0 +1,55 @@
1
+ name-template: "v$RESOLVED_VERSION"
2
+ tag-template: "v$RESOLVED_VERSION"
3
+ categories:
4
+ # PRs with this label are left out of the release notes entirely.
5
+ - type: "pre-exclude"
6
+ when:
7
+ label: "skip-release"
8
+ # major/minor/patch labels are intentionally not used for version
9
+ # resolution: Dependabot applies them to describe the dependency's own
10
+ # version jump, which says nothing about this package.
11
+ - type: "version-resolver"
12
+ semver-increment: "major"
13
+ when:
14
+ label: "breaking"
15
+ - type: "version-resolver"
16
+ semver-increment: "minor"
17
+ when:
18
+ label: "feature"
19
+ # Keep this above the other headings: exclusive stops later headings from
20
+ # matching, so a breaking PR is listed only here, even with other labels.
21
+ - title: "💥 Breaking Changes"
22
+ exclusive: true
23
+ when:
24
+ label: "breaking"
25
+ - title: "🚀 Features"
26
+ when:
27
+ labels:
28
+ - "feature"
29
+ - "performance"
30
+ - title: "🐛 Bug Fixes"
31
+ when:
32
+ label: "bug"
33
+ - title: "📄 Documentation"
34
+ when:
35
+ label: "documentation"
36
+ - title: "🔧 Internal structure enhancement"
37
+ when:
38
+ labels:
39
+ - "github structure"
40
+ - "refactoring"
41
+ - "removal"
42
+ - title: "🧰 Maintenance"
43
+ when:
44
+ label: "test"
45
+ - title: "🧱 Dependency Updates"
46
+ when:
47
+ label: "dependencies"
48
+ change-template: "- $TITLE @$AUTHOR (#$NUMBER)"
49
+ change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
50
+ version-resolver:
51
+ default: patch
52
+ template: |
53
+ ## Changes
54
+
55
+ $CHANGES
@@ -0,0 +1,111 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ checks:
14
+ name: Checks
15
+ strategy:
16
+ matrix:
17
+ python-version: ["3.12", "3.14"]
18
+ fail-fast: false
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 15
21
+ permissions:
22
+ contents: read
23
+ id-token: write # The Codecov upload authenticates with GitHub OIDC
24
+ steps:
25
+ - name: Check out the repository
26
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27
+ with:
28
+ persist-credentials: false
29
+
30
+ - name: Prepare and install deps
31
+ uses: ./.github/actions/install-deps
32
+ with:
33
+ python-version: ${{ matrix.python-version }}
34
+
35
+ # Hook environments (prek) and formatter plugins (dprint) are
36
+ # downloaded on first use; both only change with their config files.
37
+ - name: Cache prek hooks and dprint plugins
38
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
39
+ with:
40
+ path: |
41
+ ~/.cache/prek/
42
+ ~/.cache/dprint/
43
+ key: >
44
+ ${{ format('prek-{0}-{1}',
45
+ matrix.python-version,
46
+ hashFiles('.pre-commit-config.yaml', 'dprint.json')
47
+ ) }}
48
+ restore-keys: |
49
+ prek-${{ matrix.python-version }}-
50
+
51
+ - name: Run prek on all files
52
+ run: |
53
+ uvx prek run --all-files --show-diff-on-failure --color=always
54
+
55
+ - name: Run python-typing-update
56
+ run: |
57
+ uvx prek run --hook-stage manual python-typing-update --all-files --show-diff-on-failure --color=always
58
+
59
+ # The runtime floor follows Home Assistant's pin, so test it too. The
60
+ # test header shows the aiohttp version that was resolved.
61
+ - name: Run tests with the lowest allowed dependencies
62
+ run: |
63
+ uv run --isolated --resolution lowest-direct pytest --cov-report=xml
64
+
65
+ # Codecov merges the reports from both Python versions; after_n_builds
66
+ # in codecov.yml must match their number. With OIDC the repository needs
67
+ # no Codecov token secret. Pull requests from forks get no OIDC token and
68
+ # upload without one, which Codecov accepts for public repositories.
69
+ - name: Upload coverage to Codecov
70
+ # A failed upload leaves Codecov's report out of date and the commit
71
+ # without Codecov's statuses or an updated comment, but doesn't fail
72
+ # the checks.
73
+ continue-on-error: true
74
+ uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
75
+ with:
76
+ name: Python ${{ matrix.python-version }}
77
+ files: coverage.xml
78
+ disable_search: true
79
+ use_oidc: true
80
+ # Without this, an uploader that fails its signature check still runs.
81
+ fail_ci_if_error: true
82
+ # Download the uploader outside the checkout, so the sdist built
83
+ # below doesn't pick it up.
84
+ cleanup: true
85
+
86
+ - name: Build the package
87
+ run: uv build
88
+
89
+ # Install the wheel into a new environment and import it with -I, so the
90
+ # source tree can't stand in for it. This catches a wrong package path, a
91
+ # missing typing marker or copyright notice and unexpected runtime
92
+ # dependencies.
93
+ - name: Check the built wheel
94
+ run: |
95
+ uv run --isolated --no-project --with dist/*.whl python -I -c '
96
+ import pathlib
97
+ import sys
98
+ from importlib import metadata
99
+
100
+ import ghome_local_api
101
+
102
+ dist = metadata.distribution("ghome-local-api")
103
+ assert pathlib.Path(ghome_local_api.__file__) == dist.locate_file("ghome_local_api/__init__.py")
104
+ assert "ghome_local_api/py.typed" in {str(path) for path in dist.files or ()}
105
+ assert dist.requires == ["aiohttp>=3.14.4"], dist.requires
106
+ assert dist.metadata["Requires-Python"] == ">=3.12"
107
+ license_text = dist.read_text("licenses/LICENSE") or ""
108
+ for notice in ("Copyright (c) 2020 Ilja Leiko", "Copyright (c) 2026 Ruslan Sayfutdinov"):
109
+ assert notice in license_text, notice
110
+ print(f"ghome-local-api {dist.version} on Python {sys.version}")
111
+ '
@@ -0,0 +1,22 @@
1
+ name: Labeler
2
+
3
+ on:
4
+ pull_request_target:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ contents: read
10
+ pull-requests: write
11
+
12
+ jobs:
13
+ triage:
14
+ name: Triage
15
+ if: github.repository_owner == 'KapJI'
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 5
18
+ steps:
19
+ - name: Run Pull Request Labeler
20
+ uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
21
+ with:
22
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
@@ -0,0 +1,25 @@
1
+ name: Manage labels
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ contents: read
10
+ issues: write
11
+
12
+ jobs:
13
+ labeler:
14
+ name: Update labels
15
+ if: github.repository_owner == 'KapJI'
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 5
18
+ steps:
19
+ - name: Check out the repository
20
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21
+ with:
22
+ persist-credentials: false
23
+
24
+ - name: Run Labeler
25
+ uses: crazy-max/ghaction-github-labeler@548a7c3603594ec17c819e1239f281a3b801ab4d # v6.0.0
@@ -0,0 +1,68 @@
1
+ # Publishing a GitHub release runs this workflow. It builds the wheel and sdist
2
+ # once, then uploads exactly those files to PyPI through trusted publishing:
3
+ # PyPI accepts the upload job's short-lived GitHub OIDC token, so the
4
+ # repository keeps no PyPI token. The upload needs a PyPI trusted publisher for
5
+ # this workflow file and the `release` environment, and it waits for that
6
+ # environment's required reviewer.
7
+ name: Publish
8
+
9
+ concurrency: release
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ env:
19
+ PYTHON_VERSION: "3.14"
20
+
21
+ jobs:
22
+ build:
23
+ name: Build
24
+ if: github.repository_owner == 'KapJI'
25
+ runs-on: ubuntu-latest
26
+ timeout-minutes: 15
27
+ steps:
28
+ - name: Check out the repository
29
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30
+ with:
31
+ persist-credentials: false
32
+
33
+ - name: Prepare and install deps
34
+ uses: ./.github/actions/install-deps
35
+ with:
36
+ python-version: ${{ env.PYTHON_VERSION }}
37
+
38
+ - name: Build package
39
+ run: uv build
40
+
41
+ - name: Store the built files
42
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
43
+ with:
44
+ name: dist
45
+ path: dist/
46
+ if-no-files-found: error
47
+
48
+ # Only this job can get an OIDC token, and it runs no code from the
49
+ # repository: it uploads the files that the build job stored.
50
+ publish:
51
+ name: Publish to PyPI
52
+ needs: build
53
+ runs-on: ubuntu-latest
54
+ timeout-minutes: 15
55
+ environment: release
56
+ permissions:
57
+ id-token: write # Trusted publishing and PEP 740 attestations use GitHub OIDC tokens
58
+ steps:
59
+ - name: Download the built files
60
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
61
+ with:
62
+ name: dist
63
+ path: dist/
64
+
65
+ # Unlike `uv publish`, the action also creates PEP 740 attestations,
66
+ # which PyPI shows as verified provenance for each file.
67
+ - name: Publish to PyPI
68
+ uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
@@ -0,0 +1,22 @@
1
+ name: Draft a release note
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ contents: write
10
+ pull-requests: read
11
+
12
+ jobs:
13
+ draft_release:
14
+ name: Release Drafter
15
+ if: github.repository_owner == 'KapJI'
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 5
18
+ steps:
19
+ - name: Run release-drafter
20
+ uses: release-drafter/release-drafter@978bb0b30c5ee8cdd332ced253758157150d43f0 # v7.10.0
21
+ env:
22
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,4 @@
1
+ rules:
2
+ # `./` paths to local actions are the long-standing form; keep them.
3
+ self-repository:
4
+ disable: true
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ .tox/
3
+ .DS_Store
4
+ .env
5
+ /.idea/
6
+ *.pyc
7
+ .ipynb_checkpoints
8
+ .pytest_cache
9
+ *.egg-info
10
+ /build/
11
+ /dist/
12
+ /.venv/
13
+ .mypy_cache/
14
+ .ruff_cache/
15
+ .coverage
16
+ coverage.xml
17
+ /AGENTS.md
@@ -0,0 +1,11 @@
1
+ version = 1
2
+
3
+ [approve]
4
+ auto_approve_usernames = ["dependabot"]
5
+
6
+ [merge]
7
+ method = "squash"
8
+
9
+ [merge.automerge_dependencies]
10
+ versions = ["minor", "patch"]
11
+ usernames = ["dependabot"]
@@ -0,0 +1,80 @@
1
+ default_stages: [pre-commit]
2
+ repos:
3
+ - repo: https://github.com/pre-commit/pre-commit-hooks
4
+ rev: v6.0.0
5
+ hooks:
6
+ - id: check-added-large-files
7
+ - id: check-case-conflict
8
+ - id: check-json
9
+ - id: check-merge-conflict
10
+ - id: check-toml
11
+ - id: check-yaml
12
+ - id: end-of-file-fixer
13
+ - id: trailing-whitespace
14
+ - repo: https://github.com/python-jsonschema/check-jsonschema
15
+ rev: 0.39.0
16
+ hooks:
17
+ - id: check-dependabot
18
+ - id: check-github-actions
19
+ - id: check-github-workflows
20
+ - repo: https://github.com/zizmorcore/zizmor-pre-commit
21
+ rev: v1.31.1
22
+ hooks:
23
+ - id: zizmor
24
+ - repo: local
25
+ hooks:
26
+ - id: dprint
27
+ name: dprint format
28
+ entry: uv run dprint fmt
29
+ language: system
30
+ pass_filenames: false
31
+ types_or: [json, markdown, toml, yaml]
32
+ - id: ruff-format
33
+ name: ruff format
34
+ entry: uv run ruff format
35
+ language: system
36
+ types: [python]
37
+ require_serial: true
38
+ - id: ruff
39
+ name: ruff check
40
+ entry: uv run ruff check --fix
41
+ language: system
42
+ types: [python]
43
+ require_serial: true
44
+ - id: mypy
45
+ name: mypy
46
+ entry: uv run mypy
47
+ language: system
48
+ types: [python]
49
+ require_serial: true
50
+ - id: pylint
51
+ name: pylint
52
+ entry: uv run pylint
53
+ language: system
54
+ types: [python]
55
+ require_serial: true
56
+ - id: pytest
57
+ name: pytest
58
+ language: system
59
+ entry: uv run pytest
60
+ pass_filenames: false
61
+ always_run: true
62
+ - id: codespell
63
+ name: codespell
64
+ entry: uv run codespell
65
+ language: system
66
+ pass_filenames: false
67
+ always_run: true
68
+ - repo: https://github.com/cdce8p/python-typing-update
69
+ rev: v0.9.0
70
+ hooks:
71
+ # Run `python-typing-update` hook manually from time to time
72
+ # to update python typing syntax.
73
+ # Will require manual work, before submitting changes!
74
+ - id: python-typing-update
75
+ stages: [manual]
76
+ args:
77
+ - --py312-plus
78
+ - --force
79
+ - --keep-updates
80
+ files: ^.+\.py$