Skip to content

fix(registry): foundation registrars restore the built-in a name shipped with (#1363) - #1376

Merged
JarryShaw merged 1 commit into
mainfrom
fix/1363-restore-builtin-registrars
Oct 8, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/1363-restore-builtin-registrars

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner
  • Searched for similar pull requests
  • Followed the coding style — ran isort -l100 -ppcapkit (clean), and pylint/mypy on the three files: no new messages against origin/main. make targets not run.
  • make test passes, and a test case covers the change — the modules listed below only, not the whole suite
  • Changelog entry — N/A, added centrally

What is the purpose of your pull request?

  • fix — corrects a defect

Description of your pull request and other information

Refs #1363 (option 1; the protocol and option registrars follow under #1362). Refs #1364 (dumper half only).

The engine, reassembly and traceflow registrars accept the built-in a name shipped with, as a descriptor or as the class it names, and restore the shipped entry. Both dumper registrars do the same for the shipped (descriptor, ext) pair. Every other built-in is still refused (#1016). The registries are snapshotted at class definition. The shipped entry is matched through sys.modules, so an optional engine is never imported to recognise it. Re-registering the original over itself is a silent no-op. Restoring over an override warns, as any overwrite does.

Probe (check_10): on origin/main, register_extractor_engine('dpkt', MyEngine) then ('dpkt', DPKT) raises RegistryError: engine must be an Engine subclass. With the fix the restore succeeds and Extractor.__engine__ is identical to the snapshot (is for each entry). The same holds for reassembly ipv4/ipv6/tcp, traceflow tcp and dumper json.

Tests: the new tests/foundation/registry/test_restore_builtin_unit.py passes 8 tests. With git show origin/main:<src> written over the sources, 7 fail (5 failed, plus subtest failures for ipv4/ipv6/tcp/json). Only the guard test test_other_builtins_still_refused passes both ways.

  • util/run_unittest_leg.py foundation (under ulimit -f): 491 tests with the fix, 483 on origin/main, and the same 2 failures + 2 errors on both. They are fix(dumpkit): JSON output of DPKT/Scapy frames grows without bound and fills the disk #1372's test_pcap_output_opens_with_the_global_header (DPKT, Scapy) and test_pcap_run_writes_global_header_for_file_and_stream_modes, which fail before this change.
  • pytest tests/project: 389 passed, 1 skipped. Also passing: test_foundation.py, test_foundation_keyword_names.py, test_docstring_contract.py, test_extraction.py, the traceflow/engine/reassembly base tests, test_common_unit.py and test_base_class_contract.py.

…ped with (#1363)

- Extractor.register_engine/_reassembly/_traceflow accept the built-in a
  name shipped with, as its descriptor or as the class it names, and
  restore the shipped entry; every other built-in is still refused (#1016).
- Extractor.register_dumper and TraceFlow.register_dumper restore the
  shipped (descriptor, ext) pair instead of replacing it with the class,
  the dumper half of #1364.
- Re-registering the shipped original over itself is a silent no-op.
- The shipped entry is matched via sys.modules, never by importing it.

New tests/foundation/registry/test_restore_builtin_unit.py: 8 tests,
7 fail on origin/main.
@JarryShaw JarryShaw added fix Pull requests that fix a defect (fix: subject prefix) review: running A cross-review is in flight against the current head - no verdict yet labels Oct 7, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review verdict on 499cf0dea: GOOD TO GO (Sonnet reviewed; author Opus). This implements the owner's #1363 ruling for the foundation registrars.

  • Snapshots: they are taken in the class body, straight after the literals, so no user code can register first. Each is a MappingProxyType over a copy, so writing to one raises TypeError and a returned reference cannot corrupt a later restore. Subclasses share the parent's snapshot and registry, which is consistent.
  • Exact restore: every engine, reassembly, traceflow and dumper entry was overridden and then restored. Afterwards all five registries are is-identical to their shipped state. Restoring over an override warns once. Re-registering an original that was never overridden is silent.
  • No imports: an __import__ hook saw no load of dpkt, scapy, pyshark, pcap or pypcapfile during any restore. A shipped descriptor is matched by equality before resolution, so the result is correct whether or not its module is loaded yet.
  • fix(foundation): registrar error messages and type hints name the public class, not the Base the guard checks #1016 still holds: each of these raises RegistryError: DPKT under zzz, Scapy under dpkt, the DPKT descriptor under another name, IPv4 under ipv6, TCP traceflow under udp, and subclasses of DPKT and IPv4 under the shipped name. A look-alike class with the same __qualname__ and __module__ is treated as foreign.
  • Tests: the revert proof fails 10 of 13, counting subtests. The foundation leg runs 491 tests; its 2 failures and 2 errors are fix(dumpkit): JSON output of DPKT/Scapy frames grows without bound and fills the disk #1372's. tests/project gives 389 passed.

Edge cases, not blocking:

  • A dumper restored with a different ext keeps the shipped descriptor with the new ext. That follows the documented rule that a new ext changes only the extension.
  • An Extractor subclass that defines its own registries would gain shipped entries on a restore.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 7, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Coverage: 88.98% (unit tier, Python 3.14, 499cf0dea, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 4 93.55%
pcapkit/const 18777 1032 2348 843 90.27%
pcapkit/corekit 1949 84 606 20 94.91%
pcapkit/dumpkit 189 1 68 1 99.22%
pcapkit/foundation 2496 104 878 43 94.34%
pcapkit/interface 112 7 40 5 92.11%
pcapkit/protocols 16013 206 4178 177 98.06%
pcapkit/toolkit 539 74 168 3 84.58%
pcapkit/utilities 429 4 122 4 98.55%
pcapkit/vendor 4409 2359 1006 158 42.84%

Per-file detail: the coverage-html artifact of this run.

@JarryShaw
JarryShaw merged commit dcce848 into main Oct 8, 2026
41 checks passed
@JarryShaw
JarryShaw deleted the fix/1363-restore-builtin-registrars branch October 8, 2026 01:00
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 8, 2026
JarryShaw added a commit that referenced this pull request Oct 8, 2026
- ProtocolBase.register and the Internet, Link, Transport, SCTP, Frame
  and PCAPNG overrides resolved a ModuleDescriptor argument to its class
  before comparing it with the stored entry, so handing back the stored
  descriptor warned and replaced the deferred entry with the class. They
  now compare first: the stored entry, or a descriptor equal to it, is a
  silent no-op that keeps the stored object. A different entry still
  warns, and invalid input still raises RegistryError.
- Extractor.register_dumper already keeps its shipped descriptors since
  #1376; it is pinned in the new test.

New tests/protocols/test_registry_stored_descriptor_unit.py: 6 tests;
8 fail on origin/main (7 subtests and the ProtocolBase case).
JarryShaw added a commit that referenced this pull request Oct 8, 2026
…) (#1415)

- ProtocolBase.register and the Internet, Link, Transport, SCTP, Frame
  and PCAPNG overrides resolved a ModuleDescriptor argument to its class
  before comparing it with the stored entry, so handing back the stored
  descriptor warned and replaced the deferred entry with the class. They
  now compare first: the stored entry, or a descriptor equal to it, is a
  silent no-op that keeps the stored object. A different entry still
  warns, and invalid input still raises RegistryError.
- Extractor.register_dumper already keeps its shipped descriptors since
  #1376; it is pinned in the new test.

New tests/protocols/test_registry_stored_descriptor_unit.py: 6 tests;
8 fail on origin/main (7 subtests and the ProtocolBase case).
@JarryShaw JarryShaw added this to the PyPCAPKit v1.5 milestone Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Pull requests that fix a defect (fix: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant