Skip to content

[Refactor] Modernization: Python 3.10-3.15, ruff, PEP 621 packaging and tag-triggered publishing - #97

Merged
fostimus merged 3 commits into
masterfrom
df/modernize-tooling
Oct 28, 2026
Merged

fostimus merged 3 commits into
masterfrom
df/modernize-tooling

Conversation

@fostimus

@fostimus fostimus commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Layer 1 of 4 of the client modernization. The toolchain, packaging and CI, so the client changes in the layers above are built and checked the modern way.

  • Python 3.8 and 3.9 are EOL and dropped; 3.14 and 3.15 are added. pyproject.toml uses the standard [project] table.
  • click and tabulate become the cli extra, so pip install python-anvil no longer pulls in the CLI's dependencies. Importing python_anvil no longer imports the CLI.
  • ruff replaces black, isort, pylint and pydocstyle; mypy comes off its 2023 pin, with pydantic's mypy plugin handling the aliased fields that kept it there.
  • The unit tests move out of the package into tests/, so they stop shipping in the wheel.
  • CI runs lint and the tests on every supported Python. A Publish workflow publishes to PyPI with trusted publishing when a version tag is pushed, after a maintainer approves the pypi environment, the same shape as node-anvil's. dev/release.py prepares and tags releases. CHANGELOG.md moves to the Keep a Changelog format the workflow reads release notes from.
  • The project-template leftovers go: Travis, AppVeyor, Scrutinizer, Read the Docs, sniffer, tox, verchew and bin/.
  • test-client.py runs every method against a real environment (staging by default) and prints a PASS, FAIL or SKIP for each, like node-anvil's test-client.js. It is written against the 5.x client here, so it can be run before and after the transport change in [Feature] Modernization: one requests transport with base_url, OAuth, adaptive rate limits and typed errors #98; the diff of the script between the two layers is the list of behavior changes. The 5.x queries get_casts and get_welds are expected to FAIL on this layer: the API's casts and welds fields are paginated now, which [Feature] Modernization: one requests transport with base_url, OAuth, adaptive rate limits and typed errors #98 fixes.
  • graphql-core is pinned to 3.3.0a3, the version the old lock had. Regenerating the lock had picked up 3.3.0, whose immutable AST nodes break gql 3.6.0b2's schema fetch with FrozenInstanceError. [Feature] Modernization: one requests transport with base_url, OAuth, adaptive rate limits and typed errors #98 drops gql and the pin.

Setup before the first release is in CONTRIBUTING.md under Publishing: a trusted publisher on pypi.org and a pypi environment with required reviewers. No secrets.

How to verify

  • make install && make lint && make test passes on Python 3.10 and 3.15 (verified locally on both)
  • poetry build produces a wheel with no tests/ in it and LICENSE.md in it
  • Installing the wheel without the extra: import python_anvil works and import python_anvil.cli raises an ImportError pointing at python-anvil[cli]
  • Installing python_anvil[cli] gives a working anvil --help
  • poetry run python dev/release.py prepare 6.0.0 --dry-run describes the release branch, bump and changelog rename without changing anything
  • ANVIL_API_KEY=<staging key> make test-client on this layer runs the 5.x client against staging and prints a result per method (not run here: no staging key in this environment)

Breaking Changes

Python 3.8 and 3.9 are no longer supported, and the CLI needs the cli extra. Both are noted under Unreleased in CHANGELOG.md for 6.0.0.

Fixes #95
Fixes #96

…ed publishing

- pyproject.toml uses the standard [project] table. Python 3.8 and 3.9 are
  EOL and dropped; 3.14 and 3.15 are added (#95).
- The CLI's dependencies, click and tabulate, become the `cli` extra (#96).
  Importing the package no longer imports the CLI.
- ruff replaces black, isort, pylint and pydocstyle, and mypy comes off its
  2023 pin: pydantic's mypy plugin understands the aliased fields.
- The unit tests move out of the package into tests/, so they aren't shipped
  in the wheel.
- CI runs lint and the tests on every supported Python, on PRs and pushes to
  master. A Publish workflow publishes to PyPI with trusted publishing when a
  version tag is pushed, after a maintainer approves the `pypi` environment,
  and dev/release.py prepares and tags releases. CHANGELOG.md moves to the
  Keep a Changelog format the workflow reads release notes from.
- The leftovers of the project template go: Travis, AppVeyor, Scrutinizer,
  Read the Docs, sniffer, tox, verchew and the bin/ scripts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@fostimus
fostimus added this pull request to stack #101 October 21, 2026 21:04
@fostimus fostimus changed the title Modernize the toolchain: Python 3.10-3.15, ruff, PEP 621, tag-triggered publishing [Refactor] Modernization: Python 3.10-3.15, ruff, PEP 621 packaging and tag-triggered publishing Oct 21, 2026
fostimus and others added 2 commits October 21, 2026 22:16
A pass/fail per method against staging, like node-anvil's test-client.js.
Written against the 5.x client here, so it can be run on a release before
and after a change to see which behaviors changed; the transport change
updates it to the 6.0 API, and that diff is the list of changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Regenerating the lock had picked up graphql-core 3.3.0, whose AST nodes
are immutable. gql 3.6.0b2 assigns to them when it builds the
introspection query, so fetching the schema from the API failed with
FrozenInstanceError. The old lock had 3.3.0a3, which works. The transport
change drops gql, and the pin with it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@fostimus
fostimus marked this pull request as ready for review October 28, 2026 17:51
@fostimus
fostimus merged commit ed99553 into master Oct 28, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split out CLI functionality and use as an optional/extra dependency Support for Python 3.14

1 participant