Skip to content

CI: add linting and type checking#8

Merged
shenanigansd merged 1 commit into
mainfrom
br/ci
Jun 20, 2026
Merged

CI: add linting and type checking#8
shenanigansd merged 1 commit into
mainfrom
br/ci

Conversation

@shenanigansd

Copy link
Copy Markdown
Member

Failing on existing issues right now, cleanup will come later.

Signed-off-by: Bradley Reynolds <bradley.reynolds@tailstory.dev>
@shenanigansd shenanigansd requested a review from Copilot June 20, 2026 22:22
@shenanigansd shenanigansd self-assigned this Jun 20, 2026
@shenanigansd shenanigansd merged commit e106c5c into main Jun 20, 2026
6 of 7 checks passed
@shenanigansd shenanigansd deleted the br/ci branch June 20, 2026 22:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces Python linting and type-checking automation for the repository (via uv + GitHub Actions), along with local developer tooling (nox + pre-commit/prek) and some formatting cleanups in the existing stdlib tooling scripts.

Changes:

  • Add a new CI workflow to run prek, Ruff (format + lint), mypy, and ty using uv.
  • Add project metadata and tool configuration (pyproject.toml), plus lockfile (uv.lock) and local noxfile.py.
  • Reformat/normalize the existing tools/*.py scripts and harden GitHub Actions checkout settings.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
uv.lock Adds a uv lockfile capturing the dev toolchain dependencies.
pyproject.toml Defines project metadata, dev dependency group, and config for uv/Ruff/mypy/ty.
noxfile.py Adds local nox sessions for running lints and cleaning caches/artifacts.
.pre-commit-config.yaml Adds pre-commit/prek hooks including uv-lock and zizmor.
tools/stdlib_introspect.py Formatting changes; currently introduces a Python 3 syntax error in an except clause.
tools/merge_summary.py Formatting changes; currently introduces a Python 3 syntax error in an except clause.
tools/coverage_diff.py Formatting-only adjustments and minor normalization changes.
.github/workflows/stdlib-introspect.yaml Ensures checkout does not persist credentials.
.github/workflows/python-ci.yaml Adds CI job to run linting/type checks with uv.
.github/dependabot.yaml Extends Dependabot config to cover uv and pre-commit ecosystems.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/stdlib_introspect.py
Comment thread tools/merge_summary.py
Comment thread pyproject.toml
shenanigansd pushed a commit that referenced this pull request Jun 20, 2026
The stdlib-introspect matrix runs these scripts on Python 3.10-3.15, but
the previous commit (and #8) left them using newer syntax that 3.10-3.13
cannot parse:
- PEP 695 `type X = ...` aliases -> `TypeAlias`
- PEP 758 parenthesis-free `except A, B:` -> parenthesized

Add tools/ruff.toml pinning target-version = py310 (extending the root
config) so Ruff lints these files at the matrix floor rather than the
repo's dev requirement -- otherwise UP040 demands the `type` statement
back. That lower target re-enables PERF203 (a no-op once exceptions are
zero-cost), so ignore it for the tools' I/O retry/parse loops.

The rest of the modernization (annotations, pathlib, itertools.pairwise,
docstrings, dropped __future__ import) is already 3.10-compatible and
stays. Verified: ruff/mypy/ty/prek pass on the 3.14 dev env; all three
tools compile on 3.10, and stdlib_introspect + merge_summary run there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rh5G5LSDPMWLgX3cYLWUnk
shenanigansd added a commit that referenced this pull request Jun 20, 2026
…int CI (#10)

* Modernize tools, drop __future__ annotations, fix lint CI

The lint CI pointed mypy at directories that don't exist
(src/packages/tests) while the real code lives in tools/, the code
carried no annotations (so mypy --strict and ruff's ANN/D rules failed),
the mypy config loaded a pydantic plugin that isn't a dependency, and
coverage_diff's sphobjinv import was unresolved for the type checkers.

Tooling:
- Point mypy at tools/ + noxfile.py in the workflow and the noxfile
- Declare sphobjinv as a dependency so `uv sync` resolves it; tell mypy
  it ships no py.typed marker
- Drop the unused pydantic.mypy plugin
- Curate a ruff ignore list for select=ALL: formatter conflicts, the TC
  family (it assumes stringized annotations), and per-file allowances for
  CLI print / boolean-trap / arg-count / broad-except / url-open

Code:
- Remove `from __future__ import annotations` from all three tools
- Add full type annotations; PEP 695 `type` aliases for the record and
  version-key shapes
- pathlib over os.path/glob/open; itertools.pairwise over zip(x, x[1:]);
  a dict comprehension for the union build
- Name the magic comparison values and add docstrings
- Drop the now-dead sys.stdlib_module_names guard and an unused
  _markdown_summary parameter

ruff (format + check), mypy --strict, ty, and prek all pass; the three
tools still run end-to-end (introspect -> merge -> coverage diff).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rh5G5LSDPMWLgX3cYLWUnk

* Keep tools/ on the 3.10 matrix floor; scope Ruff target there

The stdlib-introspect matrix runs these scripts on Python 3.10-3.15, but
the previous commit (and #8) left them using newer syntax that 3.10-3.13
cannot parse:
- PEP 695 `type X = ...` aliases -> `TypeAlias`
- PEP 758 parenthesis-free `except A, B:` -> parenthesized

Add tools/ruff.toml pinning target-version = py310 (extending the root
config) so Ruff lints these files at the matrix floor rather than the
repo's dev requirement -- otherwise UP040 demands the `type` statement
back. That lower target re-enables PERF203 (a no-op once exceptions are
zero-cost), so ignore it for the tools' I/O retry/parse loops.

The rest of the modernization (annotations, pathlib, itertools.pairwise,
docstrings, dropped __future__ import) is already 3.10-compatible and
stays. Verified: ruff/mypy/ty/prek pass on the 3.14 dev env; all three
tools compile on 3.10, and stdlib_introspect + merge_summary run there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rh5G5LSDPMWLgX3cYLWUnk

* Limit 3.10 support to stdlib_introspect; modernize the other two

Only stdlib_introspect.py runs across the introspect matrix (3.10-3.15);
merge_summary.py and coverage_diff.py run on the aggregate/coverage jobs'
"3.x", so they don't need legacy support. The previous commit pinned all
of tools/ to py310 via tools/ruff.toml, which over-applied the floor.

Ruff's target-version is directory-scoped, not per-file, so instead of a
directory config this scopes the one genuine conflict precisely:
- stdlib_introspect.py keeps `TypeAlias` and ignores UP040 (which would
  demand the 3.12 `type` statement) for that file only. Its
  `except (ValueError, TypeError)` becomes `contextlib.suppress(...)` --
  3.10-safe, idiomatic (SIM105), and not something the py314 formatter
  rewrites into the parenthesis-free PEP 758 form.
- merge_summary.py and coverage_diff.py go back to PEP 695 `type` aliases
  and lint at the repo's py314 default.

Drop tools/ruff.toml and the PERF203 ignore (a no-op once try/except is
zero-cost, which is where these two now lint).

Verified: ruff/mypy/ty/prek pass; stdlib_introspect compiles and runs on
3.10, while the other two use modern-only syntax and run on 3.14.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rh5G5LSDPMWLgX3cYLWUnk

* Address PR review: implicit string concat + http_get guard

- CodeQL (implicit-string-concatenation-in-list): the line-wrapped prose
  strings in the report() blocks are now extracted to named locals
  (no_cells, deltas_intro, core_breakdown), matching the no_versions /
  intro style already used elsewhere. No behavior change; clears the alert
  and the missing-comma ambiguity.
- Copilot (coverage_diff.http_get): guard `attempts < 1` with a ValueError
  so a bad argument no longer falls through to the end-of-function
  AssertionError, which is now genuinely unreachable.

ruff/mypy/ty pass; merge_summary and coverage_diff still run end-to-end.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rh5G5LSDPMWLgX3cYLWUnk

---------

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants