build(deps-dev): bump ruff from 0.15.22 to 0.16.0 - #267
Merged
Conversation
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.22 to 0.16.0. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](astral-sh/ruff@0.15.22...0.16.0) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.16.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Contributor
|
Queued — the merge queue status continues in this comment ↓. |
ruff 0.16.0 expanded its default rule set from 59 rules to 413. This repo
never pinned `select`, so the bump inherited the whole new set at once and
`./doit.sh lint` reported 534 findings, failing CI.
This commit is pure tool output, so it can be skimmed rather than read:
uv run ruff check --fix --unsafe-fixes --unfixable FLY002,UP031 .
uv run ruff format $(git ls-files '*.py')
./doit.sh gen-docs
FLY002 and UP031 are held back because their fixes are worse than the
source. FLY002 collapses the CSP list in web/app.py into one 300-character
line and deletes the comments inside it. UP031 doubles every brace in the
eolymp GraphQL query. The next commit suppresses both at the site.
gen-docs runs here and not later: docs_test asserts docs/library.md matches
the generator, and the generator reads the signatures this commit rewrote.
44 findings remain, cleared by the commits that follow.
Moving `Callable`/`Awaitable` from `typing` to `collections.abc` (UP035, in the previous commit) changed how they stringify: `typing.Callable` rendered bare, but `collections.abc.Callable` carries its module prefix. That leaked into docs/library.md, where `query_sync()` and `CrawlerInfo.query` grew `collections.abc.` prefixes that tell a reader nothing. _readable() already exists to drop such prefixes; give it the new module.
Records the five places the project declines a rule from ruff 0.16's new 413-rule default, so that nobody has to rediscover the reasoning: - BLE001 is ignored project-wide. The catch-all `except Exception` is the crawler contract — any parse or transport failure becomes a RuntimeError the runner reports per crawler, so one judge's surprise never aborts a run. - `fastapi.File` joins extend-immutable-calls. `File(...)` in a parameter default is how FastAPI declares an upload, not a B008 mistake. - FLY002 is suppressed on the CSP in web/app.py. Its fix collapses the list into one 300-character line and deletes the comments inside it, and ADR 0010 records that block as load-bearing. - UP031 is suppressed on the eolymp GraphQL query. .format() needs every brace in the query body doubled. - DTZ007 is suppressed on the chart date parse in web/pdf.py. Those keys are already local-day strings from compute_day_key(); the axis needs their order, not an instant. ADR 0016 carries the argument for taking the new default set rather than pinning `select = ["E4", "E7", "E9", "F"]`, and for reversing the typing convention it collides with. Findings drop from 44 to 16.
Ruff 0.16 formats Python blocks inside Markdown, which `ruff format .` now reaches. Four files drifted. The result is worth keeping rather than excluding: these blocks are templates that get copied into real .py files, so matching the formatter is what a reader wants from them. One block was edited by hand first. The standard-test-case list in the crawlers skill puts one test per line, and the formatter would have exploded the first line across three because its trailing comment pushed it past 88 characters. Dropping the redundant "raises" from two comments keeps the shape and the exact match string.
run_crawler() and _async_main() timed their own work by subtracting two datetime.now() readings. Wall-clock time is the wrong instrument for that: it can be stepped by NTP or a timezone change mid-query, which yields a duration that is too large, too small, or negative. time.monotonic() cannot run backwards. DTZ005 pointed at these four calls for the narrower reason that they carry no timezone. Adding one would have silenced the rule while leaving the real defect, so the clock changes instead. The reported figure keeps its meaning and its format. Verified with a crawler that sleeps 0.35s: run_crawler reports 0.352.
Both timestamps the app renders were naive, so they showed whatever zone the server happened to run in and said nothing about which one that was. A reader in Berlin saw a PDF stamped two hours behind their own clock with no way to tell why. The PDF footer now uses the reader's zone. PdfSnapshot.timezone already carries it, and the day keys in the chart already respect it via compute_day_key() — the footer was the one part of the report that ignored it. The ZoneInfo lookup and its UTC fallback move into _resolve_tz() so both callers share them. /about has no reader zone available, because it is rendered server-side with no JS, so its build time is explicit UTC and labelled as such. Verified by rendering: Europe/Berlin gives "2026-08-11 17:39 CEST", Asia/Shanghai "23:39 CST", an unknown zone falls back to "15:39 UTC", and /about with BUILD_TIME set gives "2025-08-11 08:13:20 UTC".
The last ten findings, none of which ruff can fix safely: - crawlers/__init__.py imported List and Union that nothing uses. The autofix rewrote the string annotation on query_sync() but left the import, because it cannot prove a string annotation is the only reference (F401, UP035). - close_http_client() declared `global _CLIENT` but only reads it, so the statement did nothing (PLW0602). init_http_client() keeps its own, which does assign. - Three tests asserted by evaluating a bare attribute inside pytest.raises. The access is the assertion, so binding the result to `_` keeps the intent and satisfies B018 without a suppression comment. - Three temp PDFs used NamedTemporaryFile(delete=False), which SIM115 reads as a leaked handle. _write_temp_pdf() already existed for exactly this, so it now uses mkstemp with a context manager and the other two call sites route through it instead of repeating the pattern. ./doit.sh lint passes.
docs/dev/python.md told contributors the opposite of what the code now does: "Use Dict, List, Union from the typing module". Ruff 0.16's defaults rewrite exactly that, and the format-lint hook applies the rewrite on every edit, so the old rule was both wrong and unenforceable. Two sections change: - Typing states the built-in generics and | unions, names the four rules that enforce it, and points at ADR 0016 for why it reversed. - Import order was wrong independently of the bump. It read "standard library → third-party → typing", but typing and collections.abc *are* standard library and I001 sorts them into that first group. The three query() templates in docs/dev/crawlers.md get the same treatment. They are copied verbatim into new crawler files, so a stale template would have reintroduced the old style on the next crawler. Also records the eolymp GraphQL follow-up in docs/BACKLOG.md: passing the username as a query variable would drop both the manual quote escaping and the # noqa: UP031, but it changes the request payload and needs its own network verification.
The lint task ran `ruff check` only, so `ruff format` drift never failed CI. Ruff 0.16 made that gap visible: it formats python blocks inside markdown, and four documentation files had drifted without any check noticing. Both passes now run unconditionally rather than short-circuiting on the first failure, so one `.doit/lint.log` lists every problem instead of hiding the formatter behind the linter. Verified by injecting a badly formatted line into a markdown code block: the task exits 1 and the log shows the diff.
Contributor
Merge Queue Status
This pull request spent 3 minutes 54 seconds in the queue, including 3 minutes 25 seconds running CI. Required conditions to merge
|
3 tasks
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.
Bumps ruff from 0.15.22 to 0.16.0.
Release notes
Sourced from ruff's releases.
... (truncated)
Changelog
Sourced from ruff's changelog.
... (truncated)
Commits
a2635fdBump 0.16.0 (#27136)3433449[ty] Reuse full call diagnostics for implicit setter calls (#27115)2240070Reflectruff: ignoreand--add-ignorestabilization in documentation (#27...17ef711Stabilize--add-ignore(#27125)ef912bbAdd newly stabilized rules to defaults (#27055)b30f040Stabilize new default rules (#27035)bcd70c5Exclude Markdown files fromformat-devruns (#27052)87e51e2Fixformat --checkspans for syntax errors (#27045)afe2723[flake8-gettext] Stabilize qualified-name and built-in binding resolution (...a9702d8[flake8-bandit] Stabilize string literal binding resolution (S310) (#26944)Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)