Repository navigation
Move pre-commit to ruff and run fast tests on Python 3.13 and 3.14 - #267
Merged
Merged
Conversation
Finding: requires-python was already >=3.13 (no floor change needed), but test-fast.yml only ran the fast suite on 3.13 and its header comment was already stale (said 3.11+3.13 while the matrix only had 3.13). Fix: matrix is now ['3.13', '3.14']; updated both the top-of-file comment and the inline matrix comment to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finding: the lint stack carried five separate tools (isort, pyupgrade, flake8, black, nbQA) with duplicated ignore lists across the main flake8 hook and nbqa-flake8; the versions were due for a bump anyway (pre-commit-hooks v5->v6, mypy v1.13->v2.4) ahead of the 3.14 matrix. Fix: ruff-check (--fix) + ruff-format replace all five under one pre-commit repo and one [tool.ruff] config; the old flake8 ignore list (E501, E731) carries over as ruff ignores, plus the three PEP 695 pyupgrade rewrites (UP040/046/047) that change runtime semantics. isort's --profile black becomes known-first-party under [tool.ruff.lint.isort]. Updated the two remaining doc references (pre-commit.yml header comment, CONTRIBUTING.md step 5) that still named the old tools. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finding: ruff format and black disagree on a handful of stylistic calls (trailing comma placement, some multi-line call wrapping). Fix: ran `ruff format` over all 299 tracked .py files; 71 reformatted, 228 unchanged. Proved the change is purely cosmetic: for every changed file, ast.dump(ast.parse(old)) == ast.dump(ast.parse(new)) — 71 files, all AST-equal (script: scratchpad/pysupport/tuningfork/ast_equal_check.py). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finding: `ruff check --statistics` on the formatted tree reported 22 errors across 6 rules (UP017 x7, UP042 x5, E741 x4, UP031 x4, F401 x1, F841 x1); 8 were marked safely fixable. Running --fix iteratively resolved 16 of the 22 (the extra 8 beyond the initial preview are import-cleanup fixes cascading from the datetime.timezone.utc -> datetime.UTC rewrite), leaving 14 genuine lint findings for the next commit. Fix: `datetime.timezone.utc` -> `datetime.UTC` (UP017, Python 3.11+ alias) across 5 files; dropped one now-provably-unused `matplotlib` import in the marimo catalog explorer (F401). No behavior change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finding: 14 of 30 ruff-check findings needed judgment, not --fix. UP042 (str+Enum -> StrEnum) is NOT safe here: empirically str(Effort.LOW) is "Effort.LOW" under (str, Enum) but "low" under StrEnum, and tests/recipes/test_schema.py:61 asserts the former while tuningfork/recipes/_resolve_execution_plan.py:323 f-strings an Effort value into a file path — rewriting the 5 flagged classes would be a silent behavior change, not a style fix. Fix: E741 ambiguous `l` renamed to `line`/`lam_i` at its 2 sites (test_emit_x64_timing.py, _execution_telemetry.py); F841 dropped an unused `n_warmup` local in _timing.py; UP031 converted 4 %-format code strings to f-strings in _emit/_init_strategy.py (output text is unchanged — verified by the existing init-strategy/timing/telemetry test files, 150 passed). UP042 added to the ignore list alongside the existing PEP 695 out-of-scope rewrites, with the str()/f-string evidence recorded in the comment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finding: a live --all-files run showed ruff-format's new default types_or includes "markdown" (astral-sh/ruff-pre-commit v0.16.10 hook definition) — it rewrote 6 docs (CONTRIBUTING.md, README.md, 3 catalog READMEs/schema, mclmc-routing-taxonomy.md), stripping hand-aligned inline comments in the Recipe dataclass field table and collapsing docstring examples. Verified against the OLD stack on a scratch worktree of main (8bb7081): nbQA 1.9.0's hooks also declare types_or: [jupyter, markdown], so pre-commit DID hand nbqa-black / nbqa-flake8 tuningfork's 33 tracked .md files — but both reported "No notebooks found in given path(s)" (0.15-0.16s, 0 files). Root cause in nbqa's own source (nbqa/__main__.py): a .md path is only treated as a notebook if jupytext is importable in the hook's isolated env, and none of the old nbqa-black/-flake8/-isort/ -pyupgrade hooks declared jupytext as an additional_dependency — so markdown was already a complete no-op under the old stack, for a different reason (missing jupytext) than ruff-format's scoping. Fix: pin types_or: [python, pyi, jupyter] on the ruff-format hook so coverage matches the old (effectively python/ipynb-only) stack exactly — confirmed equivalent, not just avoided. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Finding: bumping mirrors-mypy v1.13.0 -> v2.4.0 surfaced 4 new "object has no attribute" errors in test_rerun_inference.py. Root cause isolated with a minimal repro: _failed_recipe() had no return annotation, so mypy treats it as untyped and its call sites get type Any; two tests then do `executed, run_root, kwargs = calls[0]` against a `list[tuple[object, ...]]` capture list and `assert executed is recipe` — mypy 2.4's sharper is-narrowing takes recipe's Any down to executed's declared `object`, so the *next* line's `recipe.tuning_seed` / `.model_name` access errors. mypy 1.13 didn't narrow Any through `is` this way. Fix: annotate `_failed_recipe() -> Recipe` (Recipe imported under TYPE_CHECKING to keep the existing local-import runtime pattern unchanged) so recipe's static type is Recipe before the assert, not Any. Confirmed in isolation (mypy_repro3.py) and against the real file; tests/notebooks/test_rerun_inference.py still passes (33/33). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The new 3.14 leg failed in CI with "Failed to spawn: pytest". The sync step passes --python 3.14, but the test step ran a bare `uv run`, which falls back to .python-version (3.13), rebuilds the env for 3.13 without the bench group, and so has no pytest. The 3.13 leg only passed because its versions happened to agree. Set UV_PYTHON from the matrix at job level so every uv command uses the same interpreter. Reproduced locally: a bare `uv run` after a 3.14 sync fails the same way, and with UV_PYTHON=3.14 it runs pytest under 3.14.7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
ruff-check --fixandruff-formatreplace isort, pyupgrade, flake8, black and nbQA in pre-commit. The localno-internal-refshook is unchanged.requires-pythonwas already>=3.13.This is part of the ecosystem move to ruff with a 3.13/3.14 test matrix. The matching PRs are blackjax-devs/blackjax#1055 and blackjax-devs/sampling-book#100.
Lint scope is unchanged
E, F, W, I, UP(targeting py313) and ignores E501 and E731 as before.typeand generics rewrites (UP040/046/047);str+Enum→StrEnum): it changesstr(Effort.LOW)from"Effort.LOW"to"low".tests/recipes/test_schema.pyasserts the current form, and_resolve_execution_plan.pybuilds a file path from an f-string of the enum value.ruff-formatonly runs on python/pyi/jupyter, because its default would also reformat Python code blocks in the catalog READMEs and schemas..mddocs. v1.9.0's hooks do match markdown, but on main nbqa-black and nbqa-flake8 print "No notebooks found in given path(s)" for all 33.mdfiles. The hook environment lacksjupytext, which nbQA needs to read markdown. So dropping nbQA loses nothing.exclude: ^scripts/had no effect:scripts/contains no tracked.pyfiles.Commits
[tool.ruff]replacing[tool.isort], CONTRIBUTING.ruff format, mechanical: 71 files, all with identical syntax trees. The author agent checked this and I re-checked it independently.ruff check --fix: UP017 ×7, F401 ×1.%→ f-string). UP042 is ignored, with the evidence in a comment.ruff-formatto Python files.-> Recipereturn annotation. Newer mypy narrowed an untyped helper'sAnytoobject.Checks run locally
pre-commit run --all-filespasses all 8 hooks under both Python 3.13 and Python 3.14.pytest tests -m fast -n 2):bench-group dependency lacks a 3.14 wheel.Implemented by the swe agent; reviewed by the TL agent, who re-ran the syntax-tree check and gitlint.
🤖 Generated with Claude Code