Repository navigation
fix(toolkit): a copied DecimalTimestamp keeps orig_len under _pydecimal (#1647) - #1653
Merged
Merged
Conversation
…al (#1647) - copy.copy and copy.deepcopy ask for __copy__ and __deepcopy__ before __reduce_ex__, and decimal.Decimal defines both. The C _decimal returns self; the pure-Python _pydecimal returns self.__class__(str(self)), so a DecimalTimestamp came back with the default resolution and no orig_len. CPython 3.15 dropped its fallback to the bundled libmpdec, and the actions/setup-python 3.15.0 build has no _decimal, so only that leg failed. - RecordTimestamp now answers __copy__, __deepcopy__ and __reduce_ex__ from each subclass's own __reduce__, ahead of the numeric base in the MRO; its own __reduce__ raises NotImplementedError rather than guessing. New tests/toolkit/test_dpkt_timestamp_copy_1647_unit.py round-trips both classes through copy, deepcopy and pickle protocols 0..HIGHEST, in process and under _pydecimal in a fresh interpreter. Without the fix 5 fail on 3.15, 3.14 and 3.11; with it, 4 passed (37 subtests) on each.
Owner
Author
|
Verdict: GOOD TO GO at |
Contributor
|
Coverage: 89.67% (unit tier, Python 3.14,
Per-file detail: the |
This was referenced Oct 13, 2026
This was referenced Oct 13, 2026
Merged
JarryShaw
added a commit
that referenced
this pull request
Oct 14, 2026
Third-party engines are best effort (#1687), so the dpkt code that exists only to match the default engine comes out: - revert #1662, #1655, #1624, #1622, #1614 and the dpkt hunks of #1605: the octet walk and its link-type stash, IPv6 in IPv4 and IPv4 in IPv6, refusing MPLS and ISL, the tunnel and extension-header walks, the IPv4 header checks and the layer bounds - keep #1690's timestamps, #1594's parser choice, #1621 and #1653 - re-land as guards: a layer dpkt's own lengths misplace (#1646) is re-serialised, not refused with ProtocolError; a Total Length below the IHL keeps the header whole (#1616), and a header the capture cuts is no input; packet2dict and packet2chain take a str payload and a raw frame - delete the modules #1662 and #1655 added; the 1615/1616 module keeps only what its #1616 tests use, as no scapy test imports it now; dpkt's comparisons with the default engine assert constants or the capture's octets, or are dropped - drop pypcapfile's VLAN_TAGS, VLAN_TAG_LEN and IPV6_EXTENSION_HEADERS, which only dpkt imported, and the 1668 module's _Agreement base, which nothing subclasses now - the docs drop the depth claims and name what dpkt leaves out silently The dpkt modules, the shared modules that run dpkt, tests/foundation/engines and the project guards pass on 3.14 and 3.11 (dpkt 1.9.8, pypcapfile 0.12.0).
JarryShaw
added a commit
that referenced
this pull request
Oct 14, 2026
Third-party engines are best effort (#1687), so the dpkt code that exists only to match the default engine comes out: - revert #1662, #1655, #1624, #1622, #1614 and the dpkt hunks of #1605: the octet walk and its link-type stash, IPv6 in IPv4 and IPv4 in IPv6, refusing MPLS and ISL, the tunnel and extension-header walks, the IPv4 header checks and the layer bounds - keep #1690's timestamps, #1594's parser choice, #1621 and #1653 - re-land as guards: a layer dpkt's own lengths misplace (#1646) is re-serialised, not refused with ProtocolError; a Total Length below the IHL keeps the header whole (#1616), and a header the capture cuts is no input; packet2dict and packet2chain take a str payload and a raw frame - delete the modules #1662 and #1655 added; the 1615/1616 module keeps only what its #1616 tests use, as no scapy test imports it now; dpkt's comparisons with the default engine assert constants or the capture's octets, or are dropped - drop pypcapfile's VLAN_TAGS, VLAN_TAG_LEN and IPV6_EXTENSION_HEADERS, which only dpkt imported, and the 1668 module's _Agreement base, which nothing subclasses now - the docs drop the depth claims and name what dpkt leaves out silently The dpkt modules, the shared modules that run dpkt, tests/foundation/engines and the project guards pass on 3.14 and 3.11 (dpkt 1.9.8, pypcapfile 0.12.0).
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
Cause.
copy.copyandcopy.deepcopylook up__copy__and__deepcopy__before__reduce_ex__(Lib/copy.py:80,:136at v3.15.0), andDecimaldefines both. The C_decimalreturnsself._pydecimalreturnsself.__class__(str(self))(Lib/_pydecimal.py:3716-3724), so the clone takes the constructor's defaults. 3.15 "Removed implicit fallback to the bundled copy of thelibmpdeclibrary" (What's New, Build changes). Theactions/setup-python3.15.0 build has no_decimal(MODULE__DECIMAL_STATE: 'missing'), so only that leg runs on_pydecimal. Pickle was never affected, because it reaches the class's own__reduce__.Fix.
RecordTimestampanswers__copy__,__deepcopy__and__reduce_ex__from each subclass's__reduce__, and comes before the numeric base in the MRO (pcapkit/toolkit/dpkt.py:122-134). Its own__reduce__raisesNotImplementedError.Tests. New
tests/toolkit/test_dpkt_timestamp_copy_1647_unit.pyruns both classes throughcopy,deepcopyand pickle protocols 0..HIGHEST, in process and under_pydecimalin a fresh interpreter. Without the fix, 5 tests fail on 3.15, 3.14 and 3.11 (resolution1000000 → 1000000000,orig_len78 → None). With it, 4 pass (37 subtests) on each. #1645's failing test also passes with_decimalblocked.Closes #1647