Skip to content

docs: #719-style prose sweep after the #1090-1102 defect wave - #2408

Merged
JarryShaw merged 1 commit into
mainfrom
sweep/1103-whole-repo-prose
Oct 28, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
sweep/1103-whole-repo-prose

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Summary

Part of the #1103 whole-repo #719-style prose sweep, scoped this round to the maker-message wave (#2296, #2404, #2405, #2407) and the registry-destination refactor (#2392, #2403). 16 files, prose-only (docstrings and comments), no behaviour change, no renames.

1. Stale Protocol → ProtocolBase cross-references in the register/register_protocol docs: protocols/protocol.py, protocols/internet/internet.py, protocols/link/link.py, protocols/transport/transport.py, protocols/transport/sctp.py, foundation/registry/protocols.py.

2. Missing Raises: sections: the bool port guard (#2287) on TCP.make, UDP.make, SCTP.make; HTTP/1's request-without-uri guard in two httpv1.py make docstrings.

3. Behaviour the prose omitted: misc/null.py gains a .. versionchanged:: 1.5.0 for protochain's narrowing to None (#2317) and protocol.py documents the other side of it; protocol.py's __init__ names the __own_make_keywords__ exception to its keyword check; foundation/reassembly/ip.py names the IPv6 M bit and which buffer an atomic fragment is isolated from (#2270); _check_code names register_protocol_code among its callers (#2186); HIP's shared lifetime helper says where the Lifetime octet appears instead of counting the makers that carry it.

4. Before/after narration → present tense (the #1103 round-6 rule): the __proto_dest__ prose and register_protocol_code key-check narration in tests/protocols/test_protocol_code_registration_unit.py and tests/vendor/test_vendor_proto_dest_2392_unit.py; the #2296 and #2406 maker-message module docstrings and their ReadersKeepInvalidFormat docstrings; registry/protocols.py's _NameLease rationale and register_protocol name-collision note; TCP's _make_mptcp_unknown length comment.

Not in this PR: no docs/source/changelog/1.5.0.rst entries for #2312–#2407 — #719 scopes the changelog to its own PR (tracked separately in #2409/#2412). docs/source/contributing/pep.rst's "_make_index not yet refactored" claim was verified against #2393/#2401 and still holds, so it's left as is.

Test plan

  • AST-structure guard (util/vendor_code_changed.py's code_of) — all 16 touched files prose-only against main, zero code-structure diffs
  • tests/protocols/test_maker_invalid_format_messages_2296_unit.py + _2406_unit.py, tests/protocols/test_protocol_code_registration_unit.py, tests/vendor/test_vendor_proto_dest_2392_unit.py — all pass
  • tests/test_docstring_contract.py + tests/project/test_conventions_doc_claims.py — pass
  • tests/project/test_docs_issue_pr_roles_1103_unit.py + tests/project/test_issue_refs_in_comments.py — pass (issue refs moved within docstrings/comments)

@github-actions github-actions Bot added this to the PyPCAPKit v1.5 milestone Oct 28, 2026
@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 28, 2026
@JarryShaw JarryShaw added docs Pull requests that change documentation only (docs: subject prefix) review: running A cross-review is in flight against the current head - no verdict yet labels Oct 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

This PR's branch name and scope (maker-message wave #2296/#2404/#2405/#2407, the _CODE_DESTINATIONS -> __proto_dest__ refactor #2392/#2403) exactly matches a #1103 sweep I was independently dispatched to run over the same files in this same worktree. Rather than opening a competing PR against the same scope, here are the additional stale-prose findings my pass turned up beyond the one fix already in this PR -- all docstrings/comments only, each verified with the ast.dump-with-docstrings-stripped guard this PR's own description uses, and covered by the relevant unit tests (tests/protocols/, tests/foundation/reassembly/, tests/test_docstring_contract.py, tests/project/test_conventions_doc_claims.py), all passing.

pcapkit/foundation/reassembly/ip.py

  • IP.reassembly's comment above the atomic-fragment branch still said # when non-fragmented (possibly discarded) packet received: it is reassembled on its own, in a buffer of its own (#2270) -- stale from before fix(reassembly): unfragmented datagram with a buffered BUFID is dropped and flushes IPv6 #2270 (the datagram is no longer discarded, and the IPv4 branch doesn't get a buffer of its own, only the IPv6 one does).
  • The class docstring and the __isolate_atomic__ comment both said "MF clear" for a base class shared by IPv4 and IPv6, where IPv6's flag is M, not MF.

pcapkit/protocols/protocol.py / pcapkit/foundation/registry/protocols.py / link/link.py / transport/transport.py / transport/sctp.py / internet/internet.py -- a half-applied rename. register's Arguments:/Warns: sections and one versionchanged block in several of these still said :class:~pcapkit.protocols.protocol.Protocol subclass, including one broken xref whose display text said ProtocolBase but targeted .Protocol.register. Several siblings (internet.py, misc/pcap/frame.py, misc/pcapng.py) already carry the corrected ProtocolBase form from #2333; these were the stragglers.

  • ProtocolBase.__init__'s Raises: for UnsupportedCall didn't carry the __own_make_keywords__ exception that fix(ipv6_ext): IPv6_Ext.make's len and data stay allowed in subclasses and are dropped #2286 added (and that _declared_keywords's own docstring already documents).
  • _check_code's docstring said "Each registrar typed on one enum calls this", but register_protocol_code now calls it too for an inferred/explicit destination -- widened the summary and the target arg note accordingly.

pcapkit/protocols/transport/{udp,tcp,sctp}.py -- none of the three make() docstrings had a Raises: entry for _make_port rejecting a bool port (#2287); added one to each, matching the private helper's own Raises:.

pcapkit/protocols/application/httpv1.py -- _make_start_line and HTTP.make's Raises: both said only "the values are neither a request's nor a response's", missing the uri is None branch #2373's reprefixing left visible.

pcapkit/protocols/internet/hip.py -- _make_lifetime_octet's docstring (added by #2400) said "Shared by the three :rfc:8003 makers, which between them carry four such octets" -- counted numbers of codebase items, against the project's no-counted-numbers ruling. Reworded to "Shared by the :rfc:8003 registration makers, wherever a Lifetime octet appears."

tests/protocols/test_maker_invalid_format_messages_2406_unit.py -- the module docstring and ReadersKeepInvalidFormat's class docstring both said _read_opt_pad and _make_opt_pad "both reject"/"reject the same thing" for a Pad1 with non-zero length. Only the reader raises; the maker (per #2406's own diff) warns and makes a PadN instead -- the class's own test (test_pad1_with_a_length_warns_by_name) proves this. Reworded both to say "guard" and spell out that only the reader raises.

pcapkit/protocols/misc/null.py / protocol.py -- NoPayload.protochain (added by #2317 to narrow a previously-wrong type declaration) carried no version directive while every comparable 1.5.0 behaviour-adjacent declaration fix in this wave got one; added a versionchanged:: 1.5.0 (careful to say it's the declaration that changed, not the runtime value -- self._protos was already None there) and a cross-referencing Note: on the base protochain.

Not fixed, flagged only (code-level, out of scope for a prose-only pass):

Full diff of the above (13 files, prose/comments only, AST-guard verified against this branch's current head):

patch
diff --git a/pcapkit/foundation/reassembly/ip.py b/pcapkit/foundation/reassembly/ip.py
index 45b233061..05f864974 100644
--- a/pcapkit/foundation/reassembly/ip.py
+++ b/pcapkit/foundation/reassembly/ip.py
@@ -67,9 +67,9 @@ class IP(ReassemblyBase[Packet[_AT], Datagram[_AT], BufferID, Buffer[_AT]], Gene
        <pcapkit.foundation.reassembly.data.ip.Datagram.conflict>`
        (:issue:`477`). An incomplete buffer expires
        after ``timeout`` seconds of capture time, 60 by default for both IPv4
-       and IPv6. A datagram with fragment offset zero and **MF** clear is
-       reported even when its BUFID is already buffered, rather than dropped
-       (:issue:`2270`).
+       and IPv6. A datagram with fragment offset zero and **MF** (**M** in
+       IPv6) clear is reported even when its BUFID is already buffered,
+       rather than dropped (:issue:`2270`).
 
     """
     if TYPE_CHECKING:
@@ -156,8 +156,10 @@ class IP(ReassemblyBase[Packet[_AT], Datagram[_AT], BufferID, Buffer[_AT]], Gene
         # belong to.
         self._dtgram.extend(self.expire(TS))
 
-        # when non-fragmented (possibly discarded) packet received: it is
-        # reassembled on its own, in a buffer of its own (#2270)
+        # a datagram with fragment offset zero and MF clear is reported even
+        # when its BUFID is already buffered, rather than dropped: isolated
+        # from that buffer (IPv6 atomic fragments) or after flushing it first
+        # (IPv4) (#2270)
         isolated = False
         if not FO and not MF:
             if self.__isolate_atomic__:
diff --git a/pcapkit/foundation/registry/protocols.py b/pcapkit/foundation/registry/protocols.py
index 3a32851cf..3d5e0770e 100644
--- a/pcapkit/foundation/registry/protocols.py
+++ b/pcapkit/foundation/registry/protocols.py
@@ -366,9 +366,9 @@ def _register_name(protocol: 'Type[ProtocolBase]', *targets: 'tuple[type, Any]')
     releasing whatever each target code held before, and followed by a lease
     when the write changed the name, so that registering the code back undoes
     it (:issue:`1505`). A name already showing ``protocol`` -- shipped, defined
-    by a :class:`~pcapkit.protocols.protocol.Protocol` subclass, or registered
-    directly -- is not leased, so no restore takes it away; one showing it
-    through a lease extends that lease to ``targets``.
+    by a :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass, or
+    registered directly -- is not leased, so no restore takes it away; one
+    showing it through a lease extends that lease to ``targets``.
 
     Args:
         protocol: Protocol class just registered -- and so validated -- at ``targets``.
@@ -565,12 +565,15 @@ def register_protocol_code(protocol: 'Type[ProtocolBase]', code: 'Any') -> 'None
 
 def _check_code(code: 'Any', kind: 'type', target: 'Type[ProtocolBase]', *,
                 number: 'bool' = False) -> 'None':
-    """Reject a registration key that is not a member of the registrar's enum.
+    """Reject a registration key that is not a member of the enum its
+    destination registry is keyed by.
 
     Each registrar typed on one enum calls this before touching any registry,
-    so a bad ``code`` leaves every registry as it was (:issue:`2186`). The check is on the type,
-    not the value: the registry enums compare equal to their values, so a
-    member of another enum would key the entry of the member it equals, e.g.
+    as does :func:`register_protocol_code` for an inferred or explicitly
+    named destination, so a bad ``code`` leaves every registry as it was
+    (:issue:`2186`). The check is on the type, not the value: the registry
+    enums compare equal to their values, so a member of another enum would
+    key the entry of the member it equals, e.g.
     :attr:`TransType.ICMP <pcapkit.const.reg.transtype.TransType.ICMP>` would
     replace :attr:`LinkType.ETHERNET <pcapkit.const.reg.linktype.LinkType.ETHERNET>`
     (:issue:`2224`).
@@ -580,7 +583,7 @@ def _check_code(code: 'Any', kind: 'type', target: 'Type[ProtocolBase]', *,
         kind: Enum the registrar is typed on.
         target: Protocol class whose registry ``code`` is destined for, named in
             the error message so a rejection says *whose* registry rejected the
-            key rather than only what it wanted -- the registrars share one
+            key rather than only what it wanted -- its callers share one
             message, and several of them are typed on the same enum.
         number: Whether a bare :class:`int` is a valid key too, as for the
             registrars keyed on a port number or a payload protocol identifier.
diff --git a/pcapkit/protocols/application/httpv1.py b/pcapkit/protocols/application/httpv1.py
index f1c48b70e..ad0336555 100644
--- a/pcapkit/protocols/application/httpv1.py
+++ b/pcapkit/protocols/application/httpv1.py
@@ -224,7 +224,8 @@ class HTTP(HTTPBase[Data_HTTP, Schema_HTTP],
 
         Raises:
             ProtocolError: If the values are neither a request's nor a
-                response's, or if ``raw_line`` or a ``raw_header`` entry that
+                response's, if they are a request's and ``uri`` is
+                :obj:`None`, or if ``raw_line`` or a ``raw_header`` entry that
                 reads back as the given values carries a CR or LF that the
                 values do not (other than the CRLF of an ``obs-fold``).
 
@@ -328,7 +329,8 @@ class HTTP(HTTPBase[Data_HTTP, Schema_HTTP],
 
         Raises:
             ProtocolError: If the values are neither a request's nor a
-                response's.
+                response's, or if they are a request's and ``uri`` is
+                :obj:`None`.
 
         """
         version = http_version.encode() if isinstance(http_version, str) else http_version
diff --git a/pcapkit/protocols/internet/hip.py b/pcapkit/protocols/internet/hip.py
index cad41bf60..163c328aa 100644
--- a/pcapkit/protocols/internet/hip.py
+++ b/pcapkit/protocols/internet/hip.py
@@ -1955,8 +1955,9 @@ class HIP(IPv6_Ext[Data_HIP, Schema_HIP], Internet[Data_HIP, Schema_HIP],
 
         An explicit ``exponent`` is the octet and wins, as a parsed parameter's
         is; otherwise ``lifetime`` is a duration and
-        :meth:`_make_registration_lifetime` encodes it. Shared by the three
-        :rfc:`8003` makers, which between them carry four such octets.
+        :meth:`_make_registration_lifetime` encodes it. Shared by the
+        :rfc:`8003` registration makers, wherever a ``Lifetime`` octet
+        appears.
 
         Args:
             code: parameter code
diff --git a/pcapkit/protocols/internet/internet.py b/pcapkit/protocols/internet/internet.py
index a64b5c769..5e986a7a8 100644
--- a/pcapkit/protocols/internet/internet.py
+++ b/pcapkit/protocols/internet/internet.py
@@ -182,7 +182,7 @@ class Internet(ProtocolBase[_PT, _ST], Generic[_PT, _ST]):  # pylint: disable=ab
         Arguments:
             code: protocol code as in :class:`~pcapkit.const.reg.transtype.TransType`
             protocol: module descriptor or a
-                :class:`~pcapkit.protocols.protocol.Protocol` subclass
+                :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
 
         Raises:
             pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a
diff --git a/pcapkit/protocols/link/link.py b/pcapkit/protocols/link/link.py
index cc4d148af..228a38b71 100644
--- a/pcapkit/protocols/link/link.py
+++ b/pcapkit/protocols/link/link.py
@@ -138,7 +138,7 @@ class Link(ProtocolBase[_PT, _ST], Generic[_PT, _ST]):  # pylint: disable=abstra
         Arguments:
             code: protocol code as in :class:`~pcapkit.const.reg.ethertype.EtherType`
             protocol: module descriptor or a
-                :class:`~pcapkit.protocols.protocol.Protocol` subclass
+                :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
 
         Raises:
             pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a
@@ -150,7 +150,7 @@ class Link(ProtocolBase[_PT, _ST], Generic[_PT, _ST]):  # pylint: disable=abstra
                 replacement so a caller can tell *what* was lost. Fires only
                 when the incumbent differs from the replacement -- see
                 :meth:`ProtocolBase.register
-                <pcapkit.protocols.protocol.Protocol.register>` for the
+                <pcapkit.protocols.protocol.ProtocolBase.register>` for the
                 guard this shares with ``register_protocol``, and for the
                 shipped descriptor that a restore puts back (:issue:`1504`).
 
@@ -158,7 +158,7 @@ class Link(ProtocolBase[_PT, _ST], Generic[_PT, _ST]):  # pylint: disable=abstra
 
            Takes the protocol as one ``protocol`` argument, a
            :class:`~pcapkit.corekit.module.ModuleDescriptor` or a
-           :class:`~pcapkit.protocols.protocol.Protocol` subclass, in place of
+           :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass, in place of
            the ``module`` and ``class_`` names.
 
         """
diff --git a/pcapkit/protocols/misc/null.py b/pcapkit/protocols/misc/null.py
index fb689b4ca..4e57bbbc0 100644
--- a/pcapkit/protocols/misc/null.py
+++ b/pcapkit/protocols/misc/null.py
@@ -68,7 +68,17 @@ class NoPayload(ProtocolBase[Data_NoPayload, Schema_NoPayload],
     @property
     def protochain(self) -> 'None':  # type: ignore[override]
         """Protocol chain of current instance, which an empty payload does not
-        have."""
+        have.
+
+        .. versionchanged:: 1.5.0
+
+           Narrows :attr:`Protocol.protochain
+           <pcapkit.protocols.protocol.ProtocolBase.protochain>`'s declared
+           type from :class:`~pcapkit.corekit.protochain.ProtoChain` to
+           :obj:`None`, the value ``self._protos`` already held here; the fix
+           is to the declaration, not the runtime value (:issue:`2317`).
+
+        """
         return None
 
     ##########################################################################
diff --git a/pcapkit/protocols/protocol.py b/pcapkit/protocols/protocol.py
index 4eda240b0..05f883e27 100644
--- a/pcapkit/protocols/protocol.py
+++ b/pcapkit/protocols/protocol.py
@@ -661,7 +661,15 @@ class ProtocolBase(Generic[_PT, _ST], metaclass=ProtocolMeta):
     # protocol chain of current instance
     @property
     def protochain(self) -> 'ProtoChain':
-        """Protocol chain of current instance."""
+        """Protocol chain of current instance.
+
+        Note:
+            :class:`~pcapkit.protocols.misc.null.NoPayload` has no chain and
+            narrows this to :obj:`None`; :meth:`_decode_next_layer` passes it
+            on as ``basis``, which
+            :class:`~pcapkit.corekit.protochain.ProtoChain` accepts.
+
+        """
         return self._protos
 
     # packet data
@@ -1031,7 +1039,7 @@ class ProtocolBase(Generic[_PT, _ST], metaclass=ProtocolMeta):
         Arguments:
             code: protocol code
             protocol: module descriptor or a
-                :class:`~pcapkit.protocols.protocol.Protocol` subclass
+                :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
 
         Raises:
             pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a
@@ -1271,9 +1279,12 @@ class ProtocolBase(Generic[_PT, _ST], metaclass=ProtocolMeta):
             UnsupportedCall: When constructing (``file`` is :obj:`None`), if a
                 keyword names no parameter of this protocol's :meth:`make`,
                 :meth:`read`, :meth:`pack`, :meth:`unpack`,
-                :meth:`__post_init__` or :meth:`__init__`, anywhere in the MRO,
-                and is not listed in :attr:`__keywords__`. Parsing (``file`` is
-                given) is unaffected.
+                :meth:`__post_init__` or :meth:`__init__`, anywhere in the MRO
+                -- except a ``make`` whose class sets
+                :attr:`__own_make_keywords__`, which counts only while it is
+                the ``make`` of the protocol being constructed -- and is not
+                listed in :attr:`__keywords__`. Parsing (``file`` is given) is
+                unaffected.
 
         Note:
             The ``_layer``, ``_protocol`` and ``__context__`` keywords are
diff --git a/pcapkit/protocols/transport/sctp.py b/pcapkit/protocols/transport/sctp.py
index 1c7086f60..45d217f73 100644
--- a/pcapkit/protocols/transport/sctp.py
+++ b/pcapkit/protocols/transport/sctp.py
@@ -694,6 +694,10 @@ class SCTP(Transport[Data_SCTP, Schema_SCTP],
         Returns:
             Constructed packet data.
 
+        Raises:
+            ProtocolError: If ``srcport`` or ``dstport`` is a :obj:`bool`
+                (:issue:`2287`).
+
         Note:
             There is no ``payload`` argument: SCTP carries its user data in the
             ``data`` field of a DATA chunk, so the payload is supplied as part
@@ -730,7 +734,7 @@ class SCTP(Transport[Data_SCTP, Schema_SCTP],
             code: payload protocol identifier (PPID), as in
                 :class:`~pcapkit.const.sctp.payload_protocol_identifier.PayloadProtocolIdentifier`
             protocol: module descriptor or a
-                :class:`~pcapkit.protocols.protocol.Protocol` subclass
+                :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
 
         Important:
             SCTP overrides :meth:`Transport.register
diff --git a/pcapkit/protocols/transport/tcp.py b/pcapkit/protocols/transport/tcp.py
index 86abc1e57..16cb60ee3 100644
--- a/pcapkit/protocols/transport/tcp.py
+++ b/pcapkit/protocols/transport/tcp.py
@@ -624,6 +624,10 @@ class TCP(Transport[Data_TCP, Schema_TCP],
         Returns:
             Constructed packet data.
 
+        Raises:
+            ProtocolError: If ``srcport`` or ``dstport`` is a :obj:`bool`
+                (:issue:`2287`).
+
         .. versionchanged:: 1.5.0
 
            An out-of-range ``srcport`` or ``dstport`` raises
diff --git a/pcapkit/protocols/transport/transport.py b/pcapkit/protocols/transport/transport.py
index e4b100874..0535c517a 100644
--- a/pcapkit/protocols/transport/transport.py
+++ b/pcapkit/protocols/transport/transport.py
@@ -79,7 +79,7 @@ class Transport(ProtocolBase[_PT, _ST], Generic[_PT, _ST]):  # pylint: disable=a
         Arguments:
             code: port number
             protocol: module descriptor or a
-                :class:`~pcapkit.protocols.protocol.Protocol` subclass
+                :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
 
         Important:
             This method must be called from a non-abstract class, as the
@@ -99,7 +99,7 @@ class Transport(ProtocolBase[_PT, _ST], Generic[_PT, _ST]):  # pylint: disable=a
                 :class:`~pcapkit.corekit.module.ModuleDescriptor` counts as
                 different from the class it names. See
                 :meth:`ProtocolBase.register
-                <pcapkit.protocols.protocol.Protocol.register>` for the
+                <pcapkit.protocols.protocol.ProtocolBase.register>` for the
                 guard this shares with ``register_protocol``, and for the
                 shipped descriptor that a restore puts back (:issue:`1504`).
 
@@ -115,7 +115,7 @@ class Transport(ProtocolBase[_PT, _ST], Generic[_PT, _ST]):  # pylint: disable=a
 
            Takes the protocol as one ``protocol`` argument, a
            :class:`~pcapkit.corekit.module.ModuleDescriptor` or a
-           :class:`~pcapkit.protocols.protocol.Protocol` subclass, in place of
+           :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass, in place of
            the ``module`` and ``class_`` names.
 
         """
diff --git a/pcapkit/protocols/transport/udp.py b/pcapkit/protocols/transport/udp.py
index 224d1c8ec..931420089 100644
--- a/pcapkit/protocols/transport/udp.py
+++ b/pcapkit/protocols/transport/udp.py
@@ -228,6 +228,10 @@ class UDP(Transport[Data_UDP, Schema_UDP],
         Returns:
             Constructed packet data.
 
+        Raises:
+            ProtocolError: If ``srcport`` or ``dstport`` is a :obj:`bool`
+                (:issue:`2287`).
+
         .. versionchanged:: 1.5.0
 
            An out-of-range ``srcport`` or ``dstport`` raises
diff --git a/tests/protocols/test_maker_invalid_format_messages_2406_unit.py b/tests/protocols/test_maker_invalid_format_messages_2406_unit.py
index aada9efb8..41562b964 100644
--- a/tests/protocols/test_maker_invalid_format_messages_2406_unit.py
+++ b/tests/protocols/test_maker_invalid_format_messages_2406_unit.py
@@ -20,8 +20,9 @@ wording:
 The parse side is deliberately untouched, as in #2296: ``invalid format`` is the
 right thing for a reader to say. :class:`ReadersKeepInvalidFormat` below pins
 that division on the one pair where the reader and the maker guard the very same
-thing -- ``_read_opt_pad`` and ``_make_opt_pad`` both reject a ``Pad1`` carrying
-a non-zero length.
+thing -- ``_read_opt_pad`` and ``_make_opt_pad`` guard a ``Pad1`` carrying a
+non-zero length, though only the reader raises; the maker warns and makes a
+``PadN`` instead.
 
 Every message is pinned whole, and every maker's valid input is exercised in the
 same class, so a guard that starts refusing good input regresses here too.
@@ -211,9 +212,10 @@ class PCAPNGBlockMessage(MakerMessageTestCase):
 class ReadersKeepInvalidFormat(MakerMessageTestCase):
     """The parse side still says ``invalid format``, as #2296 asks.
 
-    ``_read_opt_pad`` and ``_make_opt_pad`` reject the same thing -- a ``Pad1``
-    option carrying a non-zero length -- so the pair is where a sweep over the
-    makers is most likely to catch a reader by accident.
+    ``_read_opt_pad`` and ``_make_opt_pad`` guard the same thing -- a ``Pad1``
+    option carrying a non-zero length -- though only the reader raises; the
+    maker warns and makes a ``PadN`` instead. The pair is where a sweep over
+    the makers is most likely to catch a reader by accident.
 
     """

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Coverage: 91.72% (unit tier, Python 3.15, 4c569facb, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 2 95.16%
pcapkit/const 19609 880 2620 867 92.12%
pcapkit/corekit 2596 74 818 37 96.51%
pcapkit/dumpkit 282 3 102 3 98.44%
pcapkit/foundation 3045 24 1062 26 98.78%
pcapkit/interface 138 4 52 3 96.32%
pcapkit/protocols 17576 195 4668 181 98.30%
pcapkit/toolkit 924 36 334 10 95.55%
pcapkit/utilities 502 7 144 5 98.14%
pcapkit/vendor 4449 1961 1020 167 52.64%

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

@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 28, 2026
@JarryShaw
JarryShaw force-pushed the sweep/1103-whole-repo-prose branch from 56c8fbc to ac5016b Compare October 28, 2026 13:51
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: NEEDS CHANGES at ac5016b41 (Sonnet, re-review). Code and content are clean — independent 3-way AST/bytecode guard confirms all 16 files prose-only, spot-checks against the actual code all hold, test counts match main exactly (2107 passed/80 skipped/10265 subtests on tests/project/ in full).

Three leftover narration spots missed by the last round, all docstring-only:

Non-blocking: test_protocol_code_registration_unit.py:418-424 narrates #2268's old behavior in the past tense, same pattern, already disclosed as deliberately deferred — folding it in now would save a round but isn't required.

@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 28, 2026
@JarryShaw
JarryShaw force-pushed the sweep/1103-whole-repo-prose branch from ac5016b to 8c259cb Compare October 28, 2026 14:26
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: NEEDS CHANGES at 8c259cbd (Sonnet, re-review, round 4).

All four claimed fixes confirmed real and accurate (re-derived each from the actual code: LinkType.__proto_dest__ resolution, the exact count of enums declaring it, the reader/maker warn-vs-raise distinction, register_protocol_code's check-then-register loop). AST guard confirms all 16 files prose-only. Tests: 130 passed/1 skipped/334 subtests (the "135" in the commit message was stale, now corrected).

Two things left:

  1. PR body is stale — still describes revision 1 ("the one touched .py file", lists protocol.py/link.py/transport.py/hip.py/internet.py as "left untouched"), but all five are now in the diff. Rewrite from the current commit message.
  2. Same narration category recurring, milder form: test_maker_invalid_format_messages_2296_unit.py:11,14, ..._2406_unit.py:20,165, test_vendor_proto_dest_2392_unit.py:236 — "deliberately untouched", "left alone", "has not widened", "their output is unchanged". This is the fourth round catching this same pattern. For this pass, broaden the search beyond the specific lines named each round: grep for untouched|unchanged|left alone|widened|fixed on|did not list|yet|left to across every file this PR has touched (not just the ones flagged this round) and judge each hit, rather than fixing only the named spots.

Line 2 of ..._2406_unit.py ("did not list name their argument") is a reduced relative clause, not a typo — awkward but not wrong. Not blocking.

@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 28, 2026
@JarryShaw
JarryShaw force-pushed the sweep/1103-whole-repo-prose branch from 8c259cb to acdcae2 Compare October 28, 2026 14:56
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: NEEDS CHANGES at acdcae2a (Sonnet, round 5). Word class is now exhausted — independently re-grepped all 16 files (72 hits, read every one in context), confirmed the 9 round-5 fixes are accurate and present-tense, AST guard clean, 129 passed/1 skipped/334 subtests. Two small required fixes left:

  1. tests/vendor/test_vendor_proto_dest_2392_unit.py:116 — "is why refactor(foundation): declare each registry's code kind as a class attribute, not a module table (#2343) #2392 settled on it" (the same "settled on" pattern fixed at line 55, missed here).
  2. tests/protocols/test_maker_invalid_format_messages_2296_unit.py:4-9 — "Every _make_* builder... says so in the house form" overclaims (only 105 of 243 maker raise-sites use that form, e.g. MH._make_opt_hnp doesn't). Restore the scoping main had ("Several... Each site" / "The _make_* builders below").

Optional, outside this PR's touched files, not blocking: hip.py:3987 ("the maker built octets") and :4798-4800 ("has been resolving... all along") have the same past-tense pattern but are untouched by this PR — the reviewer's word class didn't include "all along"/"built", which is why these were missed; leave for a future round. PR body nits: doesn't use the repo template, title still says #1103 while scope is #2296-#2407, null.py's new versionchanged displays Protocol.protochain but targets ProtocolBase.protochain.

After these two fixes, this PR should be ready — no need for another full 25-minute review round.

@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 28, 2026
…egistry and registration prose (#1103)

#1103 whole-repo prose sweep over the maker-message wave (#2296, #2404, #2405,
#2407) and the __proto_dest__ registry refactor (#2392, #2403).

Docstrings corrected where the prose did not match the code:

* ``Protocol`` -> ``ProtocolBase`` in the ``register``/``register_protocol``
  cross-references (protocol.py, internet.py, link.py, transport.py, sctp.py,
  registry/protocols.py).
* ``Raises:`` entries for the ``bool`` port guard (#2287) in TCP, UDP and SCTP
  ``make``, and for HTTP/1's request-without-``uri`` guard.
* ``protochain`` documented on both sides of its narrowing to ``None``
  (protocol.py, misc/null.py, #2317), and ``__init__`` names the
  ``__own_make_keywords__`` exception to its keyword check.
* IP reassembly names the IPv6 ``M`` bit and which buffer an atomic fragment is
  isolated from (#2270); ``_check_code`` names ``register_protocol_code`` among
  its callers (#2186).
* HIP's shared lifetime helper says where the octet appears instead of counting
  the makers that carry it, and ``_make_opt_pad`` warns and makes a ``PadN``
  rather than raising as its reader does.

Before/after narration replaced with present tense, the pattern #1103's round 6
banned:

* the ``__proto_dest__`` prose in the registration and vendor tests, and the
  ``register_protocol_code`` key-check narration;
* the #2296 and #2406 maker-message module docstrings -- readers are exempt by
  design rather than "deliberately untouched", and the HTTP ``frame=None`` case
  is outside the guard rather than one the guard "has not widened to";
* the ``_NameLease`` rationale and the ``register_protocol`` name-collision
  note in registry/protocols.py, which described a fix and a redesign in the
  past tense;
* TCP's ``_make_mptcp_unknown`` length comment, which contrasted the current
  expression with "the former" one.

AST guard (``ast.dump`` via util/vendor_code_changed.py's ``code_of``, with
docstrings and bare string literals stripped) confirms all 16 touched files are
prose-only against e48062c. 129 tests pass (1 pre-existing skip) with 334
subtests across the four touched test modules, tests/test_docstring_contract.py,
tests/project/test_conventions_doc_claims.py,
tests/project/test_docs_issue_pr_roles_1103_unit.py and
tests/project/test_issue_refs_in_comments.py.
@JarryShaw
JarryShaw force-pushed the sweep/1103-whole-repo-prose branch from acdcae2 to 4c569fa Compare October 28, 2026 15:23
@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 28, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Review: GOOD TO GO at 4c569fac (Sonnet, round 6 — narrow final check). All three claimed fixes confirmed: the delta from round 5 is exactly 4 insertions/4 deletions across the 3 named files, nothing else. AST guard confirms all 16 files identical in structure vs the merge-base. 82 passed/1 skipped/310 subtests. No maker-side invalid format raise remains under pcapkit/protocols, confirming the #2406 title's accuracy. One non-blocking cosmetic nit: null.py's new block displays Protocol.protochain but targets ProtocolBase.protochain — fine to land as is.

@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 28, 2026
@JarryShaw
JarryShaw merged commit 8f3f3e5 into main Oct 28, 2026
65 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in PyPCAPKit Oct 28, 2026
@JarryShaw
JarryShaw deleted the sweep/1103-whole-repo-prose branch October 28, 2026 15:51
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Pull requests that change documentation only (docs: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant