Skip to content

fix: resolve typing errors surfaced by strict downstream mypy - #329

Merged
henryiii merged 1 commit into
pypa:mainfrom
henryiii:fix/downstream-strict-mypy
Jul 3, 2026
Merged

fix: resolve typing errors surfaced by strict downstream mypy#329
henryiii merged 1 commit into
pypa:mainfrom
henryiii:fix/downstream-strict-mypy

Conversation

@henryiii

@henryiii henryiii commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

🤖 AI text below 🤖

Vendoring this package into scikit-build-core and type-checking it there (mypy 2.x, python_version = "3.10", strict) surfaced 7 typing errors in the PEP 808 code that this repo's own mypy never saw. The reason: the mypy nox session pinned the checker to Python 3.8, which pulls the last 3.8-compatible mypy (1.14.1), while mypy 2.x refuses any target below 3.10 and is stricter.

Tightening (to catch this going forward):

  • Run the mypy session under Python 3.10 (so it uses mypy 2.x).
  • Set python_version = "3.10" in [tool.mypy] to pin the target explicitly.

Fixes:

  • Widen the get_* helper signatures in pyproject.py from dict[str, Any] to ProjectTable (matching get_license), so the ProjectTable cast in from_pyproject is assignable. These helpers only read the mapping.
  • Read the dynamic loop field as a plain str: with error collection the raw list can still contain values outside the Dynamic literal (e.g. the invalid "name") that the existing defensive check guards against.
  • Drop the now-unused comparison-overlap ignore on type_hint is Any.

Runtime behavior is unchanged; all 403 tests pass.

scikit-build-core vendors this package and type-checks it under mypy 2.x
targeting Python 3.10, which flagged 7 errors introduced by the PEP 808
work that this repo's own mypy session never saw: it pinned the checker
to Python 3.8, pulling the last 3.8-compatible mypy (1.14.1), whereas
mypy 2.x requires a target of 3.10 or newer.

Run the mypy session under Python 3.10 and set python_version = "3.10"
so a regression like this is caught here going forward, and fix the
errors it surfaces:

- Widen the get_* helper signatures in pyproject.py from dict[str, Any]
  to ProjectTable (matching get_license) so the ProjectTable cast in
  from_pyproject is assignable; these helpers only read the mapping.
- Read the dynamic loop field as a plain str, since with error
  collection the raw list can still hold values outside the Dynamic
  literal (e.g. the invalid "name") that the defensive check guards.
- Drop the now-unused comparison-overlap ignore on `type_hint is Any`.

Assisted-by: ClaudeCode:claude-opus-4.8
@henryiii
henryiii marked this pull request as ready for review July 3, 2026 20:21
@henryiii
henryiii merged commit 600a382 into pypa:main Jul 3, 2026
26 checks passed
@henryiii
henryiii deleted the fix/downstream-strict-mypy branch July 3, 2026 20:21
henryiii added a commit to scikit-build/scikit-build-core that referenced this pull request Jul 4, 2026
* chore: bump vendored pyproject-metadata to 0.12.0

Brings PEP 808 (partially-dynamic project metadata / METADATA 2.6),
the PEP 685 invalid-extra-name warning, and assorted fixes. Includes
the upstream typing fixes (pypa/pyproject-metadata#329) so the vendored
copy type-checks cleanly under scikit-build-core's strict mypy.

Assisted-by: ClaudeCode:claude-opus-4.8

* feat(metadata): emit METADATA 2.6 for PEP 808 dual-dynamic fields

When a field is given a static value in [project] and also listed in
project.dynamic (PEP 808), and a dynamic-metadata provider marks it as
possibly changing in the wheel (dynamic_wheel), the SDist now emits
Metadata-Version 2.6 with the static value alongside the Dynamic header,
instead of 2.2. A dual field a provider merely extends (no dynamic_wheel)
is still fully resolved into the SDist and stays pre-2.6.

process_dynamic_metadata drops resolved fields from dynamic, so
from_pyproject can no longer detect the dual case; the dual set is
captured beforehand and re-attached to the metadata object.

Assisted-by: ClaudeCode:claude-opus-4.8

* fix(metadata): skip non-string project.dynamic entries in PEP 808 scan

The dual-dynamic comprehension ran membership tests on each dynamic
entry before pyproject-metadata validates the list. A non-string
(unhashable) entry would raise TypeError here rather than letting the
library report it. Guard with isinstance so from_pyproject surfaces the
config error instead. See pypa/pyproject-metadata#331 for the mirrored
crash still present in the vendored library itself.

Assisted-by: ClaudeCode:claude-opus-4.8

* chore: bump vendored pyproject-metadata to 0.12.1

Picks up the isinstance guard for non-string project.dynamic entries
(pypa/pyproject-metadata#331), so from_pyproject now reports a collected
config error instead of a raw TypeError on malformed dynamic lists.

Assisted-by: ClaudeCode:claude-opus-4.8
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