Skip to content

Pin ruff target-version to py310, and drop the future imports it made redundant - #2182

Open
David Harris (davidharrishmc) wants to merge 2 commits into
riscv:act4from
davidharrishmc:ruff-target-version
Open

Pin ruff target-version to py310, and drop the future imports it made redundant#2182
David Harris (davidharrishmc) wants to merge 2 commits into
riscv:act4from
davidharrishmc:ruff-target-version

Conversation

@davidharrishmc

@davidharrishmc David Harris (davidharrishmc) commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Two commits: a config fix, and the cleanup it enables.

1. Pin target-version = "py310"

[tool.ruff] sets line-length but never target-version, and the root pyproject.toml has no [project] table, so there is no requires-python for ruff to infer the target from either. Ruff falls back to searching outside the repository and picks up whatever the nearest ancestor Python project declares.

The result is that lint results depend on where the repository is checked out.

In a standalone checkout, as in CI, nothing is found, ruff's default applies, and the tree lints clean. But checked out inside another Python project that declares an older floor — which is how this repo is consumed when vendored as a submodule, e.g. under a parent that sets requires-python = ">=3.9" — ruff resolves py39 and reports 16 errors CI never sees, all of them FA102 (missing from __future__ import annotations, but uses PEP 604 union) on files that are correct for this project's actual floor.

Reproduced by forcing the version on an otherwise unmodified tree:

invocation result
ruff check . (standalone, default) clean
ruff check --target-version py39 . 16 errors
ruff check --target-version py310 . clean

py310 is the floor this project already commits to everywhere else: [tool.pyright] sets pythonVersion = "3.10", all three workspace members declare requires-python = ">=3.10", AGENTS.md asks contributors to keep the Python 3.10-compatible, and CI rewrites .python-version to 3.10 for the oldest-supported-version job. Ruff was the one tool left inferring it. Note the asymmetry this removes — pyright was already immune, because its version is pinned in the same file.

This does not change CI results today. It makes them reproducible outside CI, and stable if ruff changes its default in a future release.

2. Drop from __future__ import annotations where it is now redundant

With the target pinned to py310, PEP 604 unions (X | Y) and PEP 585 builtin generics (list[int]) are natively valid in annotations. Removed from 40 files.

Three files genuinely still need it and keep it:

file why
generators/testgen/src/testgen/data/registers.py four methods annotated with classes not yet defined at that point (RegisterFile, IntegerRegisterFile, FloatRegisterFile, VectorRegisterFile) — NameError at import without lazy annotations
framework/src/act/parse_udb_config.py imports act.config.Config under if TYPE_CHECKING:; eager annotations would force it to a runtime import
framework/src/act/build_cache.py _new_hash() -> hashlib._Hash — that name exists only in typeshed, not at runtime

A note for future cleanups of this kind

The build_cache.py case is worth calling out. Python 3.14 implements PEP 649, so annotations are lazily evaluated by default there and this entire class of breakage is invisible on a 3.14 interpreter — the full ACT build passes. On the 3.10 floor it fails at import with AttributeError: module 'hashlib' has no attribute '_Hash'. Anyone repeating this cleanup should verify against 3.10, not against a modern local interpreter. This PR's first CI run caught exactly that, on the Python 3.10 (uv) job.

Verification

All re-run on Python 3.10, matching the oldest-supported-version CI job:

  • ruff check and pyright clean; ruff format --check reports no change on any touched file. (One unrelated file is format-dirty on act4 already, before and after this change.)
  • Every touched module imports — this is what catches eager-annotation errors that pyright cannot, since pyright assumes TYPE_CHECKING is true and trusts typeshed.
  • make tests leaves the checked-in generated trees with zero diff.
  • FAST=True EXTENSIONS=I make — the exact CI step that failed — completes a real build of 204 ELFs.

🤖 Generated with Claude Code

[tool.ruff] sets line-length but never target-version, and the root
pyproject.toml has no [project] table, so there is no requires-python for ruff
to infer the target from. Ruff therefore falls back to searching outside the
repository and picks up whatever the nearest ancestor Python project declares.

That makes lint results depend on where the repository happens to be checked
out. In a standalone checkout, as in CI, nothing is found and ruff's default
applies, which lints clean. But checked out inside another Python project that
declares an older floor -- for example under a tool that sets
requires-python = ">=3.9" -- ruff resolves py39 and reports 16 errors CI never
sees, all of them FA102 "missing `from __future__ import annotations`, but uses
PEP 604 union" on files that are correct for this project's actual floor.

py310 is the floor this project already commits to everywhere else:
[tool.pyright] sets pythonVersion = "3.10", all three workspace members declare
requires-python = ">=3.10", AGENTS.md asks contributors to keep the Python
3.10-compatible, and CI pins .python-version to 3.10 for the oldest-supported
version job. Ruff was the one tool left to infer it.

This does not change CI results today; it makes them reproducible outside CI
and independent of ruff's default changing in a future release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjJfW5f7acPCsErzWbCv7m
Signed-off-by: David Harris <David_Harris@hmc.edu>
@davidharrishmc David Harris (davidharrishmc) changed the title Pin ruff target-version to py310 Pin ruff target-version to py310, and drop the future imports it made redundant Aug 24, 2026
With target-version pinned to py310, PEP 604 unions (X | Y) and PEP 585
builtin generics (list[int]) are valid natively in annotations, so the future
import is redundant in most modules. Removed from 40 files.

Three files genuinely still need it and keep it:

- generators/testgen/src/testgen/data/registers.py annotates four methods with
  classes that are not yet defined at that point in the module
  (RegisterFile, IntegerRegisterFile, FloatRegisterFile, VectorRegisterFile).
  Without lazy annotations these are NameErrors at import.
- framework/src/act/parse_udb_config.py imports act.config.Config inside an
  if TYPE_CHECKING block. Eager annotations would require that import to move
  to runtime, which is a heavier change than keeping the future import.
- framework/src/act/build_cache.py annotates _new_hash() -> hashlib._Hash.
  That name exists only in typeshed, not at runtime, so evaluating the
  annotation raises AttributeError on any Python before 3.14.

The last one is worth noting for future cleanups: Python 3.14 implements
PEP 649, so annotations are lazy by default there and this class of breakage is
invisible on a 3.14 interpreter. It must be checked against the 3.10 floor.

Verified on Python 3.10 (the oldest supported version, matching the CI job):
ruff and pyright clean, ruff format reports no change on any touched file,
every touched module imports, make tests leaves the checked-in trees with zero
diff, and FAST=True EXTENSIONS=I make -- the exact CI step -- completes a real
build of 204 ELFs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjJfW5f7acPCsErzWbCv7m
Signed-off-by: David Harris <David_Harris@hmc.edu>
@github-actions github-actions Bot added status: needs-review PR is ready for a review CI Issue or pull request related to GitHub Actions workflows Coverpoints Issues or pull requests related to functional coverage or coverage generation dependencies Pull requests that update a dependency file Test Framework Issues or pull requests related to test selection, build, or execution logic Tests Issues or pull requests related to the test generator or handwritten tests labels Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI Issue or pull request related to GitHub Actions workflows Coverpoints Issues or pull requests related to functional coverage or coverage generation dependencies Pull requests that update a dependency file status: needs-review PR is ready for a review Test Framework Issues or pull requests related to test selection, build, or execution logic Tests Issues or pull requests related to the test generator or handwritten tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant