Skip to content

fix(foundation): check every register_protocol_code key before registering any (#2268) - #2343

Merged
JarryShaw merged 1 commit into
mainfrom
fix/2268-protocol-code-mapping-check
Oct 27, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/2268-protocol-code-mapping-check

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • fix — bug fix

Description

Closes #2268.

  • Fix: register_protocol_code now flattens every target and checks each key against its destination's enum before registering any — a wrong code can no longer replace a shipped entry, and a list that fails partway no longer leaves its earlier entries registered.
  • Fail-without-fix: 6 failed on origin/main. Passing on the rebased head.

@JarryShaw JarryShaw added this to the PyPCAPKit v1.5 milestone Oct 27, 2026
@JarryShaw JarryShaw added bug Issues reporting a defect (set by the bug report template; a default, not an assessment) 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 27, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: NEEDS CHANGES at 928fecc9f (Sonnet) — test-only gap, the code is correct.

  • Confirmed: checking happens before any registration (a mixed-bad mapping/list changes nothing); the destination table matches the 11 typed registrars and all 43 shipped keys; Loopback/IPX are correctly left unchecked (they have no typed registrar to mirror); the int and list forms both work. Fail-without-fix: 6 failed on origin/main. On the head, 107+262+150 passed.
  • Required: add a table-driven test pinning all 7 _DESTINATION_KINDS rows — mutating 8 of 28 table cells (dropping a row, or flipping number on SCTP/Link/Frame/PCAPNG) currently survives the test selection.
  • Non-blocking: Loopback/IPX stay genuinely unchecked by design, letting a numerically-equal wrong enum through with only a warning; a non-class destination mid-list raises a bare AttributeError rather than the house RegistryError; the bool gap is fix(foundation): _check_code(number=True) takes a bool, so register_tcp(True) adds port 1 #2269.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 27, 2026
@JarryShaw
JarryShaw force-pushed the fix/2268-protocol-code-mapping-check branch from 0ff7478 to b621dc5 Compare October 27, 2026 02:26
@JarryShaw

Copy link
Copy Markdown
Owner Author

Amended 0ff7478ba → b621dc51b: added test_every_destination_kind_row_is_enforced, which pins all 7 _DESTINATION_KINDS rows against the real registrars — a wrong-enum key, the number flag, and the row's own enum type, plus a set-equality check against the table. 14/14 single-cell mutants (dropping a row, flipping number) are killed. test_protocol_code_registration_unit.py + test_docstring_contract.py + test_tier_guard.py give 169 passed (unittest), and test_dispatch_registry_unit.py run alongside confirms nothing leaked into its exact-count assertions.

@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Oct 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: GOOD TO GO at b621dc51b (Sonnet, round 2) — test-only, the round-1 gap is closed.

  • Confirmed: all 14 single-cell mutants (7 row drops, 7 number flips) are killed, and the harness confirms it can tell a kill from a survivor by reproducing round 1 on the unamended test. No mocking loophole — _check_code runs for real before the mocked register is reached. The diff is test-only; the pcapkit/ tree hash is identical across all three heads.
  • Fail-without-fix: 6 distinct tests fail on origin/main (one ImportError plus the five original rejection cases). On the head, 26+8+135 passed.
  • Non-blocking: the new test's docstring overstates "by behaviour rather than a copy of the table" — the assertIs/set(...) checks are exactly that, and carry most of the kind-swap coverage; no positive case sends a valid AppType member through the mapping form.

@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 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

for _CODE_DESTINATIONS and _DESTINATION_KINDS, can we use Type[EnumRegistry] and Type]ProtocolBase] types to replace the type annotations? to be more specific.

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Coverage: 91.58% (unit tier, Python 3.15, 3010e54d1, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 2 95.16%
pcapkit/const 19601 881 2620 867 92.12%
pcapkit/corekit 2596 74 818 37 96.51%
pcapkit/dumpkit 282 3 102 3 98.44%
pcapkit/foundation 3036 23 1054 25 98.83%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 17455 218 4598 185 98.15%
pcapkit/toolkit 914 36 334 10 95.51%
pcapkit/utilities 502 7 144 5 98.14%
pcapkit/vendor 4432 1988 1018 167 51.87%

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

@JarryShaw
JarryShaw force-pushed the fix/2268-protocol-code-mapping-check branch from b621dc5 to 79b88ee Compare October 27, 2026 04:31
@JarryShaw

Copy link
Copy Markdown
Owner Author

Done for _CODE_DESTINATIONS (enum keys are now Type[EnumRegistry], confirmed every key is an EnumRegistry subclass). _DESTINATION_KINDS's values are also tightened the same way, but its keys stay as a bare type: Link and Internet are genuinely abstract in this codebase (they don't implement name/length/make/__index__/read — only their concrete subclasses like Ethernet and IPv4 do), and mypy's type-abstract check specifically refuses an abstract class where a dict key is typed Type[ProtocolBase] (it doesn't mind one in a tuple value, which is why _CODE_DESTINATIONS was fine). Narrowing the key type there would need a # type: ignore[type-abstract] on Link:/Internet:, which seemed worse than leaving the key bare. Say if you'd rather have the ignore instead.

Pushed as 79b88eee1. mypy on the file is back to its baseline 3 pre-existing errors (unrelated TransportProtocol | str lines), and the registry tests give 82 passed.

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

Copy link
Copy Markdown
Owner Author

i'd still prefer using Type[ProtocolBase] and ignore mypy error if necessary

@JarryShaw

Copy link
Copy Markdown
Owner Author

Ruling noted: Type[ProtocolBase] with a type: ignore on the two abstract keys (Link, Internet). Dispatching the change.

@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 27, 2026
…ering any (#2268)

register_protocol_code (and the code= class keyword) handed each
{destination: key} pair straight to destination.register, so a member
of another enum, e.g. {Frame: TransType.ICMP}, replaced the shipped
LinkType.ETHERNET entry; and it registered targets as it flattened
them, so a bad later target left the earlier ones registered.

Flatten every target first, check each key with _check_code against
the enum of the class owning its destination's __proto__
(_DESTINATION_KINDS), then register. A destination keeping a registry
of its own (Loopback, IPX) is not checked.

Tests: RegisterProtocolCodeKeyCheckTests snapshot and restore the real
registries; the five rejection cases fail on main. A table-driven test
pins every _DESTINATION_KINDS row against the real registrars, killing
all 14 single-cell mutants (dropping a row, or flipping its number
flag).
@JarryShaw
JarryShaw force-pushed the fix/2268-protocol-code-mapping-check branch from 79b88ee to 3010e54 Compare October 27, 2026 04:41
@JarryShaw

Copy link
Copy Markdown
Owner Author

Pushed 79b88eee1 → 3010e54d1: _DESTINATION_KINDS's key is now Type[ProtocolBase], with # type: ignore[type-abstract] on exactly the two abstract keys (Link, Internet). mypy --warn-unused-ignores confirms both are load-bearing. Single-file mypy is back to the 3 pre-existing errors; the whole-package run is error-set-identical to origin/main (100 errors in both). Registry tests: 82 passed.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: GOOD TO GO at 3010e54d1 (Sonnet, round 3) — also covers the owner-preferred Type[ProtocolBase]+ignore version pushed mid-review.

  • Confirmed: Link/Internet are the only two abstract classes among the destinations; the two # type: ignore[type-abstract] are both load-bearing (dropping either reintroduces exactly one error; a spurious ignore on a concrete row is flagged unused-ignore). Whole-package mypy is error-set-identical to origin/main (100 errors, both). The diff from the already-reviewed head is annotation/import/cast only — bytecode comparison confirms zero behavior change. Fail-without-fix: 7 failed (6 distinct tests) on origin/main. 265+262 passed on the head.
  • No cleaner alternative found: a TypeVar bound fails at module level; cast/deriving the table are equally mypy-clean trade-offs, not clearly better.
  • Non-blocking: a one-line comment above the two ignored rows explaining why would help, since the reason currently lives only in this thread.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: GOOD TO GO at 3010e54d1 (Sonnet, round 4) — a fresh, independent pass, not a rubber-stamp.

  • Confirmed: mypy clean to the 3-error baseline, both single-file and whole-package (error sets genuinely identical, mapped through the real diff hunks). Both ignores are exactly load-bearing — stripping either reintroduces one error, adding one elsewhere is flagged unused-ignore. The owner's two comments are both satisfied. 268 passed; a simulated merge onto current main (which now includes fix(foundation): _check_code(number=True) takes a bool, so register_tcp(True) adds port 1 #2269) stays clean at 235 passed.
  • Fail-without-fix: 7 failed (6 distinct tests) on origin/main.
  • Non-blocking: while a key is abstract, mypy skips checking that row's value tuple — inherent to the design, covered at runtime by the existing test; a one-line comment on the two ignored rows is optional, no house precedent requires one.

@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 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Ready to merge.

Review: GOOD TO GO (Sonnet, round 4) at 3010e54d1 — fresh independent re-verification of the owner's final Type[ProtocolBase]/Type[EnumRegistry] preference with ignores.
CI: Required checks passed, 0 failures.
Mergeable, 0 unresolved threads.

@JarryShaw
JarryShaw merged commit 8d5c743 into main Oct 27, 2026
63 checks passed
@JarryShaw
JarryShaw deleted the fix/2268-protocol-code-mapping-check branch October 27, 2026 14:42
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Oct 27, 2026
@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet and removed review: good-to-go Cross-review at the current head says ready; CI state is separate labels Oct 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

On hold for a design change: moving _DESTINATION_KINDS from a module-level mapping to a class attribute declared directly on each of Link/Internet/Frame/PCAPNG/TCP/UDP/SCTP, so the Enum registry and target protocol class _check_code validates against are explicitly specified where each class already declares __proto__, rather than kept in a separate table that has to stay in sync. Will post the revised diff shortly.

@JarryShaw

Copy link
Copy Markdown
Owner Author

This merged before the class-attribute redesign I started above could land on it — opened as a follow-up instead: #2392.

JarryShaw added a commit that referenced this pull request Oct 27, 2026
…tribute, not a module table (#2343)

Problem: _DESTINATION_KINDS mapped a protocol class to the Enum registry
_check_code validates its code against, found by walking the destination's
MRO for whichever ancestor owns __proto__ and looking that owner up in the
table. The pairing lived apart from the __proto__ it describes, and a new
destination needed both a new __proto__ and a new row in a module dict
elsewhere.

Fix: each of the seven destination classes (Link, Internet, Frame, PCAPNG,
TCP, UDP, SCTP) now declares its own __proto_key__ class attribute, alongside
__proto__, pairing its Enum registry with whether a bare int is also valid.
register_protocol_code reads it straight off the owner the MRO-walk already
finds (via vars(), not getattr, so a class keeping a registry of its own --
Loopback, IPX -- does not inherit its parent's pairing). _check_code also
takes the destination class explicitly now, so its error names which
registry refused, not just which enum: "TCP: code must be ... not True"
rather than "code must be ... not True". Every other call site of
_check_code (register_ethertype, register_transtype, every option/parameter
registrar) passes its own target the same way.

Two call sites write into two registries keyed alike and pass one of the two
as target, rather than checking twice for no behavioural difference:
register_linktype (Frame and PCAPNG) names Frame; register_apptype (TCP
and/or UDP, resolved after the check) names TCP.

Test: test_a_registry_of_its_own_does_not_inherit_its_parent_pairing pins the
Loopback/IPX case; test_a_rejection_names_the_destination_registry and
test_every_rejection_names_the_destination_registry (24 subtests, one per
call site) pin the new error prefix; test_every_destination_kind_row_is_enforced
now walks every ProtocolBase subclass declaring __proto_key__ rather than a
fixed dict's keys, so a new undeclared pairing is caught too.
@JarryShaw JarryShaw removed the review: running A cross-review is in flight against the current head - no verdict yet label Oct 27, 2026
JarryShaw added a commit that referenced this pull request Oct 27, 2026
…tribute, not a module table (#2343) (#2392)

Problem: _DESTINATION_KINDS mapped a protocol class to the Enum registry
_check_code validates its code against, found by walking the destination's
MRO for whichever ancestor owns __proto__ and looking that owner up in the
table. The pairing lived apart from the __proto__ it describes, and a new
destination needed both a new __proto__ and a new row in a module dict
elsewhere.

Fix: each of the seven destination classes (Link, Internet, Frame, PCAPNG,
TCP, UDP, SCTP) now declares its own __proto_key__ class attribute, alongside
__proto__, pairing its Enum registry with whether a bare int is also valid.
register_protocol_code reads it straight off the owner the MRO-walk already
finds (via vars(), not getattr, so a class keeping a registry of its own --
Loopback, IPX -- does not inherit its parent's pairing). _check_code also
takes the destination class explicitly now, so its error names which
registry refused, not just which enum: "TCP: code must be ... not True"
rather than "code must be ... not True". Every other call site of
_check_code (register_ethertype, register_transtype, every option/parameter
registrar) passes its own target the same way.

Two call sites write into two registries keyed alike and pass one of the two
as target, rather than checking twice for no behavioural difference:
register_linktype (Frame and PCAPNG) names Frame; register_apptype (TCP
and/or UDP, resolved after the check) names TCP.

Test: test_a_registry_of_its_own_does_not_inherit_its_parent_pairing pins the
Loopback/IPX case; test_a_rejection_names_the_destination_registry and
test_every_rejection_names_the_destination_registry (24 subtests, one per
call site) pin the new error prefix; test_every_destination_kind_row_is_enforced
now walks every ProtocolBase subclass declaring __proto_key__ rather than a
fixed dict's keys, so a new undeclared pairing is caught too.
JarryShaw added a commit that referenced this pull request Oct 27, 2026
…registries themselves

Follow-up to #2392/#2343. _CODE_DESTINATIONS was a module-level dict
mapping an enum registry type to the protocol class(es) owning the
__proto__ dispatch registry keyed by that enum, so register_protocol_code
could infer a destination from a bare enum member. Mirrors __proto_key__,
which #2392 moved the opposite direction (destination -> enum) onto the
destination classes themselves.

Each of the 4 enum registry classes (EtherType, TransType, LinkType,
PayloadProtocolIdentifier) now declares __proto_dest__, a tuple of
ModuleDescriptor naming its destination class(es) lazily -- const sits
below protocols in the dependency order, so a real class reference would
make const import protocols; ModuleDescriptor (already used for __proto__
dispatch tables elsewhere) avoids that without inventing a parallel
string-path scheme. _iter_code_targets reads the dunder off type(code)
via getattr() and resolves each descriptor's .klass.

getattr(), not vars(): verified aenum refuses to extend an enumeration
that already has members, so none of these four registries can gain a
subclass with its own registry -- the hazard __proto_key__'s vars() call
guards against (Loopback/IPX owning a differently-keyed registry) is
structurally impossible here. Where an enum registry is subclassed
(AppType -> TCP/UDP/SCTP/DCCP) the base has no members and the parts
share one key space, so inheriting the pairing is correct.

const/reg/*.py and const/sctp/payload_protocol_identifier.py are
regenerated, not hand-edited: the vendor crawlers (vendor/reg/*.py,
vendor/sctp/payload_protocol_identifier.py) gain a PROTO_DEST class
attribute, threaded through vendor/default.py's LINE template and
context(); a throwaway script recovered each committed file's ENUM/MISS
blocks and re-rendered through the unmodified template first, asserting
byte-identity with the committed file, before re-rendering with
PROTO_DEST to confirm the diff is purely the template's effect.

Tests: tests/vendor/test_vendor_proto_dest_2392_unit.py (new) plus
ProtoDestDeclarationTests in test_protocol_code_registration_unit.py and
an update to test_dispatch_reachability_unit.py, which read the dunder
instead of the deleted dict.
JarryShaw added a commit that referenced this pull request Oct 27, 2026
…registries themselves

Follow-up to #2392/#2343. _CODE_DESTINATIONS was a module-level dict
mapping an enum registry type to the protocol class(es) owning the
__proto__ dispatch registry keyed by that enum, so register_protocol_code
could infer a destination from a bare enum member. Mirrors __proto_key__,
which #2392 moved the opposite direction (destination -> enum) onto the
destination classes themselves.

Each of the 4 enum registry classes (EtherType, TransType, LinkType,
PayloadProtocolIdentifier) now declares __proto_dest__, a tuple of
ModuleDescriptor naming its destination class(es) lazily -- const sits
below protocols in the dependency order, so a real class reference would
make const import protocols; ModuleDescriptor (already used for __proto__
dispatch tables elsewhere) avoids that without inventing a parallel
string-path scheme. _iter_code_targets reads the dunder off type(code)
via getattr() and resolves each descriptor's .klass.

getattr(), not vars(): verified aenum refuses to extend an enumeration
that already has members, so none of these four registries can gain a
subclass with its own registry -- the hazard __proto_key__'s vars() call
guards against (Loopback/IPX owning a differently-keyed registry) is
structurally impossible here. Where an enum registry is subclassed
(AppType -> TCP/UDP/SCTP/DCCP) the base has no members and the parts
share one key space, so inheriting the pairing is correct.

const/reg/*.py and const/sctp/payload_protocol_identifier.py are
regenerated, not hand-edited: the vendor crawlers (vendor/reg/*.py,
vendor/sctp/payload_protocol_identifier.py) gain a PROTO_DEST class
attribute, threaded through vendor/default.py's LINE template and
context(); a throwaway script recovered each committed file's ENUM/MISS
blocks and re-rendered through the unmodified template first, asserting
byte-identity with the committed file, before re-rendering with
PROTO_DEST to confirm the diff is purely the template's effect.

Tests: tests/vendor/test_vendor_proto_dest_2392_unit.py (new) plus
ProtoDestDeclarationTests in test_protocol_code_registration_unit.py and
an update to test_dispatch_reachability_unit.py, which read the dunder
instead of the deleted dict.
JarryShaw added a commit that referenced this pull request Oct 27, 2026
…num registries themselves

Follow-up to #2392/#2343. _CODE_DESTINATIONS was a module-level dict
mapping an enum registry type to the protocol class(es) owning the
__proto__ dispatch registry keyed by that enum, so register_protocol_code
could infer a destination from a bare enum member. Mirrors __proto_key__,
which #2392 moved the opposite direction (destination -> enum) onto the
destination classes themselves.

Each of the 4 enum registry classes (EtherType, TransType, LinkType,
PayloadProtocolIdentifier) now declares __proto_dest__, a tuple of
ModuleDescriptor naming its destination class(es) lazily -- const sits
below protocols in the dependency order, so a real class reference would
make const import protocols; ModuleDescriptor (already used for __proto__
dispatch tables elsewhere) avoids that without inventing a parallel
string-path scheme. _iter_code_targets reads the dunder off type(code)
via getattr() and resolves each descriptor's .klass.

getattr(), not vars(): verified aenum refuses to extend an enumeration
that already has members, so none of these four registries can gain a
subclass with its own registry -- the hazard __proto_key__'s vars() call
guards against (Loopback/IPX owning a differently-keyed registry) is
structurally impossible here. The one enum registry that is subclassed,
AppType, is irrelevant here only because it declares no __proto_dest__
at all -- a class-level destination would in fact be the wrong model for
it, since register_apptype routes each member to the registry named by
that member's own transport protocol, which no single shared destination
could express.

const/reg/*.py and const/sctp/payload_protocol_identifier.py are
regenerated, not hand-edited: the vendor crawlers (vendor/reg/*.py,
vendor/sctp/payload_protocol_identifier.py) gain a PROTO_DEST class
attribute, threaded through vendor/default.py's LINE template and
context(); a throwaway script recovered each committed file's ENUM/MISS
blocks and re-rendered through the unmodified template first, asserting
byte-identity with the committed file, before re-rendering with
PROTO_DEST to confirm the diff is purely the template's effect.

Tests: tests/vendor/test_vendor_proto_dest_2392_unit.py (new) plus
ProtoDestDeclarationTests in test_protocol_code_registration_unit.py and
an update to test_dispatch_reachability_unit.py, which read the dunder
instead of the deleted dict.
JarryShaw added a commit that referenced this pull request Oct 28, 2026
…num registries themselves (#2403)

Follow-up to #2392/#2343. _CODE_DESTINATIONS was a module-level dict
mapping an enum registry type to the protocol class(es) owning the
__proto__ dispatch registry keyed by that enum, so register_protocol_code
could infer a destination from a bare enum member. Mirrors __proto_key__,
which #2392 moved the opposite direction (destination -> enum) onto the
destination classes themselves.

Each of the 4 enum registry classes (EtherType, TransType, LinkType,
PayloadProtocolIdentifier) now declares __proto_dest__, a tuple of
ModuleDescriptor naming its destination class(es) lazily -- const sits
below protocols in the dependency order, so a real class reference would
make const import protocols; ModuleDescriptor (already used for __proto__
dispatch tables elsewhere) avoids that without inventing a parallel
string-path scheme. _iter_code_targets reads the dunder off type(code)
via getattr() and resolves each descriptor's .klass.

getattr(), not vars(): verified aenum refuses to extend an enumeration
that already has members, so none of these four registries can gain a
subclass with its own registry -- the hazard __proto_key__'s vars() call
guards against (Loopback/IPX owning a differently-keyed registry) is
structurally impossible here. The one enum registry that is subclassed,
AppType, is irrelevant here only because it declares no __proto_dest__
at all -- a class-level destination would in fact be the wrong model for
it, since register_apptype routes each member to the registry named by
that member's own transport protocol, which no single shared destination
could express.

const/reg/*.py and const/sctp/payload_protocol_identifier.py are
regenerated, not hand-edited: the vendor crawlers (vendor/reg/*.py,
vendor/sctp/payload_protocol_identifier.py) gain a PROTO_DEST class
attribute, threaded through vendor/default.py's LINE template and
context(); a throwaway script recovered each committed file's ENUM/MISS
blocks and re-rendered through the unmodified template first, asserting
byte-identity with the committed file, before re-rendering with
PROTO_DEST to confirm the diff is purely the template's effect.

Tests: tests/vendor/test_vendor_proto_dest_2392_unit.py (new) plus
ProtoDestDeclarationTests in test_protocol_code_registration_unit.py and
an update to test_dispatch_reachability_unit.py, which read the dunder
instead of the deleted dict.
JarryShaw added a commit that referenced this pull request Oct 29, 2026
…ce sweep, fix other prose drift (#2428)

Round 8 of the whole-repo prose sweep (#1103). Fanned out 8 shard agents by
directory; most of the repo was clean. Changes:

* pcapkit/protocols/internet/ipv6_ext.py + its .rst: finish the carry-over
  miss from round 7 -- the `_lookup_next_layer` plain pointer still targeted
  `ProtocolBase`, flipped to `Protocol` per #2420's ruling.
* Same miss in corekit/sentinels.py (`__keywords__`), docs/source/ext.rst
  (three sites, including a verbatim twin of a paragraph #2420 already fixed
  in protocol.py), schema/schema.py and schema/link/ethernet.py.
* internet.py, link.py, transport.py, sctp.py, protocol.py: `register()`'s
  Arguments: and a couple of Returns:/versionchanged clauses said `Protocol`
  subclass/instance while the signature types `ProtocolBase` and the
  adjacent Raises: clause already said so -- internal contradiction, fixed
  to `ProtocolBase` to match.
* docs/source/contributing/conventions/protocol-layer-placement.rst: the
  Link-Application-ProtocolBase set difference is `__proto_key__`, not
  empty as claimed (#2343 added it after this page was written).
* docs/source/contributing/conventions/registry-protocol.rst: "every
  registry overrides `_validate_value`" contradicted its own next
  paragraph, where the AppType transports inherit rather than override.
* pcapkit/vendor/ipx/packet.py, vendor/reg/linktype.py: a self-contradicting
  claim and a stale counted-number, both in vendor docstrings.
* docs/source/engines.rst, docs/source/conf.py, util/changelog_md.py,
  CONTRIBUTING.md: a stale scapy version, a wrong file path, a false
  "matches the Sphinx we build with" claim, and a missing caveat about
  actionlint making Lint non-advisory.

No executable code changed -- every edit is inside a docstring, comment, or
.rst file; confirmed by diff review and `import pcapkit` from this worktree.

Four behavioral defects found but deliberately left unfixed (reported
separately): 16 of 24 pcapkit/vendor crawlers' `process(self, data)` reads
the module-global `DATA` instead of its own `data` argument (latent,
harmless only because `request()` returns that same global); an empty
`FilterType` registry behind a live TODO; three open "handle this
programmatically" TODOs in pcapkit/vendor/mh; and dead `multiprocessing.Pool`
scaffolding in vendor/__main__.py.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Issues reporting a defect (set by the bug report template; a default, not an assessment) fix Pull requests that fix a defect (fix: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(foundation): register_protocol_code's mapping form skips _check_code, replaces entries

1 participant