Require the future-annotations import with ruff - #41
Conversation
Every module under src/ carries `from __future__ import annotations` except _extras, which needs nothing from it and so went unnoticed. Ruff's isort required-imports enforces what was being eyeballed, and adds the import there. The rule is scoped to the package: tests and scripts mostly do without it, and that is their own convention rather than a lapse in this one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Whether the package's `from __future__ import annotations` convention is worth enforcing with a linter is a preference, settled by argument rather than by any test, and it shares nothing with the duplicated implementations the rest of this branch retires — no other commit here touches pyproject.toml or _extras. It is proposed on its own in #41 instead, where accepting or rejecting it costs nothing else. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The two ignore lines say what they do, and why those trees are exempt belongs to the history of the rule rather than sitting beside it in the config. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jasonleenaylor
left a comment
There was a problem hiding this comment.
This codifies an invariant the package already depends on rather than introducing a style preference -- the TYPE_CHECKING-only imports in public signatures resolve at runtime only because annotations are strings. Worth making enforceable.
I checked the one thing that could have bitten: _extras.py is the only file newly switching to string annotations, and the only runtime annotation introspection in the repo is tests/test_public_api.py, which reads raw PEP 563 strings deliberately. No exposure.
One nit inline.
This review was assisted by Claude Opus 5.
jasonleenaylor
left a comment
There was a problem hiding this comment.
@jasonleenaylor reviewed 2 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on imnasnainaec).
Every module under
src/opens withfrom __future__ import annotationsexcept
_extras.py,which needs nothing from it, so its absence was invisible. Ruff's isort
required-importsenforces what was being eyeballed, and supplies the missingimport.
The rule is scoped to the package. Tests and scripts mostly do without the
import, and that is their own convention rather than a lapse in this one, so
both are exempted from
I002rather than gaining 15 no-op imports.What is actually being decided
Whether the convention is worth a linter at all. That is a preference, settled
by argument rather than by any test, which is why a change this small is worth
its own review.
Nothing behavioural turns on it either way. The added import is a no-op in
_extras.py—requires-pythonis already>=3.11, where every annotation inthat module evaluates fine without it — so what is on offer is the guarantee
that the next module cannot quietly omit it, against a cost of one config
block.
ruff check,ruff format --checkandmypyare green.🤖 Generated with Claude Code
This change is