Add a tox target for checking dependency freshness #4

Open
justine wants to merge 2 commits from chore/outdated-target into main
Owner

Closes #3

What changed

uv run tox -e outdated reports every direct dependency against its latest PyPI release, via scripts/check_outdated.py. Dependency names are read from pyproject.toml, so the script cannot drift as they change.

group      package        installed      latest         status
--------------------------------------------------------------
runtime    click          8.4.2          8.4.2          current
runtime    pluggy         1.6.0          1.6.0          current
...
All 12 checked dependencies are current.

Three deliberate choices, all confirmed before building:

Choice Reason
On demand, not in default run or CI A new upstream release is news, not a build failure
Exit 0 regardless The script reports; you decide
Direct dependencies only Transitive versions belong to the lockfile and cannot be bumped directly

It prints a row per dependency even when nothing is behind, because uv pip list --outdated prints nothing when everything is current and that is indistinguishable from the check not running. Packages that could not be compared are counted separately, never folded into a clean result.

Incidental fix

This is the first script outside src/ and tests/, and it exposed a gap: lint, format, mypy, and pyright all take explicit paths, so they silently ignored scripts/. Adding it to each surfaced three real findings in the new file. All four gates now cover it.

Filename effect

None. No naming logic changed.

Constraints

  • Read commands still mutate nothing — the script only reads and prints

Verification

$ uv run tox
  license, lint, format, typecheck, pyright, test — all OK

$ uv run tox -e outdated
  All 12 checked dependencies are current.

Detection was verified by forcing a stale version, which correctly reported ruff 0.0.1 → 0.16.3 OUTDATED and 1 of 12 checked dependencies are behind.

Closes #3 ## What changed `uv run tox -e outdated` reports every direct dependency against its latest PyPI release, via `scripts/check_outdated.py`. Dependency names are read from `pyproject.toml`, so the script cannot drift as they change. ``` group package installed latest status -------------------------------------------------------------- runtime click 8.4.2 8.4.2 current runtime pluggy 1.6.0 1.6.0 current ... All 12 checked dependencies are current. ``` Three deliberate choices, all confirmed before building: | Choice | Reason | |---|---| | On demand, not in default run or CI | A new upstream release is news, not a build failure | | Exit 0 regardless | The script reports; you decide | | Direct dependencies only | Transitive versions belong to the lockfile and cannot be bumped directly | It prints a row per dependency even when nothing is behind, because `uv pip list --outdated` prints nothing when everything is current and that is indistinguishable from the check not running. Packages that could not be compared are counted separately, never folded into a clean result. ## Incidental fix This is the first script outside `src/` and `tests/`, and it exposed a gap: lint, format, mypy, and pyright all take explicit paths, so they silently ignored `scripts/`. Adding it to each surfaced three real findings in the new file. All four gates now cover it. ## Filename effect None. No naming logic changed. ## Constraints - [x] Read commands still mutate nothing — the script only reads and prints ## Verification ```console $ uv run tox license, lint, format, typecheck, pyright, test — all OK $ uv run tox -e outdated All 12 checked dependencies are current. ``` Detection was verified by forcing a stale version, which correctly reported `ruff 0.0.1 → 0.16.3 OUTDATED` and `1 of 12 checked dependencies are behind`.
Add a tox target for checking dependency freshness
All checks were successful
CI / check (pull_request) Successful in 51s
PR / issue-link (pull_request) Successful in 2s
64ef9e74e0
Closes #3

`uv run tox -e outdated` compares every direct dependency in pyproject.toml
against its latest PyPI release. It reads the dependency names from the file
rather than hardcoding them, so it cannot drift as dependencies change.

It prints a row per dependency whether or not anything is behind, because
`uv pip list --outdated` prints nothing when everything is current and that is
indistinguishable from the check not having run. Packages it could not compare
are counted separately and never folded into a clean result — an unreachable
PyPI or a missing install otherwise looks exactly like up-to-date.

On demand only: not in the default env_list and not in CI, exiting 0 either
way. A new upstream release is news, not a build failure, and gating on it
turns an unrelated pull request red because ruff shipped that morning. Direct
dependencies only, since transitive versions belong to the lockfile and move
when a parent moves.

Writing the first script outside src/ and tests/ exposed a gap: lint, format,
mypy, and pyright all took explicit paths and so silently ignored it. Three
findings appeared once scripts/ was added to each. Extend the four gates
rather than leave a directory that no gate covers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018XhA69mkFRwmkhrDvRsQLW
Correct an unverified claim about the except-clause rewrite
All checks were successful
CI / check (pull_request) Successful in 59s
PR / issue-link (pull_request) Successful in 2s
a2e313677d
Ref #3

The comment added with this script asserted that `ruff format` strips the
parentheses from this except clause because of `target-version = "py314"`.
That was written from a plausible inference, not a test, and it is wrong.

Six attempts failed to reproduce the rewrite in isolation: `--target-version`
py313 against py314, a real pyproject.toml carrying the project's own config,
lines above and below the 88-column limit, a comment between the try body and
the except clause, and the presence of `from __future__ import annotations`.
Every isolated case keeps the parentheses. This file loses them every time.

What triggers it here is unidentified, so the comment now says that rather
than naming a cause. The unparenthesized form is valid PEP 758 syntax from
3.14 and the formatter is stable on it, so the file is left as the formatter
wants it; only the explanation changes.

Worth recording separately: this repeats the pluggy comment failure from
earlier today, where behavior was observed and a mechanism invented to explain
it. The rule written to prevent that names third-party libraries, and a
formatter quirk did not read as one, so the trigger never fired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018XhA69mkFRwmkhrDvRsQLW
All checks were successful
CI / check (pull_request) Successful in 59s
PR / issue-link (pull_request) Successful in 2s
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin chore/outdated-target:chore/outdated-target
git switch chore/outdated-target

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff chore/outdated-target
git switch chore/outdated-target
git rebase main
git switch main
git merge --ff-only chore/outdated-target
git switch chore/outdated-target
git rebase main
git switch main
git merge --no-ff chore/outdated-target
git switch main
git merge --squash chore/outdated-target
git switch main
git merge --ff-only chore/outdated-target
git switch main
git merge chore/outdated-target
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
justine/fname!4
No description provided.