Skip to content

Commit 8f3f3e5

Browse files
authored
docs: #719-style prose sweep after the #1090-1102 defect wave (#2408)
#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.
1 parent e0847a1 commit 8f3f3e5

16 files changed

Lines changed: 151 additions & 107 deletions

File tree

‎pcapkit/foundation/reassembly/ip.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ class IP(ReassemblyBase[Packet[_AT], Datagram[_AT], BufferID, Buffer[_AT]], Gene
6767
<pcapkit.foundation.reassembly.data.ip.Datagram.conflict>`
6868
(:issue:`477`). An incomplete buffer expires
6969
after ``timeout`` seconds of capture time, 60 by default for both IPv4
70-
and IPv6. A datagram with fragment offset zero and **MF** clear is
71-
reported even when its BUFID is already buffered, rather than dropped
72-
(:issue:`2270`).
70+
and IPv6. A datagram with fragment offset zero and **MF** (**M** in
71+
IPv6) clear is reported even when its BUFID is already buffered,
72+
rather than dropped (:issue:`2270`).
7373
7474
"""
7575
if TYPE_CHECKING:
@@ -156,8 +156,10 @@ def reassembly(self, info: 'Packet[_AT]') -> 'None':
156156
# belong to.
157157
self._dtgram.extend(self.expire(TS))
158158

159-
# when non-fragmented (possibly discarded) packet received: it is
160-
# reassembled on its own, in a buffer of its own (#2270)
159+
# a datagram with fragment offset zero and MF clear is reported even
160+
# when its BUFID is already buffered, rather than dropped: isolated
161+
# from that buffer (IPv6 atomic fragments) or after flushing it first
162+
# (IPv4) (#2270)
161163
isolated = False
162164
if not FO and not MF:
163165
if self.__isolate_atomic__:

‎pcapkit/foundation/registry/protocols.py‎

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,9 @@ class rather than supplied by a caller, and this function is the funnel
200200
:class:`~pcapkit.foundation.reassembly.reassembly.ReassemblyMeta` and
201201
:class:`~pcapkit.foundation.traceflow.traceflow.TraceFlowMeta` fall back to
202202
:class:`~pcapkit.protocols.misc.raw.Raw`. The registry redesign of
203-
:issue:`514` left this key unchanged and recorded the shared namespace as a
204-
risk it did not fix, so the collision is reported here rather than
205-
resolved.
203+
:issue:`514` keeps this key, and its thread records the shared namespace as
204+
a risk that design does not resolve, so the collision is reported here
205+
rather than fixed.
206206
207207
Args:
208208
protocol: Protocol class.
@@ -256,10 +256,11 @@ class _NameLease:
256256
Each code registrar below ends by naming its class in the by-name registry,
257257
and :mod:`pcapkit.foundation.registry` has no ``unregister``: a code is
258258
undone by registering the entry it displaced (:issue:`1363`). Without a
259-
record of that by-name write, handing a code back restored the code and left
260-
the name behind (:issue:`1505`). A lease records what the write displaced and
261-
which codes still dispatch to the class, so the last of them to be handed
262-
back puts the displaced entry back, or removes the name if it was new.
259+
record of that by-name write, handing a code back would restore the code and
260+
leave the name behind (:issue:`1505`). A lease records what the write
261+
displaced and which codes still dispatch to the class, so the last of them
262+
to be handed back puts the displaced entry back, or removes the name if it
263+
was new.
263264
264265
A lease is one write, not one class: the same class can hold two leases on
265266
a name -- e.g. a built-in registered at one port over a custom class
@@ -366,9 +367,9 @@ def _register_name(protocol: 'Type[ProtocolBase]', *targets: 'tuple[type, Any]')
366367
releasing whatever each target code held before, and followed by a lease
367368
when the write changed the name, so that registering the code back undoes
368369
it (:issue:`1505`). A name already showing ``protocol`` -- shipped, defined
369-
by a :class:`~pcapkit.protocols.protocol.Protocol` subclass, or registered
370-
directly -- is not leased, so no restore takes it away; one showing it
371-
through a lease extends that lease to ``targets``.
370+
by a :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass, or
371+
registered directly -- is not leased, so no restore takes it away; one
372+
showing it through a lease extends that lease to ``targets``.
372373
373374
Args:
374375
protocol: Protocol class just registered -- and so validated -- at ``targets``.
@@ -565,12 +566,15 @@ def register_protocol_code(protocol: 'Type[ProtocolBase]', code: 'Any') -> 'None
565566

566567
def _check_code(code: 'Any', kind: 'type', target: 'Type[ProtocolBase]', *,
567568
number: 'bool' = False) -> 'None':
568-
"""Reject a registration key that is not a member of the registrar's enum.
569+
"""Reject a registration key that is not a member of the enum its
570+
destination registry is keyed by.
569571
570572
Each registrar typed on one enum calls this before touching any registry,
571-
so a bad ``code`` leaves every registry as it was (:issue:`2186`). The check is on the type,
572-
not the value: the registry enums compare equal to their values, so a
573-
member of another enum would key the entry of the member it equals, e.g.
573+
as does :func:`register_protocol_code` for an inferred or explicitly
574+
named destination, so a bad ``code`` leaves every registry as it was
575+
(:issue:`2186`). The check is on the type, not the value: the registry
576+
enums compare equal to their values, so a member of another enum would
577+
key the entry of the member it equals, e.g.
574578
:attr:`TransType.ICMP <pcapkit.const.reg.transtype.TransType.ICMP>` would
575579
replace :attr:`LinkType.ETHERNET <pcapkit.const.reg.linktype.LinkType.ETHERNET>`
576580
(:issue:`2224`).
@@ -580,7 +584,7 @@ def _check_code(code: 'Any', kind: 'type', target: 'Type[ProtocolBase]', *,
580584
kind: Enum the registrar is typed on.
581585
target: Protocol class whose registry ``code`` is destined for, named in
582586
the error message so a rejection says *whose* registry rejected the
583-
key rather than only what it wanted -- the registrars share one
587+
key rather than only what it wanted -- its callers share one
584588
message, and several of them are typed on the same enum.
585589
number: Whether a bare :class:`int` is a valid key too, as for the
586590
registrars keyed on a port number or a payload protocol identifier.

‎pcapkit/protocols/application/httpv1.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ def make(self, # type: ignore[override]
224224
225225
Raises:
226226
ProtocolError: If the values are neither a request's nor a
227-
response's, or if ``raw_line`` or a ``raw_header`` entry that
227+
response's, if they are a request's and ``uri`` is
228+
:obj:`None`, or if ``raw_line`` or a ``raw_header`` entry that
228229
reads back as the given values carries a CR or LF that the
229230
values do not (other than the CRLF of an ``obs-fold``).
230231
@@ -328,7 +329,8 @@ def _make_start_line(self, http_version: 'str | bytes', *,
328329
329330
Raises:
330331
ProtocolError: If the values are neither a request's nor a
331-
response's.
332+
response's, or if they are a request's and ``uri`` is
333+
:obj:`None`.
332334
333335
"""
334336
version = http_version.encode() if isinstance(http_version, str) else http_version

‎pcapkit/protocols/internet/hip.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,8 +1955,9 @@ def _make_lifetime_octet(self, code: 'Enum_Parameter', version: 'int',
19551955
19561956
An explicit ``exponent`` is the octet and wins, as a parsed parameter's
19571957
is; otherwise ``lifetime`` is a duration and
1958-
:meth:`_make_registration_lifetime` encodes it. Shared by the three
1959-
:rfc:`8003` makers, which between them carry four such octets.
1958+
:meth:`_make_registration_lifetime` encodes it. Shared by the
1959+
:rfc:`8003` registration makers, wherever a ``Lifetime`` octet
1960+
appears.
19601961
19611962
Args:
19621963
code: parameter code

‎pcapkit/protocols/internet/internet.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def register(cls, code: 'Enum_TransType', protocol: 'ModuleDescriptor[ProtocolBa
182182
Arguments:
183183
code: protocol code as in :class:`~pcapkit.const.reg.transtype.TransType`
184184
protocol: module descriptor or a
185-
:class:`~pcapkit.protocols.protocol.Protocol` subclass
185+
:class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
186186
187187
Raises:
188188
pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a

‎pcapkit/protocols/link/link.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def register(cls, code: 'Enum_EtherType', protocol: 'ModuleDescriptor[ProtocolBa
138138
Arguments:
139139
code: protocol code as in :class:`~pcapkit.const.reg.ethertype.EtherType`
140140
protocol: module descriptor or a
141-
:class:`~pcapkit.protocols.protocol.Protocol` subclass
141+
:class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
142142
143143
Raises:
144144
pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a
@@ -150,15 +150,15 @@ def register(cls, code: 'Enum_EtherType', protocol: 'ModuleDescriptor[ProtocolBa
150150
replacement so a caller can tell *what* was lost. Fires only
151151
when the incumbent differs from the replacement -- see
152152
:meth:`ProtocolBase.register
153-
<pcapkit.protocols.protocol.Protocol.register>` for the
153+
<pcapkit.protocols.protocol.ProtocolBase.register>` for the
154154
guard this shares with ``register_protocol``, and for the
155155
shipped descriptor that a restore puts back (:issue:`1504`).
156156
157157
.. versionchanged:: 1.3.0
158158
159159
Takes the protocol as one ``protocol`` argument, a
160160
:class:`~pcapkit.corekit.module.ModuleDescriptor` or a
161-
:class:`~pcapkit.protocols.protocol.Protocol` subclass, in place of
161+
:class:`~pcapkit.protocols.protocol.ProtocolBase` subclass, in place of
162162
the ``module`` and ``class_`` names.
163163
164164
"""

‎pcapkit/protocols/misc/null.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,17 @@ def protocol(self) -> 'NoReturn':
6868
@property
6969
def protochain(self) -> 'None': # type: ignore[override]
7070
"""Protocol chain of current instance, which an empty payload does not
71-
have."""
71+
have.
72+
73+
.. versionchanged:: 1.5.0
74+
75+
Narrows :attr:`Protocol.protochain
76+
<pcapkit.protocols.protocol.ProtocolBase.protochain>`'s declared
77+
type from :class:`~pcapkit.corekit.protochain.ProtoChain` to
78+
:obj:`None`, the value ``self._protos`` already held here; the fix
79+
is to the declaration, not the runtime value (:issue:`2317`).
80+
81+
"""
7282
return None
7383

7484
##########################################################################

‎pcapkit/protocols/protocol.py‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,15 @@ def protocol(self) -> 'Optional[str]':
661661
# protocol chain of current instance
662662
@property
663663
def protochain(self) -> 'ProtoChain':
664-
"""Protocol chain of current instance."""
664+
"""Protocol chain of current instance.
665+
666+
Note:
667+
:class:`~pcapkit.protocols.misc.null.NoPayload` has no chain and
668+
narrows this to :obj:`None`; :meth:`_decode_next_layer` passes it
669+
on as ``basis``, which
670+
:class:`~pcapkit.corekit.protochain.ProtoChain` accepts.
671+
672+
"""
665673
return self._protos
666674

667675
# packet data
@@ -1031,7 +1039,7 @@ def register(cls, code: 'int', protocol: 'ModuleDescriptor | Type[ProtocolBase]'
10311039
Arguments:
10321040
code: protocol code
10331041
protocol: module descriptor or a
1034-
:class:`~pcapkit.protocols.protocol.Protocol` subclass
1042+
:class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
10351043
10361044
Raises:
10371045
pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a
@@ -1271,9 +1279,12 @@ def __init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Optional
12711279
UnsupportedCall: When constructing (``file`` is :obj:`None`), if a
12721280
keyword names no parameter of this protocol's :meth:`make`,
12731281
:meth:`read`, :meth:`pack`, :meth:`unpack`,
1274-
:meth:`__post_init__` or :meth:`__init__`, anywhere in the MRO,
1275-
and is not listed in :attr:`__keywords__`. Parsing (``file`` is
1276-
given) is unaffected.
1282+
:meth:`__post_init__` or :meth:`__init__`, anywhere in the MRO
1283+
-- except a ``make`` whose class sets
1284+
:attr:`__own_make_keywords__`, which counts only while it is
1285+
the ``make`` of the protocol being constructed -- and is not
1286+
listed in :attr:`__keywords__`. Parsing (``file`` is given) is
1287+
unaffected.
12771288
12781289
Note:
12791290
The ``_layer``, ``_protocol`` and ``__context__`` keywords are

‎pcapkit/protocols/transport/sctp.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,10 @@ def make(self,
694694
Returns:
695695
Constructed packet data.
696696
697+
Raises:
698+
ProtocolError: If ``srcport`` or ``dstport`` is a :obj:`bool`
699+
(:issue:`2287`).
700+
697701
Note:
698702
There is no ``payload`` argument: SCTP carries its user data in the
699703
``data`` field of a DATA chunk, so the payload is supplied as part
@@ -730,7 +734,7 @@ def register(cls, code: 'Enum_PayloadProtocolIdentifier | int', protocol: 'Modul
730734
code: payload protocol identifier (PPID), as in
731735
:class:`~pcapkit.const.sctp.payload_protocol_identifier.PayloadProtocolIdentifier`
732736
protocol: module descriptor or a
733-
:class:`~pcapkit.protocols.protocol.Protocol` subclass
737+
:class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
734738
735739
Important:
736740
SCTP overrides :meth:`Transport.register

‎pcapkit/protocols/transport/tcp.py‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,10 @@ def make(self,
624624
Returns:
625625
Constructed packet data.
626626
627+
Raises:
628+
ProtocolError: If ``srcport`` or ``dstport`` is a :obj:`bool`
629+
(:issue:`2287`).
630+
627631
.. versionchanged:: 1.5.0
628632
629633
An out-of-range ``srcport`` or ``dstport`` raises
@@ -2900,13 +2904,13 @@ def _make_mptcp_unknown(self, subtype: 'Enum_MPTCPOption', opt: 'Optional[Data_M
29002904
# three octets of header -- ``kind``, ``length`` and the subtype/flags
29012905
# octet whose low nibble takes ``data[0]`` -- and then ``data[1:]`` as
29022906
# its body, so the option is never shorter than 3 octets -- the smallest
2903-
# Multipath TCP option :rfc:`8684` section 3 permits. The former
2904-
# ``2 + len(data)`` declared 2 for ``data=b''`` while still packing those
2905-
# three octets, and the segment could not be read back:
2906-
# ``MPTCPUnknown.data`` sizes itself ``pkt['length'] - 3``, which went
2907-
# negative and raised ``ProtocolError: Field data resolved to a negative
2908-
# length``. For every non-empty ``data`` the two expressions agree, so
2909-
# this only changes the empty case.
2907+
# Multipath TCP option :rfc:`8684` section 3 permits. A plain
2908+
# ``2 + len(data)`` would declare 2 for ``data=b''`` while those three
2909+
# octets are packed anyway, and the segment could not be read back:
2910+
# ``MPTCPUnknown.data`` sizes itself ``pkt['length'] - 3``, which would
2911+
# go negative and raise ``ProtocolError: Field data resolved to a
2912+
# negative length``. For every non-empty ``data`` the two expressions
2913+
# agree, so only the empty case tells them apart.
29102914
return Schema_MPTCPUnknown(
29112915
kind=cast('Enum_Option', Enum_Option.Multipath_TCP),
29122916
length=3 + len(data[1:]),

0 commit comments

Comments
 (0)