Skip to content

py(deps[dev]): Require ruff>=0.16.0#82

Open
tony wants to merge 10 commits into
masterfrom
ruff-0.16
Open

py(deps[dev]): Require ruff>=0.16.0#82
tony wants to merge 10 commits into
masterfrom
ruff-0.16

Conversation

@tony

@tony tony commented Jul 26, 2026

Copy link
Copy Markdown
Member

Summary

  • Pin a ruff>=0.16.0 floor in the dev and lint dependency groups so contributors and CI see the same diagnostics instead of splitting on whatever ruff each machine resolved.
  • Relock uv.lock onto ruff 0.16.0.
  • Reformat the Python snippets embedded in AGENTS.md and README.md — 0.16.0 formats Python and pycon code blocks inside Markdown by default, so ruff format --check now reaches documentation it previously ignored.
  • Adopt ruff's default rule set. [tool.ruff.lint] select replaces the default set rather than extending it, so this project was silently opting out of every default rule its list did not name. Renaming the key to extend-select layers the project's linters on top of the defaults instead of in place of them. Enabled rules go from 351 to 565.
  • Triage the four new findings — three fixed in code, one scoped to an ignore with its reason in the config.

Changes

pyproject.tomlruff becomes ruff>=0.16.0 in both the dev and lint groups. [tool.ruff.lint] select becomes extend-select, with the same entries, one per line, each carrying the name of the linter it selects, and a comment recording why select stays unset.

uv.lock — relocked, ruff 0.15.22 to 0.16.0.

AGENTS.md, README.mdruff format normalized the quotes in the conf.py example for linkify_issues. CLAUDE.md is a symlink to AGENTS.md, so it follows.

src/doctest_docutils.py, tests/test_doctest_docutils.pyreturn-in-init (PLE0101). Three exception classes ended their constructor with return super().__init__(...). __init__ returns None by contract, so the return carried no value and no control flow; it is now a plain statement.

CHANGES — development entries recording the ruff floor, why Markdown snippets are now in scope for ruff format, and the default rule set adoption.

Ignores added

exec-builtin (S102), scoped to docs/conf.py. The Sphinx config reads __title__, __version__, and the project URLs by exec'ing src/gp_libs.py into a dict — the standard idiom for reading package metadata without importing the package, which keeps a docs build from pulling in gp-libs' runtime dependencies. The input is a file in this repository, not untrusted data. The ignore is per-file rather than global so exec anywhere else still trips the rule.

Design decisions

The config change lands by itself, before any fix or ignore, so the rule-set delta is reviewable independently of the code it turned up. Each fix and each ignore is then its own commit carrying the rule's documentation link.

The Markdown reformat is likewise its own commit so a reviewer can confirm at a glance that the documentation churn is ruff's quote normalization and nothing else.

select cannot name the default set — ruff's selector syntax has no token for it — so leaving select unset and layering with extend-select is the only way to get defaults-plus-extras. Expanding to whole linter prefixes instead was considered and rejected: it drags in all of D, PL, S, and friends rather than the curated subset ruff recommends.

Test plan

  • uv run ruff check . — all checks passed
  • uv run ruff format . --check — all files already formatted
  • uv run mypy . — no issues found
  • uv run py.test — full suite green, including the doctests collected from docs/ and src/

codecov/patch reports 0% of the diff hit. The only executable lines this branch touches are the three exception constructors, and those constructor bodies were already outside coverage — project coverage is unchanged at 76.32% (+0.00%). The rule fix neither adds nor removes covered lines; earlier commits on this branch touched no Python source at all, which is why the check was previously reported as "coverage not affected".

tony added 3 commits July 26, 2026 13:23
why: uv's global `exclude-newer = "3 days"` supply-chain cooldown hides
ruff 0.16.0 (released 2026-07-23) from the resolver, so the version
floor in the next commit cannot resolve.

what:
- Add `ruff = false` to `[tool.uv.exclude-newer-package]`

Temporary. Revert before merge - the cooldown clears on its own and the
`ruff>=0.16` floor is what actually holds the version.
why: ruff 0.16.0 stabilizes rules inside prefixes this project already
selects and starts formatting Python code blocks in Markdown. Pinning a
floor keeps contributors and CI on the same diagnostics instead of
splitting on whatever ruff each machine resolved.

what:
- Raise `ruff` to `>=0.16.0` in the `dev` and `lint` dependency groups
- Relock `uv.lock`: ruff 0.15.22 -> 0.16.0

https://astral.sh/blog/ruff-v0.16.0
why: ruff 0.16.0 formats Python and pycon code blocks inside Markdown
by default, so `ruff format --check` now fails on documentation that
was previously out of its reach. The churn is mechanical - ruff's
quote normalization, not a prose or behavior change.

what:
- Reformat the `conf.py` snippets in `AGENTS.md` and `README.md`

https://astral.sh/blog/ruff-v0.16.0
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 76.68%. Comparing base (14807d3) to head (c1ca2f5).

Files with missing lines Patch % Lines
tests/test_doctest_docutils.py 87.50% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #82      +/-   ##
==========================================
+ Coverage   76.32%   76.68%   +0.35%     
==========================================
  Files          15       15              
  Lines        1018     1025       +7     
==========================================
+ Hits          777      786       +9     
+ Misses        241      239       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

tony added 7 commits July 26, 2026 13:25
why: The ruff floor changes what contributors need installed locally,
so it belongs in the unreleased entry rather than only in the diff.

what:
- Add a `### Development` deliverable for `ruff>=0.16.0`
why: ruff 0.16.0 published 2026-07-23T19:10Z and has now cleared uv's
3-day supply-chain cooldown, so the resolver reaches it unaided. The
`ruff>=0.16.0` floor is what holds the version; leaving the exemption
would permanently opt ruff out of the cooldown guard.

what:
- Drop `ruff = false` from `[tool.uv.exclude-newer-package]`
- Relock: the setting is recorded in `uv.lock`, so removing it forces a
  re-resolve. ruff stays at 0.16.0 and no other package moves.

This reverts commit f6474be.
why: ruff 0.16 ships a curated default rule set as its recommended
baseline. An explicit `select` replaces that set rather than extending
it, so this project was silently opting out of every default rule it
did not name. `extend-select` layers the project's own linters on top
of the default set instead of in place of it.

what:
- Replace `select` with `extend-select`, same entries, one per line
- Note in the file why `select` stays unset

Enabled rules go from 351 to 565.
https://docs.astral.sh/ruff/linter/#rule-selection
why: `__init__` returns `None` by contract, so returning the result of
`super().__init__()` returns nothing meaningful and misleads a reader
into thinking the constructor produces a value.

what:
- Call `super().__init__()` as a statement in the three exception
  classes that returned it

https://docs.astral.sh/ruff/rules/return-in-init/
why: conf.py reads `__title__`, `__version__`, and the project URLs by
exec'ing `src/gp_libs.py` into a dict. That is the Sphinx idiom for
reading package metadata without importing the package, and it keeps a
docs build from pulling in gp-libs' runtime dependencies. The input is
a file in this repository, not untrusted data.

what:
- Scope an S102 per-file-ignore to `docs/conf.py`

https://docs.astral.sh/ruff/rules/exec-builtin/
why: The rule set contributors lint against changed, so it belongs in
the unreleased entry rather than only in the diff.

what:
- Add a `### Development` deliverable for the default rule set

https://docs.astral.sh/ruff/linter/#rule-selection
why: Dropping the stray `return` from these constructors made their
bodies patch lines, and neither was exercised by a test, so the patch
coverage gate went red. The tests also pin the behaviour the PLE0101
change had to preserve: the message each exception carries.

what:
- Assert the message of `DocTestFinderNameDoesNotExist`, including the
  interpolated type of the offending object
- Assert the message of `TestDocutilsPackageRelativeError`
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.

1 participant