Repository navigation
fix(corekit): finalise each non-final Info subclass on its own state (#1490) - #1496
Merged
Merged
Conversation
Owner
Author
|
Verdict: GOOD TO GO at
Non-blocking: a user subclass with no
|
…1490) Info.__new__ read __finalised__ through inheritance, so once a non-final parent had been built its non-final children read the parent's BASE and were never finalised. They kept the __excluded__ copied at declaration, and to_dict(), len() and iteration leaked __map__, __map_reverse__ and __multi__. Read the state from the class's own __dict__ instead. - tests/corekit: new per-order tests, each order in a fresh interpreter, over a synthetic pair and six real models; drop the #1490 Gap row and flip the root-cause pin. - tests/test_final_enforcement.py: a @Final class under a BASE ancestor is now refused, and a child predating its parent's finalisation gets its own __init__.
JarryShaw
force-pushed
the
fix/1490-info-child-finalisation
branch
from
October 9, 2026 20:14
9e86cf0 to
e7d02d1
Compare
Owner
Author
2 of 13 tasks
Contributor
|
Coverage: 89.65% (unit tier, Python 3.14,
Per-file detail: the |
JarryShaw
added a commit
that referenced
this pull request
Oct 9, 2026
…#1498) (#1499) Schema.__new__ read __finalised__ through inheritance, so once a non-final parent had been built its non-final children read the parent's BASE and were never finalised: they kept the __excluded__ copied at declaration and to_dict() leaked __map__, __map_reverse__, __buffer__ and __updated__. Read the class's own __dict__ instead, as #1496 does for Info. This also closes the documented gap where a bare @Final under a BASE ancestor escaped the guard, so its Warning becomes a Note. The shipped instances are the Quick-Start option schemas of HOPOPT, IPv6-Opts and IPv4.
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.
Please follow the guide below
You will be asked some questions, please read them carefully and answer honestly
Put an
xinto all the boxes [ ] relevant to your pull request (like that [x])Use Preview tab to see how your pull request will actually look like
Searched for similar pull requests
Followed the coding style (
make pylint,make mypy,make isort)make testpasses, and a test case covers the changeAdded a changelog entry under
docs/source/changelog/and regeneratedCHANGELOG.md, if the change is user-visible — N/A — centralised in docs(changelog): shared 1.5.0 changelog — long-lived, merges last (#610, #616, #617, #618, #620) #657What is the purpose of your pull request?
Tick the commit type your subject line carries.
fix— corrects a defectfeat— adds a featureperf— changes performance, not behaviourrefactor— changes neither behaviour nor performancetest— tests onlydocs— documentation onlyci— workflows or build toolingrelease— bumps the version or rolls up a distributionchore— anything elseDescription of your pull request and other information
Info.__new__now reads__finalised__from the class's own__dict__(pcapkit/corekit/infoclass.py:424), so a non-final child is finalised on its first construction whatever its parent's state. Before, it inherited the parent'sBASE, kept the__excluded__copied at declaration, and leaked__map__,__map_reverse__,__multi__fromto_dict(),len()and iteration.tests/corekit/test_info_child_finalisation_1490_unit.py: parent-first and child-first, each in a fresh interpreter, over a synthetic pair and six real models (hopopt/ipv6_optsQuickStartOption,SMFDPDOption,ipv4.QSOption,tcp.MPTCPJoin). Onmain'sinfoclass.pyall six parent-first cases fail; child-first passes on both.test_info_roundtrip_unit.py: the fix(corekit): a non-final Info subclass built after its parent leaks internal keys from to_dict() #1490Gaprow is gone and the root-cause pin asserts['a', 'b'].test_final_enforcement.py: two behaviour changes follow. A@finalclass under aBASEancestor is now refused, closing the gap that test documented. A child declared before its parent was finalised now gets its own__init__.Ran: the new test,
tests/corekit,tests/protocols/internet,tests/protocols/transport,test_capture_roundtrip_runtime.py,tests/project,test_docstring_contract.py,test_final_enforcement.py, all green.repr(frame.info.to_dict())hashes overexamples/captures(23 files) are identical tomain.Closes #1490