diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index de373b6f3d..e6b63dd514 100755 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -158,7 +158,9 @@ The job drives them through the `Makefile` rather than restating their flags (`v variables, so a check cannot come out clean locally and red in CI because the two drifted. **Those steps are advisory, not a gate.** Each carries `continue-on-error: true`, so a finding lands -as a non-blocking annotation and a red linter will not fail your pull request. The workflow's +as a non-blocking annotation and a red one will not fail your pull request. The job's `actionlint` +step is the exception — it lints `.github/workflows/`, has no `Makefile` target, and carries no +`continue-on-error`, so a finding there does fail the job. The workflow's header records which of them are clean and what each of the others would need before its `continue-on-error` line could be deleted. Read the job's run summary, where each step writes its verdict, and try not to add to the numbers. diff --git a/docs/source/contributing/conventions/utilities-or-corekit.rst b/docs/source/contributing/conventions/utilities-or-corekit.rst index 871dd7b5a1..1a4b00e4db 100644 --- a/docs/source/contributing/conventions/utilities-or-corekit.rst +++ b/docs/source/contributing/conventions/utilities-or-corekit.rst @@ -9,11 +9,11 @@ who uses them. This rule can be checked from the import graph alone, and it need the fewest moves: one. :mod:`pcapkit.utilities` **is for cross-cutting services**: exceptions, warnings, -logging, the compatibility layer, configuration, and wrappers around third-party -libraries such as :mod:`~pcapkit.utilities.chardet`. The question to ask of a module -is *could any code use this service, and does it import nothing from* :mod:`pcapkit` -*outside* ``utilities``? Both halves have to hold, and *nothing* covers a top-level -import, one inside a function and one under ``TYPE_CHECKING`` alike. +logging, the compatibility layer, configuration, timestamp conversion, and wrappers +around third-party libraries such as :mod:`~pcapkit.utilities.chardet`. The question +to ask of a module is *could any code use this service, and does it import nothing +from* :mod:`pcapkit` *outside* ``utilities``? Both halves have to hold, and *nothing* +covers a top-level import, one inside a function and one under ``TYPE_CHECKING`` alike. :file:`tests/project/test_utilities_import_boundary_1735_unit.py` checks every module under :file:`pcapkit/utilities/` for it. diff --git a/docs/source/pcapkit/protocols/index.rst b/docs/source/pcapkit/protocols/index.rst index bbf9c04857..6eb1c2aa40 100644 --- a/docs/source/pcapkit/protocols/index.rst +++ b/docs/source/pcapkit/protocols/index.rst @@ -99,6 +99,7 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`: Raw --> FTP_DATA ARP --> RARP IPv6_Ext --> AH & ESP + Internet --> HIP B --> C(Protocol) C --> D([user customisation ...]) diff --git a/pcapkit/corekit/context.py b/pcapkit/corekit/context.py index 386ec160d1..b1b601f856 100644 --- a/pcapkit/corekit/context.py +++ b/pcapkit/corekit/context.py @@ -20,13 +20,13 @@ Rather than adding protocol specific keyword arguments to :class:`~pcapkit.foundation.extraction.Extractor`, such information is passed as a :class:`ContextRegistry` -- a mapping of protocol index ID -(cf. :meth:`Protocol.id `) +(cf. :meth:`ProtocolBase.id `) to a :class:`ProtocolContext` instance. The registry is handed to :class:`~pcapkit.foundation.extraction.Extractor` once, and is then propagated down the protocol stack by -:meth:`Protocol._import_next_layer `, +:meth:`ProtocolBase._import_next_layer `, so that a protocol nested arbitrarily deep can reach it through -:meth:`Protocol._get_context `. +:meth:`ProtocolBase._get_context `. Example: Decoding an ESP tunnel end to end:: @@ -90,7 +90,7 @@ def protocol(cls) -> 'tuple[str, ...]': """Index ID of the protocol(s) this context applies to. The returned names are matched against - :meth:`Protocol.id `, + :meth:`ProtocolBase.id `, and are case insensitive. """ diff --git a/pcapkit/corekit/decorators.py b/pcapkit/corekit/decorators.py index 633e86aae6..9c7182d6ae 100644 --- a/pcapkit/corekit/decorators.py +++ b/pcapkit/corekit/decorators.py @@ -67,9 +67,9 @@ def seekset(func: 'Callable[Concatenate[ProtocolBase, P], R_seekset]') -> 'Calla Important: This decorator function is designed for decorating *instance methods*. - The decorator will keep the current offset of :attr:`self._file `, + The decorator will keep the current offset of :attr:`self._file `, then call the decorated function. Afterwards, it will rewind the offset of - :attr:`self._file ` to the original and return the return value from + :attr:`self._file ` to the original and return the return value from the decorated function. Note: @@ -79,7 +79,7 @@ def seekset(func: 'Callable[Concatenate[ProtocolBase, P], R_seekset]') -> 'Calla *args: 'typing.Any', **kwargs: 'typing.Any') -> 'typing.Any' See Also: - :meth:`pcapkit.protocols.protocol.Protocol._read_packet` + :meth:`pcapkit.protocols.protocol.ProtocolBase._read_packet` :param func: decorated function :meta decorator: @@ -130,7 +130,7 @@ def beholder( *args: 'typing.Any', **kwargs: 'typing.Any') -> 'pcapkit.protocols.protocol.ProtocolBase' See Also: - :meth:`pcapkit.protocols.protocol.Protocol._decode_next_layer` + :meth:`pcapkit.protocols.protocol.ProtocolBase._decode_next_layer` .. versionchanged:: 1.3.0 diff --git a/pcapkit/foundation/reassembly/data/data.py b/pcapkit/foundation/reassembly/data/data.py index 1504e1ecab..93268b422e 100644 --- a/pcapkit/foundation/reassembly/data/data.py +++ b/pcapkit/foundation/reassembly/data/data.py @@ -134,7 +134,7 @@ class Deferred: Args: analyze: The analyser to call, i.e. - :meth:`Protocol.analyze ` + :meth:`ProtocolBase.analyze ` bound to the reassembly object's protocol. proto: Payload protocol type. payload: Reassembled payload to parse. diff --git a/pcapkit/protocols/application/application.py b/pcapkit/protocols/application/application.py index f33d1050de..cbf7cb5ae7 100644 --- a/pcapkit/protocols/application/application.py +++ b/pcapkit/protocols/application/application.py @@ -86,7 +86,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, See Also: For construction arguments, please refer to - :meth:`self.make `. + :meth:`self.make `. """ # call super post-init @@ -144,7 +144,7 @@ def _decode_next_layer(self, dict_: '_PT', proto: 'Optional[int]' = None, length proto: next layer protocol index; only the ``-1`` sentinel (the rest, undissected) is accepted length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Current protocol with the undissected remainder as payload. @@ -167,7 +167,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # proto: next layer protocol index; only the ``-1`` sentinel (the rest, undissected) is accepted length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Instance of :class:`~pcapkit.protocols.misc.raw.Raw`, or of diff --git a/pcapkit/protocols/application/ftp.py b/pcapkit/protocols/application/ftp.py index 37e42b1c42..888d51f0b7 100644 --- a/pcapkit/protocols/application/ftp.py +++ b/pcapkit/protocols/application/ftp.py @@ -312,7 +312,7 @@ def _decode_args(self, args: 'Optional[bytes]') -> 'tuple[Optional[str], Optiona """Decode arguments, recording how to encode them back. The arguments are decoded by :meth:`self.decode - `. Where the result does + `. Where the result does not encode back to ``args`` as UTF-8 -- which :meth:`make` uses by default -- the detected charset is returned with it, or ``'latin-1'`` (decoding again) if that does not reproduce ``args`` either, so that the diff --git a/pcapkit/protocols/application/httpv1.py b/pcapkit/protocols/application/httpv1.py index ad0336555c..124366fa57 100644 --- a/pcapkit/protocols/application/httpv1.py +++ b/pcapkit/protocols/application/httpv1.py @@ -418,7 +418,7 @@ def _decode_text(self, text: 'bytes') -> 'tuple[str, Optional[str]]': """Decode start-line text, recording how to encode it back. The text is decoded by :meth:`self.decode - `. Where the result does + `. Where the result does not encode back to ``text`` as UTF-8 -- which :meth:`make` uses by default -- the detected charset is returned with it, or ``'latin-1'`` (decoding again) if that does not reproduce ``text`` either, so that the diff --git a/pcapkit/protocols/application/httpv2.py b/pcapkit/protocols/application/httpv2.py index e2575d5e13..08e84b3930 100644 --- a/pcapkit/protocols/application/httpv2.py +++ b/pcapkit/protocols/application/httpv2.py @@ -251,7 +251,7 @@ def unpack(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> 'Data_HTTP' if length is None: # ``0 < ... < 9`` rather than ``... < 9``: an exhausted stream # (``len(self) == 0``) is left alone, so ``length`` reaches - # :meth:`Protocol.unpack ` + # :meth:`ProtocolBase.unpack ` # still ``None`` and its ``prepare`` decorator raises # :exc:`StreamEOFError` as documented above; only a *non-empty* # short stream is rejected as malformed here. diff --git a/pcapkit/protocols/application/ngap.py b/pcapkit/protocols/application/ngap.py index 356a0ecd3a..8bcea2156f 100644 --- a/pcapkit/protocols/application/ngap.py +++ b/pcapkit/protocols/application/ngap.py @@ -31,7 +31,7 @@ (``pip install pypcapkit[NGAP]``). :mod:`pcapkit` imports and works without it; an NGAP payload simply degrades to the opaque payload path, exactly as an unregistered PPID would, because -:meth:`~pcapkit.protocols.protocol.Protocol._import_next_layer`, which +:meth:`~pcapkit.protocols.protocol.ProtocolBase._import_next_layer`, which :class:`~pcapkit.protocols.transport.sctp.SCTP` inherits, is wrapped in :func:`~pcapkit.corekit.decorators.beholder` and falls back to :class:`~pcapkit.protocols.misc.raw.Raw`. diff --git a/pcapkit/protocols/application/ospf.py b/pcapkit/protocols/application/ospf.py index f1cda117b7..c6cc575acb 100644 --- a/pcapkit/protocols/application/ospf.py +++ b/pcapkit/protocols/application/ospf.py @@ -112,9 +112,9 @@ class OSPF(Application[Data_OSPF, Schema_OSPF], """ #: Version number of corresponding protocol, as read off the header. Held on #: the instance rather than read back out of :attr:`self._info - #: ` because :attr:`name` and + #: ` because :attr:`name` and #: :attr:`alias` are needed *during* :meth:`read` -- :meth:`self._decode_next_layer - #: ` builds the + #: ` builds the #: protocol chain out of :attr:`alias` -- and ``_info`` is not assigned until #: :meth:`read` has returned. See ``ARP._acnm`` on #: :class:`~pcapkit.protocols.link.arp.ARP`, which has the same constraint. @@ -403,7 +403,7 @@ def _make_id_numbers(self, id: 'IPv4Address | str | bytes | bytearray') -> 'byte The description below uses :attr:`self.__class__.__name__ ` rather than :attr:`self.alias - `, because ``alias`` + `, because ``alias`` here reads ``self._version``, which :meth:`read` only assigns from the wire -- unavailable to a construction-only instance that never went through :meth:`read`. diff --git a/pcapkit/protocols/data/data.py b/pcapkit/protocols/data/data.py index 1f6ecebef3..8ee68b528c 100644 --- a/pcapkit/protocols/data/data.py +++ b/pcapkit/protocols/data/data.py @@ -19,7 +19,7 @@ class Data(Info): The ``__next_name__``, ``__next_type__`` and ``__short_read__`` keys are metadata, listed in :attr:`~pcapkit.corekit.infoclass.Info.__included__` and :attr:`~pcapkit.corekit.infoclass.Info.__excluded__`: - :meth:`Protocol.from_data ` + :meth:`ProtocolBase.from_data ` dispatches the payload on the first two and on nothing else, and cuts a short read back on the third. :meth:`to_dict` carries them, so that ``from_data(info.to_dict())`` rebuilds as ``from_data(info)`` does, while diff --git a/pcapkit/protocols/data/internet/hip.py b/pcapkit/protocols/data/internet/hip.py index 5170f35d3b..52db6c699c 100644 --- a/pcapkit/protocols/data/internet/hip.py +++ b/pcapkit/protocols/data/internet/hip.py @@ -520,9 +520,7 @@ class CertParameter(Parameter): #: Certificate group -- :rfc:`8002#section-2`'s "Group ID grouping #: multiple related CERT parameters". An arbitrary number, since that #: section leaves the CERT group namespace to each sending host, so no - #: registry stands behind it; it used to decode through the - #: Diffie-Hellman group registry and report a group of ``7`` as the curve - #: ``NIST_P_256``. See :issue:`2283`. + #: registry stands behind it. See :issue:`2283`. cert_group: 'int' #: Certificate count. cert_count: 'int' diff --git a/pcapkit/protocols/internet/esp.py b/pcapkit/protocols/internet/esp.py index e7eb6a2637..7dcc950682 100644 --- a/pcapkit/protocols/internet/esp.py +++ b/pcapkit/protocols/internet/esp.py @@ -1470,7 +1470,7 @@ def _make_opaque(self, spi: 'int', seq: 'int', total: 'int', payload_data: 'byte The payload is surfaced as :class:`~pcapkit.protocols.misc.raw.Raw` -- which is what a next header of :data:`None` resolves to -- so that - :attr:`self.payload ` + :attr:`self.payload ` and the protocol chain behave as they do for any other protocol, and the trailer fields are left :data:`None` rather than guessed at. diff --git a/pcapkit/protocols/internet/internet.py b/pcapkit/protocols/internet/internet.py index 5e986a7a83..8e9c3a6980 100644 --- a/pcapkit/protocols/internet/internet.py +++ b/pcapkit/protocols/internet/internet.py @@ -431,7 +431,7 @@ def _decode_next_layer(self, dict_: '_PT', proto: 'Optional[int]' = None, # pyl dict\_: info buffer proto: next layer protocol index length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) version: IP version ipv6_exthdr: protocol chain of IPv6 extension headers payload: payload from packet. If not provided, will extract from @@ -480,7 +480,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # Arguments: proto: next layer protocol index length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) version: IP protocol version extension: if is extension header payload: payload from packet. If not provided, will extract from diff --git a/pcapkit/protocols/internet/ipv6.py b/pcapkit/protocols/internet/ipv6.py index 60ee9a05c4..4e790d86ea 100644 --- a/pcapkit/protocols/internet/ipv6.py +++ b/pcapkit/protocols/internet/ipv6.py @@ -506,7 +506,7 @@ def _decode_next_layer(self, ipv6: 'Data_IPv6', proto: 'Optional[int]' = None, ipv6: info buffer proto: next layer protocol index length: valid (*not padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Current protocol with next layer extracted. @@ -685,7 +685,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # Arguments: proto: next layer protocol index length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) version: IP protocol version extension: if is extension header payload: payload from packet. If not provided, will extract from diff --git a/pcapkit/protocols/internet/ipv6_ext.py b/pcapkit/protocols/internet/ipv6_ext.py index a79ed722a5..638cdf4ed8 100644 --- a/pcapkit/protocols/internet/ipv6_ext.py +++ b/pcapkit/protocols/internet/ipv6_ext.py @@ -108,7 +108,7 @@ class for that code instead (see the bottom of the module), so dispatch ``IPv6-Route``, ``IPv6-Opts``, ``MH``, ``HIP``, ``IPv6-Frag`` and ``AH`` all have dedicated classes. When one of *those* raises, :func:`~pcapkit.corekit.decorators.beholder` - (:meth:`Protocol._import_next_layer `) + (:meth:`ProtocolBase._import_next_layer `) would substitute plain :class:`~pcapkit.protocols.misc.raw.Raw`, which loses ``next`` and crashes the walk as in path 1. :meth:`IPv6._import_next_layer ` @@ -299,7 +299,7 @@ def protocol(self) -> 'Optional[Enum_ExtensionHeader] | Optional[str]': In the *fallback* role (this instance parsed this module's own schema) this is **not** the base - :attr:`Protocol.protocol ` + :attr:`ProtocolBase.protocol ` meaning ("name of next layer protocol"). On the owner's ruling for GitHub issue :issue:`891` it is deliberately repointed at this instance's *own* identity, i.e. which header's format it parsed, such as diff --git a/pcapkit/protocols/internet/mh.py b/pcapkit/protocols/internet/mh.py index b4b3fb8d32..081b464b1f 100644 --- a/pcapkit/protocols/internet/mh.py +++ b/pcapkit/protocols/internet/mh.py @@ -575,11 +575,10 @@ class FastBindingAcknowledgmentStatus(EnumLookup, IntEnum): :class:`~pcapkit.corekit.enum.EnumLookup`, like every other :class:`int`-valued registry here, so a key that is neither an :class:`int` nor a :class:`str` raises - :exc:`~pcapkit.utilities.exceptions.EnumValueError`. A ``get`` override - was rejected (decided on :issue:`935`; the override was deleted, not - widened to accept ``default``): this class mints no alias - (``__members__`` and ``list(cls)`` hold the same members), so an override - could only repeat the base's dual :class:`int`/name resolution. + :exc:`~pcapkit.utilities.exceptions.EnumValueError`. This class mints + no alias (``__members__`` and ``list(cls)`` hold the same members), so + an override could only repeat the base's dual :class:`int`/name + resolution (see :issue:`935`). """ @@ -646,11 +645,10 @@ class IPv6AddressPrefixCode(EnumLookup, IntEnum): :class:`~pcapkit.corekit.enum.EnumLookup`, like every other :class:`int`-valued registry here, so a key that is neither an :class:`int` nor a :class:`str` raises - :exc:`~pcapkit.utilities.exceptions.EnumValueError`. A ``get`` override - was rejected (decided on :issue:`935`; the override was deleted, not - widened to accept ``default``): this class mints no alias - (``__members__`` and ``list(cls)`` hold the same members), so an override - could only repeat the base's dual :class:`int`/name resolution. + :exc:`~pcapkit.utilities.exceptions.EnumValueError`. This class mints + no alias (``__members__`` and ``list(cls)`` hold the same members), so + an override could only repeat the base's dual :class:`int`/name + resolution (see :issue:`935`). """ diff --git a/pcapkit/protocols/link/arp.py b/pcapkit/protocols/link/arp.py index 4d67155c6d..fc5a49b232 100644 --- a/pcapkit/protocols/link/arp.py +++ b/pcapkit/protocols/link/arp.py @@ -420,7 +420,7 @@ def _make_addr_resolve(self, addr: 'str | bytes | bytearray', htype: 'int') -> ' Notes: The messages are prefixed with :attr:`self.__class__.__name__ ` rather than :attr:`self.alias - `, for the reason + `, for the reason :meth:`_make_proto_resolve` gives. """ @@ -480,7 +480,7 @@ def _make_proto_resolve(self, addr: 'IPv4Address | IPv6Address | str | bytes', p The messages are prefixed with :attr:`self.__class__.__name__ ` rather than :attr:`self.alias - `, even though the + `, even though the latter is this project's usual choice: :attr:`alias` here reads ``self._acnm``, which :meth:`read` only assigns once the operation code is known, and this method runs from :meth:`make` -- before diff --git a/pcapkit/protocols/link/c_tag.py b/pcapkit/protocols/link/c_tag.py index 0d94745fe1..012830276b 100644 --- a/pcapkit/protocols/link/c_tag.py +++ b/pcapkit/protocols/link/c_tag.py @@ -71,7 +71,7 @@ def alias(self) -> 'Literal["802.1Q"]': #: class-name default -- a rename must not silently move the output key. @property def info_name(self) -> 'Literal["c_tag"]': - """Key name of the :attr:`~pcapkit.protocols.protocol.Protocol.info` dict.""" + """Key name of the :attr:`~pcapkit.protocols.protocol.ProtocolBase.info` dict.""" return 'c_tag' ########################################################################## diff --git a/pcapkit/protocols/link/l2tp.py b/pcapkit/protocols/link/l2tp.py index b946c78c2e..1bb5447f0d 100644 --- a/pcapkit/protocols/link/l2tp.py +++ b/pcapkit/protocols/link/l2tp.py @@ -40,7 +40,7 @@ :attr:`Internet.__proto__ ` leaves 115 unbound: the binding waits on an ``L2TPv3`` class, not on a different framing decision. It also means v3 is the first member of this family -to have a real :meth:`~pcapkit.protocols.protocol.Protocol.__index__`. +to have a real :meth:`~pcapkit.protocols.protocol.ProtocolBase.__index__`. Binding :class:`~pcapkit.protocols.link.l2tpv2.L2TPv2` at 115 instead does not work (:issue:`548`), and is recorded so it is not proposed again. Over IP the v3 @@ -62,7 +62,7 @@ the value 1 "to permit detection of L2F packets should they arrive intermixed with L2TP packets". L2F is a separate protocol with its own header. It is therefore to be implemented as ``L2F``, the canonical name, carrying ``L2TPv1`` -only as an alias in its :meth:`~pcapkit.protocols.protocol.Protocol.id`. See +only as an alias in its :meth:`~pcapkit.protocols.protocol.ProtocolBase.id`. See :meth:`HTTPv1.id ` for how a version-flavoured alias is spelled: canonical name first, alias second, since callers take element zero as canonical. @@ -118,8 +118,8 @@ class L2TP(Link[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstract-metho It is abstract for the same mechanical reason :class:`~pcapkit.protocols.internet.ip.IP` is: - :attr:`~pcapkit.protocols.protocol.Protocol.name` and - :meth:`~pcapkit.protocols.protocol.Protocol.read` are both declared + :attr:`~pcapkit.protocols.protocol.ProtocolBase.name` and + :meth:`~pcapkit.protocols.protocol.ProtocolBase.read` are both declared abstract by :class:`~pcapkit.protocols.protocol.ProtocolBase` and neither is defined here, so the class cannot be instantiated. Bind a version, never this class. @@ -138,12 +138,12 @@ class L2TP(Link[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstract-metho #: NOTE: Declared on the base, and so shared by every version, deliberately. #: This is the key the parsed datagram appears under, and a consumer wants #: ``udp.l2tp`` whichever version was on the wire -- the version is reported - #: by :attr:`~pcapkit.protocols.protocol.Protocol.alias` instead. Left to + #: by :attr:`~pcapkit.protocols.protocol.ProtocolBase.alias` instead. Left to #: the class-name default it would read ``l2tpv2``, ``l2tpv3`` and so on, and #: every consumer would have to know the version to find the data. @property def info_name(self) -> 'Literal["l2tp"]': - """Key name of the :attr:`~pcapkit.protocols.protocol.Protocol.info` dict.""" + """Key name of the :attr:`~pcapkit.protocols.protocol.ProtocolBase.info` dict.""" return 'l2tp' ########################################################################## diff --git a/pcapkit/protocols/link/link.py b/pcapkit/protocols/link/link.py index 228a38b71b..49d9ae445f 100644 --- a/pcapkit/protocols/link/link.py +++ b/pcapkit/protocols/link/link.py @@ -72,9 +72,9 @@ class Link(ProtocolBase[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=abstra #: Protocol index mapping for decoding next layer, see #: :meth:`self._decode_next_layer - #: ` & + #: ` & #: :meth:`self._import_next_layer - #: `. + #: `. __proto__ = collections.defaultdict( lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), { @@ -178,7 +178,7 @@ def from_data(cls, data: '_PT | dict[str, Any]', **kwargs: 'Any') -> 'Self': Args: data: Protocol data. **kwargs: Construction keywords, as for :meth:`ProtocolBase.from_data - `. + `. Returns: Protocol instance, cut back to what was captured when the header @@ -202,7 +202,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, Notes: A header the data ends inside keeps that in its - :attr:`~pcapkit.protocols.protocol.Protocol.info`, so that + :attr:`~pcapkit.protocols.protocol.ProtocolBase.info`, so that :meth:`from_data` rebuilds only what was captured (:issue:`1458`). """ diff --git a/pcapkit/protocols/link/loopback.py b/pcapkit/protocols/link/loopback.py index 73664d89b7..1b221bd297 100644 --- a/pcapkit/protocols/link/loopback.py +++ b/pcapkit/protocols/link/loopback.py @@ -85,7 +85,7 @@ class Loopback(Link[Data_Loopback, Schema_Loopback], ``alias`` it was dispatched with; for ``LINKTYPE_NULL``, which a frame parsed on its own is read as, the byte order is read from the octets themselves (see :func:`family_byteorder`). Either way it is kept in - :attr:`~pcapkit.protocols.protocol.Protocol.info`, and + :attr:`~pcapkit.protocols.protocol.ProtocolBase.info`, and :meth:`from_data ` reads the family back in that byte order rather than inferring it again. @@ -119,9 +119,9 @@ class Loopback(Link[Data_Loopback, Schema_Loopback], #: Protocol index mapping for decoding next layer, see #: :meth:`self._decode_next_layer - #: ` & + #: ` & #: :meth:`self._import_next_layer - #: `. Keyed by + #: `. Keyed by #: address family rather than by EtherType, so this class keeps a registry #: of its own instead of sharing :attr:`Link.__proto__ #: `. @@ -182,7 +182,7 @@ def read(self, length: 'Optional[int]' = None, *, alias: 'Optional[int]' = None, anything else as ``LINKTYPE_NULL``. byteorder: Byte order to read the family in, ahead of ``alias``. :meth:`make` is handed the one - :attr:`~pcapkit.protocols.protocol.Protocol.info` holds by + :attr:`~pcapkit.protocols.protocol.ProtocolBase.info` holds by :meth:`from_data `, and it reaches here too, so a rebuild reads the family as it was parsed rather than inferring it again. diff --git a/pcapkit/protocols/link/s_tag.py b/pcapkit/protocols/link/s_tag.py index 68c17f4dea..1a3a53379a 100644 --- a/pcapkit/protocols/link/s_tag.py +++ b/pcapkit/protocols/link/s_tag.py @@ -68,7 +68,7 @@ def alias(self) -> 'Literal["802.1ad"]': #: and customer tag apart in the parsed info dict. @property def info_name(self) -> 'Literal["s_tag"]': - """Key name of the :attr:`~pcapkit.protocols.protocol.Protocol.info` dict.""" + """Key name of the :attr:`~pcapkit.protocols.protocol.ProtocolBase.info` dict.""" return 's_tag' ########################################################################## diff --git a/pcapkit/protocols/link/vlan.py b/pcapkit/protocols/link/vlan.py index 1787cffc54..58aeff8049 100644 --- a/pcapkit/protocols/link/vlan.py +++ b/pcapkit/protocols/link/vlan.py @@ -33,14 +33,14 @@ They are nonetheless distinct classes rather than one class bound at two EtherTypes, because 802.1ad *stacks* them: a Q-in-Q frame carries a service tag whose next EtherType is ``0x8100``, selecting a customer tag in turn. Both tags -therefore appear in one frame, and :attr:`~pcapkit.protocols.protocol.Protocol.info_name` +therefore appear in one frame, and :attr:`~pcapkit.protocols.protocol.ProtocolBase.info_name` -- ``s_tag`` against ``c_tag`` -- is what keeps them apart in the parsed :class:`~pcapkit.corekit.infoclass.Info`. A single class bound at both EtherTypes would nest one ``c_tag`` inside another, leaving nothing in the output to say which of the two was the service tag. Two distinct EtherTypes also mean two distinct -:meth:`~pcapkit.protocols.protocol.Protocol.__index__` values, which is the +:meth:`~pcapkit.protocols.protocol.ProtocolBase.__index__` values, which is the project's rule for when protocols get separate modules: siblings that *share* an index may share a module, as :class:`~pcapkit.protocols.link.arp.InARP` shares :mod:`~pcapkit.protocols.link.arp` and @@ -83,12 +83,12 @@ class VLAN(Link[Data_VLAN, Schema_VLAN], # pylint: disable=abstract-method The class implements the whole of the tag -- both parsing and construction -- since the customer and service tags are byte-for-byte identical. What it deliberately leaves to its subclasses is only how the tag *names* itself: - :attr:`~pcapkit.protocols.protocol.Protocol.name`, - :attr:`~pcapkit.protocols.protocol.Protocol.alias` and - :attr:`~pcapkit.protocols.protocol.Protocol.info_name`. + :attr:`~pcapkit.protocols.protocol.ProtocolBase.name`, + :attr:`~pcapkit.protocols.protocol.ProtocolBase.alias` and + :attr:`~pcapkit.protocols.protocol.ProtocolBase.info_name`. It is abstract for the same reason :class:`~pcapkit.protocols.internet.ip.IP` - is: :attr:`~pcapkit.protocols.protocol.Protocol.name` is declared + is: :attr:`~pcapkit.protocols.protocol.ProtocolBase.name` is declared abstract by :class:`~pcapkit.protocols.protocol.ProtocolBase` and is not defined here, so the class cannot be instantiated. Bind :class:`~pcapkit.protocols.link.c_tag.C_Tag` or diff --git a/pcapkit/protocols/misc/pcap/frame.py b/pcapkit/protocols/misc/pcap/frame.py index 11028754f5..a61410c7c6 100644 --- a/pcapkit/protocols/misc/pcap/frame.py +++ b/pcapkit/protocols/misc/pcap/frame.py @@ -23,7 +23,7 @@ .. versionchanged:: 1.5.0 - ``bytes(frame)`` and :attr:`~pcapkit.protocols.protocol.Protocol.packet` + ``bytes(frame)`` and :attr:`~pcapkit.protocols.protocol.ProtocolBase.packet` hold this frame's own octets, where they held the next frame's (:issue:`357`), and the parsed ``time`` is timezone-aware UTC. The parsed ``len`` is the on-wire length and ``cap_len`` the captured one, where the @@ -101,8 +101,8 @@ class Frame(ProtocolBase[Data_Frame, Schema_Frame], ########################################################################## #: Protocol index mapping for decoding the next layer; see - #: :meth:`self._decode_next_layer ` - #: and :meth:`self._import_next_layer `. + #: :meth:`self._decode_next_layer ` + #: and :meth:`self._import_next_layer `. #: Each value is a :class:`~pcapkit.corekit.module.ModuleDescriptor` naming the #: module and class, or a :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass. __proto__ = collections.defaultdict( @@ -216,7 +216,7 @@ def pack(self, **kwargs: 'Any') -> 'bytes': global packet data to underlying methods. This is useful when the packet data is not available in the current instance. - As in :meth:`Protocol.pack `, + As in :meth:`ProtocolBase.pack `, the header is made on a copy outside construction, so the instance keeps its own (:issue:`1769`). @@ -521,7 +521,7 @@ def _check_record_floor(self, length: 'Optional[int]') -> 'None': Args: length: Length of packet data, as the caller declared it, or :obj:`None` to measure what is left in - :attr:`self._file `. + :attr:`self._file `. Raises: StreamEOFError: If fewer than sixteen octets are left to read. @@ -636,7 +636,7 @@ def _decode_next_layer(self, dict_: 'Data_Frame', proto: 'Optional[int]' = None, dict\_: info buffer proto: next layer protocol index length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Current protocol with packet extracted. diff --git a/pcapkit/protocols/misc/pcap/header.py b/pcapkit/protocols/misc/pcap/header.py index 71da285923..db5554707a 100644 --- a/pcapkit/protocols/misc/pcap/header.py +++ b/pcapkit/protocols/misc/pcap/header.py @@ -253,7 +253,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, Notes: A header the data ends inside keeps that in its - :attr:`~pcapkit.protocols.protocol.Protocol.info`, so that + :attr:`~pcapkit.protocols.protocol.ProtocolBase.info`, so that :meth:`~pcapkit.protocols.protocol.ProtocolBase.from_data` rebuilds only what was captured (:issue:`1470`). diff --git a/pcapkit/protocols/misc/pcapng.py b/pcapkit/protocols/misc/pcapng.py index 634c558e3b..936f7d9618 100644 --- a/pcapkit/protocols/misc/pcapng.py +++ b/pcapkit/protocols/misc/pcapng.py @@ -349,7 +349,7 @@ def _block_type_name(block_type: 'Enum_BlockType') -> 'str': ``block_type`` is looked up rather than having its :attr:`~enum.Enum.name` read directly, because :attr:`PCAPNG._type ` is only an :class:`~pcapkit.const.pcapng.block_type.BlockType` on the parse path. - On the make path :meth:`~pcapkit.protocols.protocol.Protocol._make_index` + On the make path :meth:`~pcapkit.protocols.protocol.ProtocolBase._make_index` returns a plain :obj:`int`, which the assignment in :meth:`PCAPNG.make ` only :func:`~typing.cast` to the enumeration, so reading ``.name`` off it @@ -760,8 +760,8 @@ class PCAPNG(ProtocolBase[Data_PCAPNG, Schema_PCAPNG], ########################################################################## #: Protocol index mapping for decoding the next layer; see - #: :meth:`self._decode_next_layer ` - #: and :meth:`self._import_next_layer `. + #: :meth:`self._decode_next_layer ` + #: and :meth:`self._import_next_layer `. #: Each value is a :class:`~pcapkit.corekit.module.ModuleDescriptor` naming the #: module and class, or a :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass. __proto__ = collections.defaultdict( @@ -1254,7 +1254,7 @@ def pack(self, **kwargs: 'Any') -> 'bytes': global packet data to underlying methods. This is useful when the packet data is not available in the current instance. - As in :meth:`Protocol.pack `, + As in :meth:`ProtocolBase.pack `, the header is made on a copy outside construction, so the instance keeps its own header, block type, byte order and option counts (:issue:`1769`). @@ -1654,7 +1654,7 @@ def _check_block_floor(self, length: 'Optional[int]') -> 'None': Args: length: Length of packet data, as the caller declared it, or :obj:`None` to measure what is left in - :attr:`self._file `. + :attr:`self._file `. Raises: StreamEOFError: If fewer than twelve octets are left to read. @@ -1717,7 +1717,7 @@ def _captured(self, offset: 'int') -> 'int': Returns: Octets from ``offset`` to the end of - :attr:`self._file `. + :attr:`self._file `. """ current = self._file.tell() @@ -1757,10 +1757,10 @@ def _read_block_cut(self, header: 'Schema_PCAPNG', offset: 'int', ) def _get_payload(self) -> 'bytes': - """Get payload of :attr:`self.__header__ `. + """Get payload of :attr:`self.__header__ `. Returns: - Payload of :attr:`self.__header__ ` as :obj:`bytes`. + Payload of :attr:`self.__header__ ` as :obj:`bytes`. See Also: This is a wrapper function for :meth:`pcapkit.protocols.schema.schema.Schema.get_payload`. @@ -2247,7 +2247,7 @@ def _decode_next_layer(self, dict_: 'Data_PCAPNG', proto: 'Optional[int]' = None dict\_: info buffer proto: next layer protocol index length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Current protocol with packet extracted. diff --git a/pcapkit/protocols/misc/raw.py b/pcapkit/protocols/misc/raw.py index 3151628686..5398403516 100644 --- a/pcapkit/protocols/misc/raw.py +++ b/pcapkit/protocols/misc/raw.py @@ -7,7 +7,7 @@ :mod:`pcapkit.protocols.misc.raw` contains :class:`~pcapkit.protocols.misc.raw.Raw` only, which implements an extractor for unknown protocols, and constructs a -:class:`~pcapkit.protocols.protocol.Protocol` like object. +:class:`~pcapkit.protocols.protocol.ProtocolBase` like object. """ import io diff --git a/pcapkit/protocols/protocol.py b/pcapkit/protocols/protocol.py index 05f883e271..2083851bb7 100644 --- a/pcapkit/protocols/protocol.py +++ b/pcapkit/protocols/protocol.py @@ -213,7 +213,7 @@ def _raw_where_parsed(made: 'Any', parsed: 'Any') -> 'bool': #: Keywords that configure the construction rather than naming a field, and are #: therefore consumed by :meth:`ProtocolBase.__init__ #: ` or by the schema layer -#: instead of by a :meth:`make `. No +#: instead of by a :meth:`make `. No #: signature declares them, so :func:`_declared_keywords` cannot find them and #: they are listed here. #: @@ -244,9 +244,9 @@ def _raw_where_parsed(made: 'Any', parsed: 'Any') -> 'bool': #: Methods a construction keyword may be destined for. The keywords handed to #: :class:`Protocol` reach all of them: :meth:`ProtocolBase.__post_init__ #: ` passes the same -#: ``**kwargs`` to :meth:`pack ` (and +#: ``**kwargs`` to :meth:`pack ` (and #: through it to ``make``) *and* to :meth:`unpack -#: ` (and through it to ``read``). +#: ` (and through it to ``read``). _KEYWORD_CONSUMERS = ('make', 'read', 'pack', 'unpack', '__post_init__', '__init__') @@ -523,8 +523,8 @@ class ProtocolBase(Generic[_PT, _ST], metaclass=ProtocolMeta): __layer__: 'Optional[Literal["Link", "Internet", "Transport", "Application"]]' = None #: Protocol index mapping for decoding the next layer; see - #: :meth:`self._decode_next_layer ` - #: and :meth:`self._import_next_layer `. + #: :meth:`self._decode_next_layer ` + #: and :meth:`self._import_next_layer `. #: Each value is a :class:`~pcapkit.corekit.module.ModuleDescriptor` naming the #: module and class, or a :class:`ProtocolBase` subclass. __proto__: 'DefaultDict[int, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]' = collections.defaultdict( @@ -591,7 +591,7 @@ class ProtocolBase(Generic[_PT, _ST], metaclass=ProtocolMeta): __reconstructing__: 'bool' = False #: Caller supplied parsing context; see :mod:`pcapkit.corekit.context`. - #: :meth:`self.__init__ ` replaces this with a real + #: :meth:`self.__init__ ` replaces this with a real #: :class:`~pcapkit.corekit.context.ContextRegistry`; the class-level #: :data:`None` is what an instance built without ``__init__`` (e.g. #: ``object.__new__(SomeProtocol)``) sees, so reading it is always safe. @@ -734,7 +734,7 @@ def id(cls) -> 'tuple[str, ...]': the method may return multiple values. See Also: - :meth:`pcapkit.protocols.protocol.Protocol.__getitem__` + :meth:`pcapkit.protocols.protocol.ProtocolBase.__getitem__` """ return (cls.__name__,) @@ -822,7 +822,7 @@ def pack(self, **kwargs: 'Any') -> 'bytes': .. versionchanged:: 1.5.0 Calling it no longer replaces the instance's - :attr:`__header__ `, which left :attr:`schema` + :attr:`__header__ `, which left :attr:`schema` disagreeing with :attr:`info` (:issue:`1769`). """ @@ -874,7 +874,7 @@ def unpack(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> '_PT': packet data to underlying methods. This is useful when the packet data is not available in the current instance. - When :attr:`self.__header__ ` is already set, + When :attr:`self.__header__ ` is already set, by :meth:`from_schema` or by the :meth:`pack` call that :meth:`__post_init__` makes to construct the instance, that schema is kept, unless it still holds raw :obj:`bytes` where parsing its @@ -970,10 +970,10 @@ def expand_comp(value: 'str | ProtocolBase | Type[ProtocolBase]') -> 'tuple': 1. If ``value`` is a protocol instance, the method will return the protocol class, and the protocol names in upper case obtained from - :meth:`Protocol.id `. + :meth:`ProtocolBase.id `. 2. If ``value`` is a protocol class, the method will return the protocol class itself, and the protocol names in upper case - obtained from :meth:`Protocol.id `. + obtained from :meth:`ProtocolBase.id `. 3. If ``value`` is :obj:`str`, the method will attempt to search for the existing registered protocol class from :data:`pcapkit.protocols.__proto__` and follow **step 2**; otherwise, @@ -1248,11 +1248,11 @@ def __init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Optional file: Source packet stream. length: Length of packet data. _layer (str): Parse packet until ``_layer`` - (:attr:`self._exlayer `). + (:attr:`self._exlayer `). While parsing, the un-prefixed ``layer`` is accepted as well -- see the note below. _protocol: Parse packet until ``_protocol`` - (:attr:`self._exproto `), + (:attr:`self._exproto `), given as a protocol name (:obj:`str`), a protocol class or a protocol instance. While parsing, the un-prefixed ``protocol`` is accepted as well -- @@ -1261,16 +1261,17 @@ def __init__(self, file: 'Optional[IO[bytes] | bytes]' = None, length: 'Optional handed over by :meth:`self._import_next_layer `. While parsing, it is republished as ``__packet__`` so that - :meth:`self.unpack ` -- and through it the + :meth:`self.unpack ` -- and through it the schema -- can see it; see the note below. - __context__: Caller supplied parsing context (:attr:`self._exctx `; + __context__: Caller supplied parsing context + (:attr:`self._exctx `; see :mod:`pcapkit.corekit.context`): a :class:`~pcapkit.corekit.context.ContextRegistry`, a :class:`~pcapkit.corekit.context.ProtocolContext`, a mapping of names to :class:`~pcapkit.corekit.context.ProtocolContext`, or an iterable of :class:`~pcapkit.corekit.context.ProtocolContext`. It is consumed here rather - than being forwarded to :meth:`self.read `, and is + than being forwarded to :meth:`self.read `, and is propagated to nested layers by :meth:`self._import_next_layer `. **kwargs: Arbitrary keyword arguments. @@ -1427,7 +1428,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, See Also: For construction arguments, please refer to - :meth:`self.make `. + :meth:`self.make `. """ if file is None: @@ -1460,8 +1461,8 @@ def __init_subclass__(cls, /, schema: 'Optional[Type[_ST]]' = None, UnsupportedCall: If any unrecognised class keyword is given. This method is called when a subclass of :class:`ProtocolBase` is defined. - It is used to set the :attr:`self.__schema__ ` - and :attr:`self.__data__ ` + It is used to set the :attr:`self.__schema__ ` + and :attr:`self.__data__ ` attributes of the subclass, and, if ``code`` is given, to register the subclass into the next-layer dispatch :term:`registry` (or registries) that ``code`` names -- e.g. :attr:`Link.__proto__ @@ -1617,14 +1618,14 @@ def __length_hint__(self) -> 'Optional[int]': """Return an estimated length for the object.""" def __iter__(self) -> 'IO[bytes]': - """Iterate through :attr:`self._data `.""" + """Iterate through :attr:`self._data `.""" return io.BytesIO(self._data) def __getitem__(self, key: 'str | Protocol | Type[Protocol]') -> 'ProtocolBase': """Subscription (``getitem``) support. * If ``key`` is a :class:`~pcapkit.protocols.protocol.Protocol` object, - the method will fetch its indexes (:meth:`self.id `). + the method will fetch its indexes (:meth:`self.id `). * Later, search the packet's chain of protocols with the calculated ``key``. * If no matches, then raises :exc:`~pcapkit.utilities.exceptions.ProtocolNotFound`. @@ -1639,7 +1640,7 @@ def __getitem__(self, key: 'str | Protocol | Type[Protocol]') -> 'ProtocolBase': See Also: The method calls - :meth:`self.expand_comp ` + :meth:`self.expand_comp ` to handle the ``key`` and expand it for robust searching. """ @@ -1671,7 +1672,7 @@ def __contains__(self, name: 'str | Protocol | Type[Protocol]') -> 'bool': See Also: The method calls - :meth:`self.expand_comp ` + :meth:`self.expand_comp ` to handle the ``name`` and expand it for robust searching. """ @@ -1719,7 +1720,7 @@ def __eq__(cls, other: 'object') -> 'bool': return False def __hash__(self) -> 'int': - """Return the hash value for :attr:`self._data `.""" + """Return the hash value for :attr:`self._data `.""" return hash(self._data) ########################################################################## @@ -1752,10 +1753,10 @@ def _get_context(self, cls: 'Optional[Type[_CTX]]' = None) -> 'Optional[_CTX]': return registry.match(self.id(), cls) def _get_payload(self) -> 'bytes': - """Get payload from :attr:`self.__header__ `. + """Get payload from :attr:`self.__header__ `. Returns: - Payload of :attr:`self.__header__ ` as :obj:`bytes`. + Payload of :attr:`self.__header__ ` as :obj:`bytes`. See Also: This is a wrapper function for :meth:`pcapkit.protocols.schema.schema.Schema.get_payload`. @@ -1775,7 +1776,7 @@ def _read_protos(self, size: int) -> 'Optional[StdlibEnum | AenumEnum]': # pyli """ def _read_fileng(self, *args: 'Any', **kwargs: 'Any') -> 'bytes': - """Read file buffer (:attr:`self._file `). + """Read file buffer (:attr:`self._file `). This method wraps the :meth:`file.read ` call. @@ -2176,7 +2177,7 @@ def _make_payload(cls, data: 'Data') -> 'ProtocolBase': :class:`~pcapkit.protocols.misc.null.NoPayload` instance will be returned, exactly as for a protocol with no next layer. Otherwise, the payload will be constructed by :meth:`Protocol.from_data - `. + `. :meth:`Info.to_dict ` carries both keys, so ``data`` rebuilt from such a :obj:`dict` dispatches as @@ -2303,7 +2304,7 @@ def _decode_next_layer(self, dict_: '_PT', proto: 'int', length: 'Optional[int]' dict\_: info buffer proto: next layer protocol index length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Current protocol with next layer extracted. @@ -2342,7 +2343,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, Arguments: proto: next layer protocol index length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Instance of next layer. @@ -2519,8 +2520,8 @@ def __init_subclass__(cls, /, schema: 'Optional[Type[_ST]]' = None, **kwargs: Arbitrary keyword arguments. This method is called when a subclass of :class:`Protocol` is defined. - It is used to set the :attr:`self.__schema__ ` - and :attr:`self.__data__ ` + It is used to set the :attr:`self.__schema__ ` + and :attr:`self.__data__ ` attributes of the subclass. Notes: diff --git a/pcapkit/protocols/schema/internet/esp.py b/pcapkit/protocols/schema/internet/esp.py index 5f3566d917..70a24b3666 100644 --- a/pcapkit/protocols/schema/internet/esp.py +++ b/pcapkit/protocols/schema/internet/esp.py @@ -29,7 +29,7 @@ class ESP(Schema): This also means :attr:`payload` is **not** the next layer's data: the next layer lives inside the ciphertext, and is handed to - :meth:`Protocol._decode_next_layer ` + :meth:`ProtocolBase._decode_next_layer ` explicitly once decrypted. """ diff --git a/pcapkit/protocols/schema/internet/hip.py b/pcapkit/protocols/schema/internet/hip.py index d90abc54d6..a4faa0c9cc 100644 --- a/pcapkit/protocols/schema/internet/hip.py +++ b/pcapkit/protocols/schema/internet/hip.py @@ -418,13 +418,15 @@ def parameter_total_len(length: 'int') -> 'int': def parameter_padding_len(pkt: 'dict[str, Any]') -> 'int': """Return the number of padding octets a HIP parameter needs. - Used by the ``padding`` field of every parameter schema in this module. - The count is whatever :func:`parameter_total_len` leaves over once the - four-octet ``Type`` and ``Length`` header and the ``Length`` octets of - contents are accounted for, which :rfc:`7401` Section 5.2.1 bounds at + Used by the ``padding`` field of every parameter schema in this module + except :class:`LocatorSetParameter`, which needs + :func:`locator_set_padding_len` instead (see its ``padding`` field for + why). The count is whatever :func:`parameter_total_len` leaves over once + the four-octet ``Type`` and ``Length`` header and the ``Length`` octets + of contents are accounted for, which :rfc:`7401` Section 5.2.1 bounds at "0-7 bytes". - This is one function shared by every parameter rather than a lambda + This is one function shared by those parameters rather than a lambda repeated per class, so the RFC's arithmetic is stated in one place. Args: diff --git a/pcapkit/protocols/schema/internet/ipv6_route.py b/pcapkit/protocols/schema/internet/ipv6_route.py index d22fc6e1f8..23be77e230 100644 --- a/pcapkit/protocols/schema/internet/ipv6_route.py +++ b/pcapkit/protocols/schema/internet/ipv6_route.py @@ -269,7 +269,7 @@ def post_process(self, packet: 'dict[str, Any]') -> 'Schema': # # NOTE: ``ip`` still has to be *set*, though, rather than merely # left alone. :meth:`Protocol.__post_init__ - # ` packs and + # ` packs and # then unpacks, and :meth:`IPv6_Route.read # ` hands # :meth:`~pcapkit.protocols.internet.ipv6_route.IPv6_Route._read_data_type_rpl` diff --git a/pcapkit/protocols/schema/link/ethernet.py b/pcapkit/protocols/schema/link/ethernet.py index 02221eeaf6..9e885edae7 100644 --- a/pcapkit/protocols/schema/link/ethernet.py +++ b/pcapkit/protocols/schema/link/ethernet.py @@ -30,7 +30,7 @@ def callback_payload(self: 'PayloadField', packet: 'dict[str, Any]') -> 'None': Important: The lookup goes through :meth:`ProtocolBase._lookup_next_layer - ` rather than + ` rather than subscripting the registry. :attr:`Ethernet.__proto__ ` *is* :attr:`Link.__proto__ `, a diff --git a/pcapkit/protocols/schema/schema.py b/pcapkit/protocols/schema/schema.py index 0bbf3e1045..403358c380 100644 --- a/pcapkit/protocols/schema/schema.py +++ b/pcapkit/protocols/schema/schema.py @@ -377,7 +377,7 @@ class Schema(Mapping[str, _VT], Generic[_VT], metaclass=SchemaMeta): :class:`~pcapkit.corekit.fields.numbers.NumberField` masks an out-of-range integer to its width on packing, so e.g. ``70000`` in a two-octet field packs as ``0x1170``. The range checks live in each - protocol's :meth:`~pcapkit.protocols.protocol.Protocol.make`, and in a + protocol's :meth:`~pcapkit.protocols.protocol.ProtocolBase.make`, and in a field whose values have a range of their own, such as :class:`~pcapkit.corekit.fields.numbers.PortEnumField`. See GitHub issue :issue:`2314`. @@ -1232,7 +1232,7 @@ class _EnumRegistry(collections.defaultdict): block falls back to its ``Unknown*``/``Unassigned*`` schema -- so this subclass keeps returning it and just stops recording it. :meth:`ProtocolBase._lookup_registry - ` + ` does the same for the protocol-layer ``__proto__`` family. """ diff --git a/pcapkit/protocols/transport/sctp.py b/pcapkit/protocols/transport/sctp.py index 45d217f73a..ab4a326eb8 100644 --- a/pcapkit/protocols/transport/sctp.py +++ b/pcapkit/protocols/transport/sctp.py @@ -454,7 +454,7 @@ class SCTP(Transport[Data_SCTP, Schema_SCTP], #: :meth:`self._decode_next_layer #: ` & #: :meth:`self._import_next_layer - #: `. + #: `. #: #: Important: #: Keyed by the DATA chunk's *payload protocol identifier* (PPID), **not** @@ -982,7 +982,7 @@ def _decode_next_layer(self, dict_: 'Data_SCTP', proto: 'Optional[int]' = None, proto: payload protocol identifier of the DATA chunk carrying the payload, if any length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Current protocol with next layer extracted. @@ -1000,9 +1000,9 @@ def _decode_next_layer(self, dict_: 'Data_SCTP', proto: 'Optional[int]' = None, does for an unregistered transport type. Resolving it to :class:`~pcapkit.protocols.misc.raw.Raw` is :meth:`ProtocolBase._import_next_layer - `'s job, + `'s job, through :meth:`ProtocolBase._lookup_next_layer - `, which + `, which leaves :attr:`self.__proto__ ` untouched. """ diff --git a/pcapkit/protocols/transport/tcp.py b/pcapkit/protocols/transport/tcp.py index 82304c9359..19916b01c3 100644 --- a/pcapkit/protocols/transport/tcp.py +++ b/pcapkit/protocols/transport/tcp.py @@ -338,7 +338,7 @@ class TCP(Transport[Data_TCP, Schema_TCP], #: :meth:`self._decode_next_layer #: ` & #: :meth:`self._import_next_layer - #: `. + #: `. __proto__ = collections.defaultdict( lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), { diff --git a/pcapkit/protocols/transport/transport.py b/pcapkit/protocols/transport/transport.py index 0535c517a9..cbc3fae1ef 100644 --- a/pcapkit/protocols/transport/transport.py +++ b/pcapkit/protocols/transport/transport.py @@ -44,7 +44,7 @@ class Transport(ProtocolBase[_PT, _ST], Generic[_PT, _ST]): # pylint: disable=a if TYPE_CHECKING: #: Protocol index mapping for decoding next layer, #: see :meth:`self._decode_next_layer ` - #: & :meth:`self._import_next_layer `. + #: & :meth:`self._import_next_layer `. __proto__: 'DefaultDict[int, ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]]' ########################################################################## @@ -171,7 +171,7 @@ def from_data(cls, data: '_PT | dict[str, Any]', **kwargs: 'Any') -> 'Self': Args: data: Protocol data. **kwargs: Construction keywords, as for :meth:`ProtocolBase.from_data - `. + `. Returns: Protocol instance, cut back to what was captured when the header @@ -195,7 +195,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, Notes: A header the data ends inside keeps that in its - :attr:`~pcapkit.protocols.protocol.Protocol.info`, so that + :attr:`~pcapkit.protocols.protocol.ProtocolBase.info`, so that :meth:`from_data` rebuilds only what was captured (:issue:`1458`). """ @@ -223,7 +223,7 @@ def _make_port(cls, port: 'Enum_AppType | int', ProtocolError: If ``port`` is a :obj:`bool` (:issue:`2287`). Important: - :meth:`self.make ` accepts + :meth:`self.make ` accepts a bare :obj:`int` for a port, but the schema field converts it only on the way *out* (in :meth:`PortEnumField.pre_process @@ -254,7 +254,7 @@ def _decode_next_layer(self, dict_: '_PT', ports: 'tuple[int, int]', length: 'Op dict_: info buffer ports: source & destination port numbers length: valid (*non-padding*) length - packet: packet info (passed from :meth:`self.unpack `) + packet: packet info (passed from :meth:`self.unpack `) Returns: Current protocol with next layer extracted. @@ -262,7 +262,7 @@ def _decode_next_layer(self, dict_: '_PT', ports: 'tuple[int, int]', length: 'Op Important: The port is forwarded **whether or not it is registered**: :meth:`ProtocolBase._import_next_layer - ` passes + ` passes it on as ``alias`` and :class:`~pcapkit.protocols.misc.raw.Raw` records it as :attr:`Data_Raw.protocol `. Dropping it would diff --git a/pcapkit/protocols/transport/udp.py b/pcapkit/protocols/transport/udp.py index 9314200893..df0996d7c1 100644 --- a/pcapkit/protocols/transport/udp.py +++ b/pcapkit/protocols/transport/udp.py @@ -75,7 +75,7 @@ class UDP(Transport[Data_UDP, Schema_UDP], .. versionchanged:: 1.5.0 :meth:`make` takes ``total_length``, which a - :meth:`~pcapkit.protocols.protocol.Protocol.from_data` rebuild + :meth:`~pcapkit.protocols.protocol.ProtocolBase.from_data` rebuild passes so that a truncated capture keeps its declared Length (:issue:`1155`), and ``trailer``, so that the octets past the Length field rebuild as captured (:issue:`1461`). @@ -90,7 +90,7 @@ class UDP(Transport[Data_UDP, Schema_UDP], #: :meth:`self._decode_next_layer #: ` & #: :meth:`self._import_next_layer - #: `. + #: `. __proto__ = collections.defaultdict( lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), { diff --git a/pcapkit/utilities/chardet.py b/pcapkit/utilities/chardet.py index d3685836f2..f52cf5d83d 100644 --- a/pcapkit/utilities/chardet.py +++ b/pcapkit/utilities/chardet.py @@ -38,7 +38,7 @@ def detect(value: 'bytes') -> 'str': retains 19.1 MB. :data:`~pcapkit.utilities.config.DETECT_CACHE_SIZE` therefore caps the entries rather than the footprint, which matters because :meth:`ProtocolBase.decode - ` is public and a caller + ` is public and a caller may hand it a whole payload. Use :meth:`detect.cache_clear ` to release it in a long-running process. diff --git a/tests/const/test_const_enum_builtin_parity.py b/tests/const/test_const_enum_builtin_parity.py index 733cfa8965..3905603b3e 100644 --- a/tests/const/test_const_enum_builtin_parity.py +++ b/tests/const/test_const_enum_builtin_parity.py @@ -2,14 +2,15 @@ """Every :mod:`pcapkit.const` registry must reject an invalid value the way the built-in does. GitHub issue #647 counted the generated range guards under :mod:`pcapkit.const` -and found that 113 of the 117 modules raise a bare :exc:`ValueError`. The issue +and found that nearly all of the modules raise a bare :exc:`ValueError`, with +only a handful behaving differently (enumerated below). The issue proposed replacing them with :class:`~pcapkit.utilities.exceptions.EnumError`; the decision went the other way. A bare :exc:`ValueError` is exactly what :class:`enum.IntEnum` raises for a value it does not define, mirroring the built-in is the intent, and :class:`~pcapkit.utilities.exceptions.EnumError` is ``(BaseError, TypeError)`` -- not a :exc:`ValueError` at all -- so swapping it in would have diverged from the -built-in *and* walked past the ``except ValueError`` in all 113 generated +built-in *and* walked past the ``except ValueError`` in most of the generated ``get()`` bodies, silently undoing GitHub issue #584. What was left was the inconsistency. Six registries across four modules did diff --git a/tests/project/test_annotation_names.py b/tests/project/test_annotation_names.py index bb1f128ff2..ee900bee0b 100644 --- a/tests/project/test_annotation_names.py +++ b/tests/project/test_annotation_names.py @@ -5,8 +5,8 @@ need inside an ``if TYPE_CHECKING:`` block. Nothing at runtime evaluates those strings, so a name that is *never imported at all* costs nothing until a type checker or a documentation build looks at it -- at which point it is an error in a -file that has been passing tests for months. Issue #642 found these, and mypy -2.3.1 agreed they were the complete set: +file whose tests all pass. Issue #642 found these, and mypy 2.3.1 agreed they were +the complete set: .. code-block:: text