fix(reg): cast TransportProtocol.undefined so mypy infers its own type - #777
Conversation
|
Cross-review at Confirmed, and more strongly than claimed. mypy goes 116/39 → 112/38, and the error lists were R1 — the new mypy test cannot run on any CI job, and does not say so. R2 — a false claim in the new comment, in both files, and it ships as published API documentation. The comment calls There is no composition below in either file the comment lives in, and the 5,287 compositions in the sibling modules never mention One stated measurement does not survive, though the conclusion does. The PR rejects the explicit annotation as leaving the "net error count unchanged". Measured, it gives 113 errors in 39 files, not 116 — it removes three of the four and leaves one at the declaration. So the right reason to prefer Three smaller test issues: A useful finding for #773, which owns |
79e8699 to
19b3617
Compare
|
Cross-review at 1. The 2. A transient agent-coordination fact baked into a permanent docstring, pointing at the wrong issue. R1's mechanism independently reproduced, twice over. The reviewer re-created Route 1 in a scratch worktree touching only the test file and got exactly the claimed Everything else held up under independent reproduction. Every R2 clause checked live: One coverage note, not a change request: of the three new tests, two fail against Routed to the worker. Label moves to |
#770) - mypy has no aenum plugin, so TransportProtocol is a plain class to it. undefined = 0 is a bare int literal, inferring as int, while the auto()-valued siblings infer as Any -- the only member that then disagreed with the four sites defaulting to it: the class attribute __transport__, and the proto parameter on __new__, get and get_all. - Wrap the literal in typing.cast in the BASE template (pcapkit/vendor/reg/apptype/apptype.py) so mypy infers TransportProtocol instead. cast is the identity function at run time, so undefined stays exactly 0 and still composes, and regenerating from a byte-identical cached IANA fetch changes only this member's comment and assignment in pcapkit/const/reg/apptype/apptype.py -- tcp/udp/sctp/dccp.py are untouched, member counts (6147/6143/91/10) unchanged, and every member's name/port/svc/proto/value is unchanged. - Give the member a one-line #: contract instead of the mypy rationale: Sphinx autodocs it with :undoc-members:, and would otherwise publish the cast's reasoning as the member's own rendered description. - Add tests pinning the fix: source-text shape (bounded failure messages, not raw assertIn/assertNotRegex against the ~200 KiB generated module), a direct mypy.api.run check, and a runtime guard that undefined is still 0 and composes. The mypy check skips inline when mypy is unavailable -- it is a Pipfile dev-package, not a pyproject.toml extra -- rather than a tracked HAS_MYPY gate, which was measured to break tests/test_tier_guard.py's DependencyGateCoverageTests (mypy has no MODULE_PROVIDERS entry); #779 tracks that gap. mypy on the whole package: 116 errors/39 files -> 112/38, matching lint.yml's existing pin (measured at 932cb48, unaffected by this).
19b3617 to
47849d1
Compare
|
Round-three cross-review at Both required changes verified independently rather than re-read. For the bounded check it reverted the const module's
The unprompted third fix checks out too, which is the one I most expected to be wrong. One commit sitting directly on Settled in earlier rounds and not re-run: the R2 docstring clauses, the live-IANA regeneration, Ten CI legs still outstanding on this head, so this is a review verdict rather than a merge signal. |
make pylint,make mypy,make isort)make testpasses, and a test case covers the change — ran the scoped test file only (coverage+pytestand plainunittest), not the full suite, per this host's OOM historydocs/source/changelog/and regeneratedCHANGELOG.md— N/A, changelog centralised in docs(changelog): shared 1.5.0 changelog — long-lived, merges last (#610, #616, #617, #618, #620) #657; no behaviour change, thoughundefineddoes gain a rendered Sphinx description it previously lacked as an undoc-member (see below)What is the purpose of your pull request?
fix— corrects a defectDescription of your pull request and other information
Fixes #770.
mypy has no
aenumplugin, soTransportProtocolis a plain class to it.undefined = 0in theBASEtemplate is a bare int literal, inferring asint, while theauto()-valued siblings infer asAny— the only memberthat then disagreed with the four sites defaulting to it: the class
attribute
__transport__, and theprotoparameter on__new__,getand
get_all.Wraps the literal in
typing.castinstead, in the vendorBASEtemplateonly, then regenerates.
castis the identity function at run time, soundefinedstays exactly0and still composes(
tcp | undefined is tcp). Regenerating from a byte-identical cached IANAfetch changes only this member's comment and assignment in the generated
base module;
tcp.py/udp.py/sctp.py/dccp.pyare untouched, and everymember's name/port/svc/proto/value plus the counts (6147/6143/91/10) are
unchanged.
TransportProtocolis autoclassed with:undoc-members:(
docs/source/pcapkit/const/reg.rst), soundefined's comment is split:a one-line
#:contract (TransportProtocol(0) is undefined, theprotosentinel default, what
_missing_extends from) is what Sphinx renders,and the mypy/
castrationale stays in an adjacent plain#comment Sphinxdoes not pick up.
mypy.inisetswarn_redundant_casts, so this alsomeans the cast starts erroring on its own the day
aenumships stubs thatlet mypy infer the type without it, rather than lingering unnoticed.
Two rejected alternatives, measured: an explicit member annotation
(
undefined: 'TransportProtocol' = 0) does not fix the disagreement, itonly relocates it — one
[assignment]at the member's own declarationline, 113 errors/39 files rather than 116, so
cast(112/38) wins on beingthe only one that reaches zero, not on parity.
auto() & 0is run-timeidentical to the bare literal (value
0, no burned counter slot, siblingsunaffected) and is rejected only because it leans on
aenum's undocumentedinternal handling of a composed
auto(), not because it misbehaves.mypy on the whole package: 116 errors/39 files → 112/38.
lint.yml's ownpin (112/38, measured at
932cb48d1) already matches this count, so itneeds no change here.
Tests added: the generated source's shape, a direct
mypy.api.runcheck,and a runtime guard that
undefinedis still0and composes. The shapecheck uses a plain containment test rather than
assertIn/assertNotRegexdirectly — both format their default failure message from the whole
~200 KiB generated module (measured: 219,113 chars for a bare
assertInon this source), so a failure instead gets a short, bounded message.
The mypy check skips inline when mypy is not importable — it's a
Pipfile[dev-packages]entry, not apyproject.tomlextra, so nounit-tests.ymljob ever has it. Gating that instead with a trackedHAS_MYPYflag was measured and rejected:mypyhas noMODULE_PROVIDERSentry intests/_dependency_gates.py, so adding thegate breaks
tests/test_tier_guard.py'sDependencyGateCoverageTestsoutright (4 errors, 2 failures of its 9, measured). #779 tracks closing
that gap; neither file is edited here.