diff --git a/docs/source/contributing/conventions/protocol-family-grouping.rst b/docs/source/contributing/conventions/protocol-family-grouping.rst index 353916255a..e505c65735 100644 --- a/docs/source/contributing/conventions/protocol-family-grouping.rst +++ b/docs/source/contributing/conventions/protocol-family-grouping.rst @@ -363,5 +363,4 @@ holds :class:`~pcapkit.protocols.link.linux_sll1.LinuxSLL1`. **The** ``schema/`` ``data/`` **modules follow the same layout**: the top-level class takes the module's name, and sub-structure classes such as :class:`~pcapkit.protocols.schema.internet.igmpv3.Query` share its module. Ruled on -:issue:`2529`, where the class that does not match yet is pending: -:class:`null.NoPayload `. +:issue:`2529`. diff --git a/docs/source/ext.rst b/docs/source/ext.rst index 96ee461a60..1e66e65110 100644 --- a/docs/source/ext.rst +++ b/docs/source/ext.rst @@ -130,7 +130,7 @@ The protocol classes :mod:`pcapkit` ships: + +----------------+-----------------------+-------------------------------------------------------------+ | | :class:`pcapkit.protocols.misc.raw.Raw` | + +----------------+-----------------------+-------------------------------------------------------------+ -| | :class:`pcapkit.protocols.misc.null.NoPayload` | +| | :class:`pcapkit.protocols.misc.no_payload.NoPayload` | +------------------------------------------------------------------+----------------+-----------------------+-------------------------------------------------------------+ .. _ext-new-protocol: diff --git a/docs/source/pcapkit/protocols/index.rst b/docs/source/pcapkit/protocols/index.rst index a03d6daab4..8cd1e7fcab 100644 --- a/docs/source/pcapkit/protocols/index.rst +++ b/docs/source/pcapkit/protocols/index.rst @@ -190,7 +190,7 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`: click DTLS "application/dtls.html#pcapkit.protocols.application.dtls.DTLS" click Raw "misc/raw.html#pcapkit.protocols.misc.raw.Raw" - click NoPayload "misc/null.html#pcapkit.protocols.misc.null.NoPayload" + click NoPayload "misc/no_payload.html#pcapkit.protocols.misc.no_payload.NoPayload" click PCAPNG "misc/pcapng.html#pcapkit.protocols.misc.pcapng.PCAPNG" click Header "misc/pcap.html#pcapkit.protocols.misc.pcap.header.Header" click Frame "misc/pcap.html#pcapkit.protocols.misc.pcap.frame.Frame" diff --git a/docs/source/pcapkit/protocols/link/radiotap.rst b/docs/source/pcapkit/protocols/link/radiotap.rst index 992ab8d5a4..368e49d322 100644 --- a/docs/source/pcapkit/protocols/link/radiotap.rst +++ b/docs/source/pcapkit/protocols/link/radiotap.rst @@ -47,7 +47,7 @@ Decoding every optional field radiotap.org defines is tracked on :attr:`~pcapkit.protocols.data.link.radiotap.Radiotap.fields`. * **Hands** everything from ``it_len`` on, the 802.11 MAC frame, to :class:`~pcapkit.protocols.link.ieee802_11.IEEE802_11` - (:class:`~pcapkit.protocols.misc.null.NoPayload` when nothing follows). + (:class:`~pcapkit.protocols.misc.no_payload.NoPayload` when nothing follows). The header names no next protocol, since an 802.11 frame always follows it, so the frame is looked up in :attr:`Radiotap.__proto__ ` diff --git a/docs/source/pcapkit/protocols/misc/index.rst b/docs/source/pcapkit/protocols/misc/index.rst index 37a0d28219..492ac25473 100644 --- a/docs/source/pcapkit/protocols/misc/index.rst +++ b/docs/source/pcapkit/protocols/misc/index.rst @@ -9,7 +9,7 @@ Auxiliary Protocols These include the PCAP header classes, the PCAP-NG :class:`~pcapkit.protocols.misc.pcapng.PCAPNG` class, the :class:`~pcapkit.protocols.misc.raw.Raw` class for not-supported protocols, and -the :class:`~pcapkit.protocols.misc.null.NoPayload` class for indication of +the :class:`~pcapkit.protocols.misc.no_payload.NoPayload` class for indication of empty payload. .. toctree:: @@ -18,5 +18,5 @@ empty payload. pcap pcapng raw - null + no_payload checksum diff --git a/docs/source/pcapkit/protocols/misc/no_payload.rst b/docs/source/pcapkit/protocols/misc/no_payload.rst new file mode 100644 index 0000000000..604322eb96 --- /dev/null +++ b/docs/source/pcapkit/protocols/misc/no_payload.rst @@ -0,0 +1,53 @@ +No-Payload Packet +================= + +.. module:: pcapkit.protocols.misc.no_payload + +:mod:`pcapkit.protocols.misc.no_payload` contains +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` only, which +implements a :class:`~pcapkit.protocols.protocol.Protocol` like +object whose payload is recursively +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` itself. + +.. versionadded:: 1.6.0 + + Moved here from ``pcapkit.protocols.misc.null``, with its data model and + header schema, since a protocol class is named after its module + (:issue:`2529`). + +.. versionremoved:: 1.6.0 + + ``pcapkit.protocols.misc.null``, ``pcapkit.protocols.data.misc.null`` and + ``pcapkit.protocols.schema.misc.null``, with no alias (:issue:`2529`). + +.. autoclass:: pcapkit.protocols.misc.no_payload.NoPayload + :no-members: + :show-inheritance: + + .. autoproperty:: name + .. autoproperty:: length + .. autoproperty:: protocol + + .. automethod:: read + .. automethod:: make + + .. automethod:: __post_init__ + .. automethod:: __index__ + +Header Schemas +-------------- + +.. module:: pcapkit.protocols.schema.misc.no_payload + +.. autoclass:: pcapkit.protocols.schema.misc.no_payload.NoPayload + :members: + :show-inheritance: + +Data Models +----------- + +.. module:: pcapkit.protocols.data.misc.no_payload + +.. autoclass:: pcapkit.protocols.data.misc.no_payload.NoPayload + :members: + :show-inheritance: diff --git a/docs/source/pcapkit/protocols/misc/null.rst b/docs/source/pcapkit/protocols/misc/null.rst deleted file mode 100644 index 39da8bed4d..0000000000 --- a/docs/source/pcapkit/protocols/misc/null.rst +++ /dev/null @@ -1,42 +0,0 @@ -No-Payload Packet -================= - -.. module:: pcapkit.protocols.misc.null - -:mod:`pcapkit.protocols.misc.null` contains -:class:`~pcapkit.protocols.misc.null.NoPayload` only, which -implements a :class:`~pcapkit.protocols.protocol.Protocol` like -object whose payload is recursively -:class:`~pcapkit.protocols.misc.null.NoPayload` itself. - -.. autoclass:: pcapkit.protocols.misc.null.NoPayload - :no-members: - :show-inheritance: - - .. autoproperty:: name - .. autoproperty:: length - .. autoproperty:: protocol - - .. automethod:: read - .. automethod:: make - - .. automethod:: __post_init__ - .. automethod:: __index__ - -Header Schemas --------------- - -.. module:: pcapkit.protocols.schema.misc.null - -.. autoclass:: pcapkit.protocols.schema.misc.null.NoPayload - :members: - :show-inheritance: - -Data Models ------------ - -.. module:: pcapkit.protocols.data.misc.null - -.. autoclass:: pcapkit.protocols.data.misc.null.NoPayload - :members: - :show-inheritance: diff --git a/pcapkit/corekit/decorators.py b/pcapkit/corekit/decorators.py index 020dcf03bf..4fb55af3c3 100644 --- a/pcapkit/corekit/decorators.py +++ b/pcapkit/corekit/decorators.py @@ -108,7 +108,7 @@ def beholder( This decorator calls the decorated function. Should any exception be raised, it re-parses the current layer's payload as :class:`~pcapkit.protocols.misc.raw.Raw` -- or as - :class:`~pcapkit.protocols.misc.null.NoPayload`, if the error is an + :class:`~pcapkit.protocols.misc.no_payload.NoPayload`, if the error is an end-of-file :exc:`~pcapkit.utilities.exceptions.StructError` -- whose ``error`` is the exception's message. @@ -185,7 +185,7 @@ def behold(*args: 'P.args', **kwargs: 'P.kwargs') -> 'R_beholder': beholding.reset(token) except Exception as exc: if isinstance(exc, StructError) and exc.eof: # pylint: disable=no-member - from pcapkit.protocols.misc.null import NoPayload as protocol # isort: skip # pylint: disable=import-outside-toplevel + from pcapkit.protocols.misc.no_payload import NoPayload as protocol # isort: skip # pylint: disable=import-outside-toplevel else: from pcapkit.protocols.misc.raw import Raw as protocol # type: ignore[assignment] # isort: skip # pylint: disable=import-outside-toplevel # error = traceback.format_exc(limit=1).strip().rsplit(os.linesep, maxsplit=1)[-1] diff --git a/pcapkit/protocols/application/application.py b/pcapkit/protocols/application/application.py index d606f1e024..29a0e5aab5 100644 --- a/pcapkit/protocols/application/application.py +++ b/pcapkit/protocols/application/application.py @@ -23,7 +23,7 @@ from typing import TYPE_CHECKING, Generic, overload from pcapkit.corekit.protochain import ProtoChain -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.protocol import _PT, _ST, ProtocolBase from pcapkit.protocols.schema.schema import keep_short_read, replay_short_read from pcapkit.utilities.exceptions import IntError, UnsupportedCall @@ -49,7 +49,7 @@ class Application(ProtocolBase[_PT, _ST], Generic[_PT, _ST]): # pylint: disable :class:`~pcapkit.protocols.application.sslv2.SSLv2` and :class:`~pcapkit.protocols.application.dtls.DTLS` do for a further record and :class:`~pcapkit.protocols.application.httpv2.HTTPv2` for a further frame -- - or to :class:`~pcapkit.protocols.misc.null.NoPayload` when nothing remains. + or to :class:`~pcapkit.protocols.misc.no_payload.NoPayload` when nothing remains. """ @@ -124,7 +124,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, # ``_decode_next_layer``, which already set the payload and the chain # (basis included); only a protocol that did not gets the empty default if getattr(self, '_next', None) is None: - #: pcapkit.protocols.misc.null.NoPayload: Payload of current instance. + #: pcapkit.protocols.misc.no_payload.NoPayload: Payload of current instance. self._next = NoPayload() #: pcapkit.corekit.protochain.ProtoChain: Protocol chain of current instance. self._protos = ProtoChain(self.__class__, self.alias) @@ -179,7 +179,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # Returns: Instance of :class:`~pcapkit.protocols.misc.raw.Raw`, or of - :class:`~pcapkit.protocols.misc.null.NoPayload` when nothing remains. + :class:`~pcapkit.protocols.misc.no_payload.NoPayload` when nothing remains. Raises: UnsupportedCall: If ``proto`` is anything but ``-1``, i.e. a real diff --git a/pcapkit/protocols/application/http.py b/pcapkit/protocols/application/http.py index b8f6403263..08d13e6e03 100644 --- a/pcapkit/protocols/application/http.py +++ b/pcapkit/protocols/application/http.py @@ -35,7 +35,7 @@ from pcapkit.corekit.protochain import ProtoChain from pcapkit.protocols.application.application import Application from pcapkit.protocols.data.data import Data -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.protocol import _PT, _ST from pcapkit.utilities.exceptions import ProtocolError diff --git a/pcapkit/protocols/application/ssl.py b/pcapkit/protocols/application/ssl.py index 06eb989a64..6ea6bff747 100644 --- a/pcapkit/protocols/application/ssl.py +++ b/pcapkit/protocols/application/ssl.py @@ -61,7 +61,7 @@ SupportedVersionsClientHello as Data_SupportedVersionsClientHello from pcapkit.protocols.data.application.tls import \ SupportedVersionsServerHello as Data_SupportedVersionsServerHello -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.protocol import _PT, _ST from pcapkit.utilities.exceptions import CaughtByCaller, ProtocolError from pcapkit.utilities.warnings import RegistryWarning, warn diff --git a/pcapkit/protocols/data/misc/__init__.py b/pcapkit/protocols/data/misc/__init__.py index 89d3ca843e..7d20db2b7a 100644 --- a/pcapkit/protocols/data/misc/__init__.py +++ b/pcapkit/protocols/data/misc/__init__.py @@ -75,7 +75,7 @@ # misc protocols from pcapkit.protocols.data.misc.raw import Raw -from pcapkit.protocols.data.misc.null import NoPayload +from pcapkit.protocols.data.misc.no_payload import NoPayload from pcapkit.protocols.data.misc.checksum import IP_Pseudo __all__ = [ diff --git a/pcapkit/protocols/data/misc/null.py b/pcapkit/protocols/data/misc/no_payload.py similarity index 100% rename from pcapkit/protocols/data/misc/null.py rename to pcapkit/protocols/data/misc/no_payload.py diff --git a/pcapkit/protocols/internet/ah.py b/pcapkit/protocols/internet/ah.py index 7480755fcc..8f3cbcb3f7 100644 --- a/pcapkit/protocols/internet/ah.py +++ b/pcapkit/protocols/internet/ah.py @@ -30,7 +30,7 @@ from pcapkit.protocols.data.internet.ah import AH as Data_AH from pcapkit.protocols.internet.ipsec import IPsec from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.ah import AH as Schema_AH from pcapkit.protocols.schema.internet.ah import AH_HEADER_LEN from pcapkit.utilities.exceptions import UnsupportedCall diff --git a/pcapkit/protocols/internet/hip.py b/pcapkit/protocols/internet/hip.py index a7938c9f92..2e4f90f37e 100644 --- a/pcapkit/protocols/internet/hip.py +++ b/pcapkit/protocols/internet/hip.py @@ -128,7 +128,7 @@ from pcapkit.protocols.data.internet.hip import ViaRVSParameter as Data_ViaRVSParameter from pcapkit.protocols.internet.internet import Internet from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.hip import HIP as Schema_HIP from pcapkit.protocols.schema.internet.hip import AckDataParameter as Schema_AckDataParameter from pcapkit.protocols.schema.internet.hip import ACKParameter as Schema_ACKParameter diff --git a/pcapkit/protocols/internet/hopopt.py b/pcapkit/protocols/internet/hopopt.py index 572d3b936f..7193a33452 100644 --- a/pcapkit/protocols/internet/hopopt.py +++ b/pcapkit/protocols/internet/hopopt.py @@ -65,7 +65,7 @@ TunnelEncapsulationLimitOption as Data_TunnelEncapsulationLimitOption from pcapkit.protocols.data.internet.hopopt import UnassignedOption as Data_UnassignedOption from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.hopopt import HOPOPT as Schema_HOPOPT from pcapkit.protocols.schema.internet.hopopt import CALIPSOOption as Schema_CALIPSOOption from pcapkit.protocols.schema.internet.hopopt import HomeAddressOption as Schema_HomeAddressOption diff --git a/pcapkit/protocols/internet/icmpv4.py b/pcapkit/protocols/internet/icmpv4.py index 28c186e685..5a8dafe1e8 100644 --- a/pcapkit/protocols/internet/icmpv4.py +++ b/pcapkit/protocols/internet/icmpv4.py @@ -36,7 +36,7 @@ from pcapkit.protocols.data.internet.icmpv4 import TimeExceeded as Data_TimeExceeded from pcapkit.protocols.data.internet.icmpv4 import Unknown as Data_Unknown from pcapkit.protocols.internet.icmp import ICMP -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.icmpv4 import \ DestinationUnreachable as Schema_DestinationUnreachable from pcapkit.protocols.schema.internet.icmpv4 import Echo as Schema_Echo diff --git a/pcapkit/protocols/internet/icmpv6.py b/pcapkit/protocols/internet/icmpv6.py index 8c4c645987..7aff29c94b 100644 --- a/pcapkit/protocols/internet/icmpv6.py +++ b/pcapkit/protocols/internet/icmpv6.py @@ -37,7 +37,7 @@ from pcapkit.protocols.data.internet.icmpv6 import TimeExceeded as Data_TimeExceeded from pcapkit.protocols.data.internet.icmpv6 import Unknown as Data_Unknown from pcapkit.protocols.internet.icmp import ICMP -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.icmpv6 import \ DestinationUnreachable as Schema_DestinationUnreachable from pcapkit.protocols.schema.internet.icmpv6 import Echo as Schema_Echo diff --git a/pcapkit/protocols/internet/internet.py b/pcapkit/protocols/internet/internet.py index 8fdb264e6a..bff2517bff 100644 --- a/pcapkit/protocols/internet/internet.py +++ b/pcapkit/protocols/internet/internet.py @@ -395,7 +395,7 @@ def _next_layer_class(self, proto: 'Optional[int]', file_: 'bytes', length: 'int extension: if is extension header, see :meth:`_next_exthdr_depth` Returns: - :class:`~pcapkit.protocols.misc.null.NoPayload` if there is + :class:`~pcapkit.protocols.misc.no_payload.NoPayload` if there is nothing to parse; :class:`~pcapkit.protocols.misc.raw.Raw` if the parse stops at this layer, or the next layer is an IPv6 extension header past :data:`~pcapkit.utilities.config.EXTENSION_HEADER_LIMIT` in a row; otherwise the @@ -411,7 +411,7 @@ class registered for ``proto``. Paired with it, the keywords that """ if min(length, len(file_)) == 0: - from pcapkit.protocols.misc.null import NoPayload # isort: skip # pylint: disable=import-outside-toplevel + from pcapkit.protocols.misc.no_payload import NoPayload # isort: skip # pylint: disable=import-outside-toplevel return NoPayload, {} if self._sigterm: from pcapkit.protocols.misc.raw import Raw # isort: skip # pylint: disable=import-outside-toplevel diff --git a/pcapkit/protocols/internet/ipv6_ext.py b/pcapkit/protocols/internet/ipv6_ext.py index 6225d24ca8..08affb757d 100644 --- a/pcapkit/protocols/internet/ipv6_ext.py +++ b/pcapkit/protocols/internet/ipv6_ext.py @@ -141,7 +141,7 @@ from pcapkit.const.reg.transtype import TransType as Enum_TransType from pcapkit.protocols.data.internet.ipv6_ext import IPv6_Ext as Data_IPv6_Ext from pcapkit.protocols.internet.internet import Internet -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.protocol import _PT, _ST, ProtocolBase from pcapkit.protocols.schema.internet.ipv6_ext import IPv6_Ext as Schema_IPv6_Ext from pcapkit.protocols.schema.schema import Schema diff --git a/pcapkit/protocols/internet/ipv6_frag.py b/pcapkit/protocols/internet/ipv6_frag.py index 173f50d198..9fbbe91147 100644 --- a/pcapkit/protocols/internet/ipv6_frag.py +++ b/pcapkit/protocols/internet/ipv6_frag.py @@ -29,7 +29,7 @@ from pcapkit.const.reg.transtype import TransType as Enum_TransType from pcapkit.protocols.data.internet.ipv6_frag import IPv6_Frag as Data_IPv6_Frag from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.ipv6_frag import IPv6_Frag as Schema_IPv6_Frag from pcapkit.utilities.exceptions import UnsupportedCall diff --git a/pcapkit/protocols/internet/ipv6_opts.py b/pcapkit/protocols/internet/ipv6_opts.py index 27b48d263a..11ed512f61 100644 --- a/pcapkit/protocols/internet/ipv6_opts.py +++ b/pcapkit/protocols/internet/ipv6_opts.py @@ -65,7 +65,7 @@ TunnelEncapsulationLimitOption as Data_TunnelEncapsulationLimitOption from pcapkit.protocols.data.internet.ipv6_opts import UnassignedOption as Data_UnassignedOption from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.ipv6_opts import CALIPSOOption as Schema_CALIPSOOption from pcapkit.protocols.schema.internet.ipv6_opts import \ HomeAddressOption as Schema_HomeAddressOption diff --git a/pcapkit/protocols/internet/ipv6_route.py b/pcapkit/protocols/internet/ipv6_route.py index 311fe527ed..772f73ed89 100644 --- a/pcapkit/protocols/internet/ipv6_route.py +++ b/pcapkit/protocols/internet/ipv6_route.py @@ -36,7 +36,7 @@ from pcapkit.protocols.data.internet.ipv6_route import Type2 as Data_Type2 from pcapkit.protocols.data.internet.ipv6_route import UnknownType as Data_UnknownType from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.ipv6_route import RPL as Schema_RPL from pcapkit.protocols.schema.internet.ipv6_route import IPv6_Route as Schema_IPv6_Route from pcapkit.protocols.schema.internet.ipv6_route import RoutingType as Schema_RoutingType diff --git a/pcapkit/protocols/internet/mh.py b/pcapkit/protocols/internet/mh.py index 2f8d812817..9efe9703f9 100644 --- a/pcapkit/protocols/internet/mh.py +++ b/pcapkit/protocols/internet/mh.py @@ -285,7 +285,7 @@ UpdateNotificationMessage as Data_UpdateNotificationMessage from pcapkit.protocols.data.internet.mh import VendorSpecificOption as Data_VendorSpecificOption from pcapkit.protocols.internet.ipv6_ext import IPv6_Ext -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.schema.internet.mh import MH as Schema_MH from pcapkit.protocols.schema.internet.mh import \ AccessNetworkIdentifierOption as Schema_AccessNetworkIdentifierOption diff --git a/pcapkit/protocols/link/frad.py b/pcapkit/protocols/link/frad.py index 9539ea504c..d9a0368870 100644 --- a/pcapkit/protocols/link/frad.py +++ b/pcapkit/protocols/link/frad.py @@ -411,7 +411,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # if TYPE_CHECKING: protocol: 'Type[ProtocolBase]' if not min(length, len(file_)): - from pcapkit.protocols.misc.null import \ + from pcapkit.protocols.misc.no_payload import \ NoPayload as protocol # isort: skip # pylint: disable=import-outside-toplevel elif self._sigterm: from pcapkit.protocols.misc.raw import \ diff --git a/pcapkit/protocols/link/linux_sll.py b/pcapkit/protocols/link/linux_sll.py index ee7d8b5c0a..900d03bb5e 100644 --- a/pcapkit/protocols/link/linux_sll.py +++ b/pcapkit/protocols/link/linux_sll.py @@ -260,7 +260,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, # if TYPE_CHECKING: protocol: 'Type[ProtocolBase]' if not min(length, len(file_)): - from pcapkit.protocols.misc.null import \ + from pcapkit.protocols.misc.no_payload import \ NoPayload as protocol # isort: skip # pylint: disable=import-outside-toplevel elif self._sigterm: from pcapkit.protocols.misc.raw import \ diff --git a/pcapkit/protocols/link/radiotap.py b/pcapkit/protocols/link/radiotap.py index 4c500afe2a..0236ae632c 100644 --- a/pcapkit/protocols/link/radiotap.py +++ b/pcapkit/protocols/link/radiotap.py @@ -48,7 +48,7 @@ :attr:`~pcapkit.protocols.data.link.radiotap.Radiotap.fields`. * **Hands** everything from ``it_len`` on, the 802.11 MAC frame, to :class:`~pcapkit.protocols.link.ieee802_11.IEEE802_11` - (:class:`~pcapkit.protocols.misc.null.NoPayload` when nothing follows). + (:class:`~pcapkit.protocols.misc.no_payload.NoPayload` when nothing follows). The header names no next protocol, since an 802.11 frame always follows it, so the frame is looked up in :attr:`Radiotap.__proto__ ` diff --git a/pcapkit/protocols/misc/__init__.py b/pcapkit/protocols/misc/__init__.py index 162cd894bf..36f52a96af 100644 --- a/pcapkit/protocols/misc/__init__.py +++ b/pcapkit/protocols/misc/__init__.py @@ -7,7 +7,7 @@ :mod:`pcapkit.protocols.misc` contains the auxiliary protocol implementations. These include the :class:`~pcapkit.protocols.misc.raw.Raw` class for not-supported -protocols, the :class:`~pcapkit.protocols.misc.null.NoPayload` class for +protocols, the :class:`~pcapkit.protocols.misc.no_payload.NoPayload` class for indication of empty payload, the PCAP and PCAP-NG file format classes, and the checksum pseudo-headers in :mod:`pcapkit.protocols.misc.checksum`. @@ -21,7 +21,7 @@ # Miscellaneous Classes for Protocols from pcapkit.protocols.misc.raw import Raw -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload # Checksum Pseudo-Headers from pcapkit.protocols.misc.checksum import IP_Pseudo diff --git a/pcapkit/protocols/misc/checksum/ip_pseudo.py b/pcapkit/protocols/misc/checksum/ip_pseudo.py index 818ad20dfb..e21a495152 100644 --- a/pcapkit/protocols/misc/checksum/ip_pseudo.py +++ b/pcapkit/protocols/misc/checksum/ip_pseudo.py @@ -66,7 +66,7 @@ from pcapkit.protocols.data.misc.checksum.ip_pseudo import IP_Pseudo as Data_IP_Pseudo from pcapkit.protocols.internet.ipv4 import IPv4 from pcapkit.protocols.internet.ipv6 import IPV6_HEADER_LEN, IPv6 -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.protocol import ProtocolBase from pcapkit.protocols.schema.internet.ipv6 import IP_MAX_LENGTH, jumbo_payload_length from pcapkit.protocols.schema.misc.checksum.ip_pseudo import IPV4_PSEUDO_LEN, IPV6_PSEUDO_LEN @@ -338,7 +338,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, f'expected {IPV4_PSEUDO_LEN} or {IPV6_PSEUDO_LEN}') super().__post_init__(file, length, **kwargs) # type: ignore[arg-type] - #: pcapkit.protocols.misc.null.NoPayload: Next layer (no payload). + #: pcapkit.protocols.misc.no_payload.NoPayload: Next layer (no payload). self._next = NoPayload() #: pcapkit.corekit.protochain.ProtoChain: Protocol chain from current layer. self._protos = ProtoChain(self.__class__, self.alias) diff --git a/pcapkit/protocols/misc/null.py b/pcapkit/protocols/misc/no_payload.py similarity index 83% rename from pcapkit/protocols/misc/null.py rename to pcapkit/protocols/misc/no_payload.py index 63246f00d6..b770d1bffc 100644 --- a/pcapkit/protocols/misc/null.py +++ b/pcapkit/protocols/misc/no_payload.py @@ -2,21 +2,32 @@ """No-Payload Packet ======================= -.. module:: pcapkit.protocols.misc.null +.. module:: pcapkit.protocols.misc.no_payload -:mod:`pcapkit.protocols.misc.null` contains -:class:`~pcapkit.protocols.misc.null.NoPayload` only, which +:mod:`pcapkit.protocols.misc.no_payload` contains +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` only, which implements a :class:`~pcapkit.protocols.protocol.Protocol` like object whose payload is -:class:`~pcapkit.protocols.misc.null.NoPayload` itself. +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` itself. + +.. versionadded:: 1.6.0 + + Moved here from ``pcapkit.protocols.misc.null``, with its data model and + header schema, since a protocol class is named after its module + (:issue:`2529`). + +.. versionremoved:: 1.6.0 + + ``pcapkit.protocols.misc.null``, ``pcapkit.protocols.data.misc.null`` and + ``pcapkit.protocols.schema.misc.null``, with no alias (:issue:`2529`). """ import io from typing import TYPE_CHECKING, overload -from pcapkit.protocols.data.misc.null import NoPayload as Data_NoPayload +from pcapkit.protocols.data.misc.no_payload import NoPayload as Data_NoPayload from pcapkit.protocols.protocol import ProtocolBase -from pcapkit.protocols.schema.misc.null import NoPayload as Schema_NoPayload +from pcapkit.protocols.schema.misc.no_payload import NoPayload as Schema_NoPayload from pcapkit.utilities.exceptions import UnsupportedCall if TYPE_CHECKING: @@ -133,10 +144,10 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, # pylint: d self._data = b'' #: io.BytesIO: Source data stream. self._file = io.BytesIO() - #: pcapkit.protocols.data.misc.null.NoPayload: Data model of current instance. + #: pcapkit.protocols.data.misc.no_payload.NoPayload: Data model of current instance. self._info = Data_NoPayload() - #: pcapkit.protocols.misc.null.NoPayload: Payload of current instance. + #: pcapkit.protocols.misc.no_payload.NoPayload: Payload of current instance. self._next = self #: None: Protocol chain of current instance, which an empty payload #: does not have. diff --git a/pcapkit/protocols/misc/raw.py b/pcapkit/protocols/misc/raw.py index 3151628686..c4221e2fd7 100644 --- a/pcapkit/protocols/misc/raw.py +++ b/pcapkit/protocols/misc/raw.py @@ -15,7 +15,7 @@ from pcapkit.corekit.protochain import ProtoChain from pcapkit.protocols.data.misc.raw import Raw as Data_Raw -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.protocol import ProtocolBase from pcapkit.protocols.schema.misc.raw import Raw as Schema_Raw from pcapkit.utilities.exceptions import UnsupportedCall @@ -155,7 +155,7 @@ def __post_init__(self, file: 'Optional[IO[bytes] | bytes]' = None, else: alias = self.alias - #: pcapkit.protocols.misc.null.NoPayload: Next layer (no payload). + #: pcapkit.protocols.misc.no_payload.NoPayload: Next layer (no payload). self._next = NoPayload() #: pcapkit.corekit.protochain.ProtoChain: Protocol chain from current layer. self._protos = ProtoChain(self.__class__, alias) diff --git a/pcapkit/protocols/protocol.py b/pcapkit/protocols/protocol.py index 7771185542..7c13b218ec 100644 --- a/pcapkit/protocols/protocol.py +++ b/pcapkit/protocols/protocol.py @@ -226,7 +226,7 @@ def _raw_where_parsed(made: 'Any', parsed: 'Any') -> 'bool': #: ` reconstructs from. #: Refusing it would make ``from_data`` fail on any protocol whose ``make`` does #: not declare a ``packet``, starting with -#: :class:`~pcapkit.protocols.misc.null.NoPayload`, the innermost layer of every +#: :class:`~pcapkit.protocols.misc.no_payload.NoPayload`, the innermost layer of every #: packet. It is also a real field name for some protocols -- #: :meth:`HIP.make ` takes the HIP #: packet *type* under it -- and listing it here does not change how it binds, @@ -655,7 +655,7 @@ def protochain(self) -> 'ProtoChain': """Protocol chain of current instance. Note: - :class:`~pcapkit.protocols.misc.null.NoPayload` has no chain and + :class:`~pcapkit.protocols.misc.no_payload.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. @@ -984,7 +984,7 @@ def analyze(cls, proto: 'int', payload: 'bytes', **kwargs: 'Any') -> 'ProtocolBa report = protocol(payload_io, len(payload), **kwargs) # type: ignore[abstract] except Exception as exc: if isinstance(exc, StructError) and exc.eof: # pylint: disable=no-member - from pcapkit.protocols.misc.null import NoPayload as protocol # pylint: disable=import-outside-toplevel # isort: skip + from pcapkit.protocols.misc.no_payload import NoPayload as protocol # pylint: disable=import-outside-toplevel # isort: skip else: from pcapkit.protocols.misc.raw import Raw as protocol # pylint: disable=import-outside-toplevel # isort: skip # error = traceback.format_exc(limit=1).strip().rsplit(os.linesep, maxsplit=1)[-1] @@ -1568,7 +1568,8 @@ def __getitem__(self, key: 'str | Protocol | Type[Protocol]') -> 'ProtocolBase': return self # then check recursively - from pcapkit.protocols.misc.null import NoPayload # pylint: disable=import-outside-toplevel + from pcapkit.protocols.misc.no_payload import \ + NoPayload # pylint: disable=import-outside-toplevel payload = self._next while not isinstance(payload, NoPayload): @@ -1600,7 +1601,8 @@ def __contains__(self, name: 'str | Protocol | Type[Protocol]') -> 'bool': return True # then check recursively - from pcapkit.protocols.misc.null import NoPayload # pylint: disable=import-outside-toplevel + from pcapkit.protocols.misc.no_payload import \ + NoPayload # pylint: disable=import-outside-toplevel payload = self._next while not isinstance(payload, NoPayload): @@ -2324,7 +2326,7 @@ def _make_payload(cls, data: 'Data') -> 'ProtocolBase': This method uses ``__next_type__`` and ``__next_name__`` to determine the payload type and name. If either of them is missing or :data:`None`, or ``data`` holds nothing under ``__next_name__``, a - :class:`~pcapkit.protocols.misc.null.NoPayload` instance will be + :class:`~pcapkit.protocols.misc.no_payload.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 `. @@ -2354,7 +2356,7 @@ def _make_payload(cls, data: 'Data') -> 'ProtocolBase': name = cast('Optional[str]', data.get('__next_name__')) if (proto is None or not (isinstance(proto, type) and issubclass(proto, ProtocolBase)) or name is None or name not in data): - from pcapkit.protocols.misc.null import \ + from pcapkit.protocols.misc.no_payload import \ NoPayload # pylint: disable=import-outside-toplevel return NoPayload() @@ -2510,7 +2512,7 @@ def _import_next_layer(self, proto: 'int', length: 'Optional[int]' = None, *, length = len(file_) if min(length, len(file_)) == 0: - from pcapkit.protocols.misc.null import NoPayload as protocol # isort: skip # pylint: disable=import-outside-toplevel + from pcapkit.protocols.misc.no_payload import NoPayload as protocol # isort: skip # pylint: disable=import-outside-toplevel elif self._sigterm: from pcapkit.protocols.misc.raw import Raw as protocol # isort: skip # pylint: disable=import-outside-toplevel else: @@ -2587,7 +2589,7 @@ def _parse_next_layer(klass: 'Type[ProtocolBase]', file_: 'bytes', length: 'int' depth = frame_depth.get() + 1 limit = config.FRAME_LAYER_LIMIT if limit != -1 and depth > limit: - from pcapkit.protocols.misc.null import NoPayload # isort: skip # pylint: disable=import-outside-toplevel + from pcapkit.protocols.misc.no_payload import NoPayload # isort: skip # pylint: disable=import-outside-toplevel from pcapkit.protocols.misc.raw import Raw # isort: skip # pylint: disable=import-outside-toplevel # NOTE: Nothing is lost if the next layer is raw already, or empty. diff --git a/pcapkit/protocols/schema/misc/__init__.py b/pcapkit/protocols/schema/misc/__init__.py index fb24c2edee..9965aedb6c 100644 --- a/pcapkit/protocols/schema/misc/__init__.py +++ b/pcapkit/protocols/schema/misc/__init__.py @@ -76,7 +76,7 @@ # misc protocols from pcapkit.protocols.schema.misc.raw import Raw -from pcapkit.protocols.schema.misc.null import NoPayload +from pcapkit.protocols.schema.misc.no_payload import NoPayload from pcapkit.protocols.schema.misc.checksum import IP_Pseudo __all__ = [ diff --git a/pcapkit/protocols/schema/misc/null.py b/pcapkit/protocols/schema/misc/no_payload.py similarity index 100% rename from pcapkit/protocols/schema/misc/null.py rename to pcapkit/protocols/schema/misc/no_payload.py diff --git a/pcapkit/protocols/schema/schema.py b/pcapkit/protocols/schema/schema.py index 115f8cc507..c87a44cf88 100644 --- a/pcapkit/protocols/schema/schema.py +++ b/pcapkit/protocols/schema/schema.py @@ -132,7 +132,7 @@ class marked with a user's own ``from typing import final`` on 3.10 is # place of the omitted values, so that it could not be packed at all and # failed with an error naming a field class rather than a field. # - # :class:`~pcapkit.protocols.schema.misc.null.NoPayload` is what the test + # :class:`~pcapkit.protocols.schema.misc.no_payload.NoPayload` is what the test # protects: it declares an argument-less ``__init__`` of its own so that no # generated one displaces it. if '__init__' not in cls.__dict__: diff --git a/pcapkit/protocols/transport/sctp.py b/pcapkit/protocols/transport/sctp.py index 31f9e16b15..5b12f9b414 100644 --- a/pcapkit/protocols/transport/sctp.py +++ b/pcapkit/protocols/transport/sctp.py @@ -968,7 +968,7 @@ def _get_payload(self) -> 'bytes': whose payload protocol identifier selects the next layer. Should the packet carry no DATA chunk, an empty :obj:`bytes` is returned and the next layer resolves to - :class:`~pcapkit.protocols.misc.null.NoPayload`. + :class:`~pcapkit.protocols.misc.no_payload.NoPayload`. Returns: Payload of the packet as :obj:`bytes`. diff --git a/pcapkit/protocols/transport/transport.py b/pcapkit/protocols/transport/transport.py index 1363b46817..785ddac543 100644 --- a/pcapkit/protocols/transport/transport.py +++ b/pcapkit/protocols/transport/transport.py @@ -208,7 +208,7 @@ def analyze(cls, ports: 'tuple[Enum_AppType, Enum_AppType]', payload: 'bytes', * report = protocol(payload_io, len(payload), **kwargs) # type: ignore[abstract] except Exception as exc: if isinstance(exc, StructError) and exc.eof: # pylint: disable=no-member - from pcapkit.protocols.misc.null import NoPayload as protocol # pylint: disable=import-outside-toplevel # isort:skip + from pcapkit.protocols.misc.no_payload import NoPayload as protocol # pylint: disable=import-outside-toplevel # isort:skip else: from pcapkit.protocols.misc.raw import Raw as protocol # pylint: disable=import-outside-toplevel # isort:skip # error = traceback.format_exc(limit=1).strip().rsplit(os.linesep, maxsplit=1)[-1] diff --git a/pcapkit/toolkit/pcap.py b/pcapkit/toolkit/pcap.py index 255f7ad223..aa746625ad 100644 --- a/pcapkit/toolkit/pcap.py +++ b/pcapkit/toolkit/pcap.py @@ -28,7 +28,7 @@ from pcapkit.protocols.internet.ip import IP as Protocol_IP from pcapkit.protocols.internet.ipv4 import IPv4 from pcapkit.protocols.internet.ipv6 import IPv6 -from pcapkit.protocols.misc.null import NoPayload +from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw from pcapkit.protocols.protocol import ProtocolBase from pcapkit.protocols.schema.transport.tcp import TCP_DATA_OFFSET_OCTET, TCP_MIN_HEADER_LEN diff --git a/tests/_support.py b/tests/_support.py index 9b3708feed..48fc794db1 100644 --- a/tests/_support.py +++ b/tests/_support.py @@ -555,7 +555,7 @@ def install_fake_payload_protocols(test: 'unittest.TestCase', raw_cls: type, them poisons every later test that imports :mod:`pcapkit`. raw_cls: Stand-in to bind as ``pcapkit.protocols.misc.raw.Raw``. null_cls: Stand-in to bind as - ``pcapkit.protocols.misc.null.NoPayload``. + ``pcapkit.protocols.misc.no_payload.NoPayload``. Raises: RuntimeError: If ``test`` is not under :func:`isolate_modules`. @@ -569,9 +569,9 @@ def install_fake_payload_protocols(test: 'unittest.TestCase', raw_cls: type, raw_module.Raw = raw_cls sys.modules['pcapkit.protocols.misc.raw'] = raw_module - null_module = types.ModuleType('pcapkit.protocols.misc.null') + null_module = types.ModuleType('pcapkit.protocols.misc.no_payload') null_module.NoPayload = null_cls - sys.modules['pcapkit.protocols.misc.null'] = null_module + sys.modules['pcapkit.protocols.misc.no_payload'] = null_module def _reset_abc_caches() -> None: diff --git a/tests/foundation/registry/test_protocols.py b/tests/foundation/registry/test_protocols.py index da7a030967..f8b0ce7bed 100644 --- a/tests/foundation/registry/test_protocols.py +++ b/tests/foundation/registry/test_protocols.py @@ -306,7 +306,7 @@ def test_sibling_registries_name_what_they_displaced(self) -> None: from pcapkit.const.sctp.payload_protocol_identifier import PayloadProtocolIdentifier from pcapkit.protocols.link.link import Link from pcapkit.protocols.internet.internet import Internet - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.pcap.frame import Frame from pcapkit.protocols.misc.pcapng import PCAPNG from pcapkit.protocols.misc.raw import Raw diff --git a/tests/integration/test_frame_iteration.py b/tests/integration/test_frame_iteration.py index 6e4ca97858..32fd7a3f2d 100644 --- a/tests/integration/test_frame_iteration.py +++ b/tests/integration/test_frame_iteration.py @@ -96,7 +96,7 @@ def stack(frame: 'Any') -> 'list[Any]': apart, which is what :class:`ExtractionLimitTests` has to assert on. """ - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload walked = [] # type: list[Any] current = frame.payload diff --git a/tests/project/test_no_moved_name_re_exports_1744_unit.py b/tests/project/test_no_moved_name_re_exports_1744_unit.py index e60ea509b5..698d7188a1 100644 --- a/tests/project/test_no_moved_name_re_exports_1744_unit.py +++ b/tests/project/test_no_moved_name_re_exports_1744_unit.py @@ -25,6 +25,9 @@ ``versionremoved`` for the version that removed them, in the module docstring and on the docs page, per #1103; the beta-only ones are deleted with no directive. +* :class:`TestMovedModules` -- a shipped module that moved whole does not import + at its old path, and the module that took its place records ``versionremoved`` + for that path, in the docstring and on the docs page. This module is unit-tier and reads no capture. @@ -123,6 +126,18 @@ 'pcapkit/protocols/application/httpv2.rst', '1.6.0'), ) +#: Shipped modules that moved whole, as ``(old module, the module recording its +#: removal, docs page, the version that removed it)``. +MOVED_MODULES = ( + # #2529: shipped in 1.5.x, renamed after the class they hold. + ('pcapkit.protocols.misc.null', 'pcapkit.protocols.misc.no_payload', + 'pcapkit/protocols/misc/no_payload.rst', '1.6.0'), + ('pcapkit.protocols.schema.misc.null', 'pcapkit.protocols.misc.no_payload', + 'pcapkit/protocols/misc/no_payload.rst', '1.6.0'), + ('pcapkit.protocols.data.misc.null', 'pcapkit.protocols.misc.no_payload', + 'pcapkit/protocols/misc/no_payload.rst', '1.6.0'), +) + def _sources() -> 'list[pathlib.Path]': """Every Python file a reader could live in.""" @@ -323,5 +338,26 @@ def test_docstring_and_docs_page_carry_the_directive(self) -> 'None': self.assertTrue((ROOT / source).is_file()) +class TestMovedModules(unittest.TestCase): + """A shipped module that moved whole is gone, and recorded as removed, twice.""" + + def test_the_old_module_does_not_import(self) -> 'None': + for old, _, _, _ in MOVED_MODULES: + with self.subTest(module=old): + with self.assertRaises(ModuleNotFoundError): + importlib.import_module(old) + + def test_docstring_and_docs_page_carry_the_directive(self) -> 'None': + for old, recorder, page, version in MOVED_MODULES: + module = importlib.import_module(recorder) + for label, text in (('docstring', module.__doc__ or ''), + ('docs page', (_docs_dir() / page).read_text(encoding='utf-8'))): + with self.subTest(module=old, where=label): + blocks = re.findall(rf'(?ms)^\.\. versionremoved:: {re.escape(version)}\n\n(.*?)(?=^\S|\Z)', + text) + self.assertTrue(any(f'``{old}``' in block for block in blocks), + f'no versionremoved:: {version} block names ``{old}`` in {label}') + + if __name__ == '__main__': unittest.main() diff --git a/tests/protocols/application/test_application_dispatch_unit.py b/tests/protocols/application/test_application_dispatch_unit.py index a293bdc334..998c6e8cf3 100644 --- a/tests/protocols/application/test_application_dispatch_unit.py +++ b/tests/protocols/application/test_application_dispatch_unit.py @@ -78,14 +78,14 @@ def test_sentinel_dispatches_remainder_to_raw(self) -> None: self.assertIn('Raw', str(proto.protochain)) def test_sentinel_with_nothing_left_is_no_payload(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload proto = self._protocol_class(-1)(packet=b'ab') self.assertIsInstance(proto.payload, NoPayload) def test_undispatched_application_still_has_no_payload(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload proto = self._protocol_class(None)(packet=b'abtrailer') diff --git a/tests/protocols/application/test_dtls13_unified_header_unit.py b/tests/protocols/application/test_dtls13_unified_header_unit.py index 9f0282fc19..a8b58f3dba 100644 --- a/tests/protocols/application/test_dtls13_unified_header_unit.py +++ b/tests/protocols/application/test_dtls13_unified_header_unit.py @@ -215,7 +215,7 @@ def test_a_record_after_one_with_a_length_is_a_further_layer(self) -> None: def test_a_record_without_a_length_is_the_last(self) -> None: """It runs to the end of the datagram, so octets that would open a record are its ciphertext.""" from pcapkit.protocols.application.dtls import DTLS - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload last = _unified(_NO_LENGTH_EPOCH3, b'\x07', None, _FRAGMENT + self.CCS) wire = self.CCS + last diff --git a/tests/protocols/application/test_http2_roundtrip_unit.py b/tests/protocols/application/test_http2_roundtrip_unit.py index fa99558353..4376d3ff70 100644 --- a/tests/protocols/application/test_http2_roundtrip_unit.py +++ b/tests/protocols/application/test_http2_roundtrip_unit.py @@ -230,7 +230,7 @@ def setUp(self) -> None: def test_every_frame_is_an_http2_layer(self) -> None: """Each layer holds the frame header the specification frames (RFC 9113, section 4.1).""" from pcapkit.protocols.application.httpv2 import HTTPv2 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload for name, wire in SEGMENTS.items(): with self.subTest(segment=name): diff --git a/tests/protocols/application/test_httpv2_segment_frames_2536_unit.py b/tests/protocols/application/test_httpv2_segment_frames_2536_unit.py index c4929e8447..497bfaed4e 100644 --- a/tests/protocols/application/test_httpv2_segment_frames_2536_unit.py +++ b/tests/protocols/application/test_httpv2_segment_frames_2536_unit.py @@ -66,7 +66,7 @@ def setUp(self) -> None: reimport_once_per_class(self) def test_two_and_three_frames_are_each_a_layer(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.transport.tcp import TCP for name, segment, chain in ( diff --git a/tests/protocols/application/test_layer_placement_unit.py b/tests/protocols/application/test_layer_placement_unit.py index 91408db5b7..78ec3bb7fc 100644 --- a/tests/protocols/application/test_layer_placement_unit.py +++ b/tests/protocols/application/test_layer_placement_unit.py @@ -150,7 +150,7 @@ def test_ftp_data_subclasses_both_application_and_raw_in_that_order(self) -> Non def test_ftp_data_still_parses_and_rebuilds_as_raw(self) -> None: """The ``Application`` base leaves ``Raw``'s parsing and rebuild untouched.""" from pcapkit.protocols.application.ftp_data import FTP_DATA - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.utilities.exceptions import IntError packet = FTP_DATA(b'binary-file-contents') @@ -300,7 +300,7 @@ def test_ospf_still_attaches_its_undissected_body(self) -> None: def test_rarp_still_attaches_a_padded_frames_trailer(self) -> None: """Ethernet pads a short RARP frame; ``ARP.read`` dispatches the padding.""" from pcapkit.protocols.application.rarp import RARP - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw unpadded = RARP(rarp_request()) diff --git a/tests/protocols/application/test_sslv2_unit.py b/tests/protocols/application/test_sslv2_unit.py index 6e1e6d6794..7e62ac992f 100644 --- a/tests/protocols/application/test_sslv2_unit.py +++ b/tests/protocols/application/test_sslv2_unit.py @@ -765,7 +765,7 @@ def setUp(self) -> None: def test_every_record_is_an_sslv2_layer(self) -> None: """Each record's header form and RECORD-LENGTH, per the draft's ยง4.1.""" from pcapkit.protocols.application.sslv2 import SSLv2 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload for name, wire in SEGMENTS.items(): with self.subTest(segment=name): diff --git a/tests/protocols/application/test_tls_dtls_roundtrip_unit.py b/tests/protocols/application/test_tls_dtls_roundtrip_unit.py index 7f6c876051..92678f4c50 100644 --- a/tests/protocols/application/test_tls_dtls_roundtrip_unit.py +++ b/tests/protocols/application/test_tls_dtls_roundtrip_unit.py @@ -331,7 +331,7 @@ def setUp(self) -> None: def test_every_record_is_a_tls_layer(self) -> None: from pcapkit.protocols.application.tls import TLS - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload for name, wire in TLS_SEGMENTS.items(): with self.subTest(segment=name): @@ -526,7 +526,7 @@ def setUp(self) -> None: def test_every_record_is_a_dtls_layer(self) -> None: from pcapkit.protocols.application.dtls import DTLS from pcapkit.protocols.data.application.dtls import DTLSCiphertext - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload for name, wire in DTLS_DATAGRAMS.items(): with self.subTest(datagram=name): diff --git a/tests/protocols/internet/test_icmp_selector_runtime.py b/tests/protocols/internet/test_icmp_selector_runtime.py index 07b8d3c198..600a1dbbeb 100644 --- a/tests/protocols/internet/test_icmp_selector_runtime.py +++ b/tests/protocols/internet/test_icmp_selector_runtime.py @@ -59,7 +59,7 @@ def _selectors(self) -> 'Iterator[tuple[str, Any, set[str]]]': yield f'{name} class', getattr(pcapkit, name), MATCHES[name] def test_frame_selectors(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.utilities.exceptions import ProtocolNotFound for version in SAMPLES: diff --git a/tests/protocols/internet/test_igmp_unit.py b/tests/protocols/internet/test_igmp_unit.py index 8443a2df80..4d8de2d625 100644 --- a/tests/protocols/internet/test_igmp_unit.py +++ b/tests/protocols/internet/test_igmp_unit.py @@ -230,7 +230,7 @@ def test_trailing_octets_are_kept_as_raw_and_rebuilt(self) -> None: def test_no_trailing_octets_have_no_payload(self) -> None: from pcapkit.protocols.internet.igmpv1 import IGMPv1 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload parsed = IGMPv1(io.BytesIO(IGMP_PACKETS['v1-query'][0]), 8) self.assertIsInstance(parsed.payload, NoPayload) diff --git a/tests/protocols/internet/test_ipv4_header_truncated_payload_runtime.py b/tests/protocols/internet/test_ipv4_header_truncated_payload_runtime.py index c781e12bf2..538df93d1d 100644 --- a/tests/protocols/internet/test_ipv4_header_truncated_payload_runtime.py +++ b/tests/protocols/internet/test_ipv4_header_truncated_payload_runtime.py @@ -6,7 +6,7 @@ none of its octets, so its UDP layer was parsed from an empty stream into an all-zero header, and :meth:`~pcapkit.protocols.protocol.ProtocolBase.from_data` rebuilt those 8 octets as if they had been on the wire. Such a payload is a -:class:`~pcapkit.protocols.misc.null.NoPayload`. ``test.pcapng`` frame 3, cut +:class:`~pcapkit.protocols.misc.no_payload.NoPayload`. ``test.pcapng`` frame 3, cut inside the IPv4 header itself (18 of 20 octets), is kept as raw octets (#1170). @@ -54,7 +54,7 @@ def test_capture_cut_inside_the_header(self) -> None: def test_header_without_payload_octets(self) -> None: from pcapkit.protocols.internet.ipv4 import IPv4 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload parsed = IPv4(HEADER, len(HEADER)) self.assertIsInstance(parsed.payload, NoPayload) diff --git a/tests/protocols/internet/test_ipv4_tso_total_length_1547_runtime.py b/tests/protocols/internet/test_ipv4_tso_total_length_1547_runtime.py index 43045b7238..6774311fcc 100644 --- a/tests/protocols/internet/test_ipv4_tso_total_length_1547_runtime.py +++ b/tests/protocols/internet/test_ipv4_tso_total_length_1547_runtime.py @@ -184,7 +184,7 @@ def test_a_bogus_total_length_is_not_dissected_further(self) -> None: # as the trailer, and the Total Length is written back as it was. from pcapkit.protocols.internet.ipv4 import IPv4 from pcapkit.protocols.link.ethernet import Ethernet - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload frame = _records()[1][0][3] lengths: 'list[int]' = [] diff --git a/tests/protocols/internet/test_ipv4_unit.py b/tests/protocols/internet/test_ipv4_unit.py index bec91ebd66..f4e301e6ae 100644 --- a/tests/protocols/internet/test_ipv4_unit.py +++ b/tests/protocols/internet/test_ipv4_unit.py @@ -126,7 +126,7 @@ def test_ipv4_from_data_rebuilds_a_parsed_datagram(self) -> None: The wire literals below are parsed rather than constructed, so the info they yield carries what parsing actually produces -- a :class:`~pcapkit.protocols.misc.raw.Raw` or - :class:`~pcapkit.protocols.misc.null.NoPayload` instance for the payload, + :class:`~pcapkit.protocols.misc.no_payload.NoPayload` instance for the payload, and an option *container* for the options -- rather than the constructor-shaped values :meth:`IPv4.make ` is normally handed. Without @@ -145,7 +145,7 @@ def test_ipv4_from_data_rebuilds_a_parsed_datagram(self) -> None: """ from pcapkit.const.ipv4.option_number import OptionNumber from pcapkit.protocols.internet.ipv4 import IPv4 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw cases = [ @@ -205,7 +205,7 @@ def test_ipv4_make_accepts_a_protocol_instance_as_payload(self) -> None: """ from pcapkit.protocols.internet.ipv4 import IPv4 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw from pcapkit.protocols.protocol import Protocol, ProtocolBase @@ -311,7 +311,7 @@ def test_schema_pack_packs_a_second_real_protocol_as_payload(self) -> None: This closes a hole in the tests above rather than describing a defect of its own. Every one of them hands the payload field a :class:`~pcapkit.protocols.misc.raw.Raw` or a - :class:`~pcapkit.protocols.misc.null.NoPayload`, because those are what + :class:`~pcapkit.protocols.misc.no_payload.NoPayload`, because those are what *parsing* yields, so between them they exercise exactly two of the :class:`~pcapkit.protocols.protocol.ProtocolBase` descendants the check in :meth:`Schema.pack @@ -345,7 +345,7 @@ def test_schema_pack_packs_a_second_real_protocol_as_payload(self) -> None: """ from pcapkit.protocols.internet.ipv4 import IPv4 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw from pcapkit.protocols.protocol import Protocol, ProtocolBase from pcapkit.protocols.transport.tcp import TCP diff --git a/tests/protocols/internet/test_ipv6_ext_chain_limit_1604_unit.py b/tests/protocols/internet/test_ipv6_ext_chain_limit_1604_unit.py index c778e05689..55eef5ca84 100644 --- a/tests/protocols/internet/test_ipv6_ext_chain_limit_1604_unit.py +++ b/tests/protocols/internet/test_ipv6_ext_chain_limit_1604_unit.py @@ -75,7 +75,7 @@ def frame(carrier: str, count: int, *, mixed: bool = False) -> bytes: def raw_of(parsed: object) -> object: """The first :class:`~pcapkit.protocols.misc.raw.Raw` layer of ``parsed``, if any.""" - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw layer = parsed diff --git a/tests/protocols/internet/test_ipv6_jumbogram_unit.py b/tests/protocols/internet/test_ipv6_jumbogram_unit.py index 24b273196a..8bbd70bb9d 100644 --- a/tests/protocols/internet/test_ipv6_jumbogram_unit.py +++ b/tests/protocols/internet/test_ipv6_jumbogram_unit.py @@ -5,7 +5,7 @@ and carries its real length in a Jumbo Payload option of the Hop-by-Hop Options header. :class:`~pcapkit.protocols.internet.ipv6.IPv6` read only the Payload Length, so its next layer was -:class:`~pcapkit.protocols.misc.null.NoPayload` and the whole jumbo payload +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` and the whole jumbo payload ended up in ``info.trailer``. The Jumbo Payload Length gives the payload extent, and only the octets past it are ``trailer``. Every packet rebuilds byte for byte. diff --git a/tests/protocols/internet/test_ipv6_unit.py b/tests/protocols/internet/test_ipv6_unit.py index 7bc0f9a884..927918ef15 100644 --- a/tests/protocols/internet/test_ipv6_unit.py +++ b/tests/protocols/internet/test_ipv6_unit.py @@ -196,7 +196,7 @@ def test_ipv6_decode_next_layer_without_extensions_and_import_branches(self) -> from pcapkit.protocols.data.internet.ipv6 import IPv6 as Data_IPv6 from pcapkit.protocols.internet.internet import Internet from pcapkit.protocols.internet.ipv6 import IPv6 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw proto = object.__new__(IPv6) diff --git a/tests/protocols/link/test_linux_sll_arphrd_registry_unit.py b/tests/protocols/link/test_linux_sll_arphrd_registry_unit.py index 80dd329d78..6ede1a0671 100644 --- a/tests/protocols/link/test_linux_sll_arphrd_registry_unit.py +++ b/tests/protocols/link/test_linux_sll_arphrd_registry_unit.py @@ -132,7 +132,7 @@ def test_every_other_arphrd_type_dispatches_by_ethertype(self) -> None: def test_an_empty_payload_is_no_payload_on_either_path(self) -> None: from pcapkit.const.linux.arphrd import ARPHRD - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload for version, header, _ in self._versions(): for arphrd in (ARPHRD.FRAD, 1): diff --git a/tests/protocols/link/test_loopback_unit.py b/tests/protocols/link/test_loopback_unit.py index 394c23565d..ba1c4d960f 100644 --- a/tests/protocols/link/test_loopback_unit.py +++ b/tests/protocols/link/test_loopback_unit.py @@ -176,7 +176,7 @@ def _extract(self, octets: bytes, suffix: str): # type: ignore[no-untyped-def] def _assert_capture(self, linktype: int, records: 'list[tuple[bytes, str]]', ipv4: int) -> 'list': """Extract ``records`` under ``linktype`` in both formats; check chains and rebuilds.""" - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.pcap.frame import Frame frames = [] diff --git a/tests/protocols/link/test_netlink_unit.py b/tests/protocols/link/test_netlink_unit.py index 340ff7656b..93972928b7 100644 --- a/tests/protocols/link/test_netlink_unit.py +++ b/tests/protocols/link/test_netlink_unit.py @@ -117,7 +117,7 @@ def test_payload_is_always_raw_regardless_of_type(self) -> None: def test_zero_length_payload_is_no_payload(self) -> None: from pcapkit.protocols.link.netlink import Netlink - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload raw = _nlmsghdr('little', nlmsg_type=3) parsed = Netlink(raw, len(raw)) diff --git a/tests/protocols/link/test_radiotap_unit.py b/tests/protocols/link/test_radiotap_unit.py index 0d56b1cb21..3bb2d4db21 100644 --- a/tests/protocols/link/test_radiotap_unit.py +++ b/tests/protocols/link/test_radiotap_unit.py @@ -53,7 +53,7 @@ def test_minimal_header_with_empty_bitmask(self) -> None: extended present-flags word. """ from pcapkit.protocols.link.radiotap import Radiotap - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload raw = _radiotap(8, [0]) parsed = Radiotap(raw, len(raw)) @@ -207,7 +207,7 @@ def test_malformed_it_len_larger_than_what_was_captured(self) -> None: what is there, and the payload is empty rather than negative-length. """ from pcapkit.protocols.link.radiotap import Radiotap - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload raw = _radiotap(200, [0]) + b'\x01\x02\x03' parsed = Radiotap(raw, len(raw)) diff --git a/tests/protocols/misc/checksum/test_ip_pseudo_2471_unit.py b/tests/protocols/misc/checksum/test_ip_pseudo_2471_unit.py index a9d847c238..654a2a8931 100644 --- a/tests/protocols/misc/checksum/test_ip_pseudo_2471_unit.py +++ b/tests/protocols/misc/checksum/test_ip_pseudo_2471_unit.py @@ -223,7 +223,7 @@ def test_rejections(self) -> None: def test_name_and_chain(self) -> None: from pcapkit.protocols.misc.checksum.ip_pseudo import IP_Pseudo - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload pseudo = IP_Pseudo(src='10.0.0.1', dst='10.0.0.2', protocol=6, upper_length=20) self.assertEqual(pseudo.name, 'IP Pseudo-Header') diff --git a/tests/protocols/misc/test_no_payload_path_2529_unit.py b/tests/protocols/misc/test_no_payload_path_2529_unit.py new file mode 100644 index 0000000000..e23f1a4db7 --- /dev/null +++ b/tests/protocols/misc/test_no_payload_path_2529_unit.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +"""``NoPayload`` and its schema and data model live in ``no_payload`` modules, and only there. + +GitHub issue #2529: a protocol class and the module holding it share a name, so +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` is in +:mod:`pcapkit.protocols.misc.no_payload`, its header schema in +:mod:`pcapkit.protocols.schema.misc.no_payload` and its data model in +:mod:`pcapkit.protocols.data.misc.no_payload`. The ``misc.null`` paths they +shipped under in 1.5.x keep no re-export, by the ruling on #1715 (#1744). This +pins both halves: the old paths do not import, and every importer reaches the +classes through the new modules. The ``versionremoved`` notes for the old paths +are pinned with the other shipped paths, in +:mod:`tests.project.test_no_moved_name_re_exports_1744_unit`. + +""" +import importlib +import importlib.util +import unittest + +from tests._support import reimport_once_per_class + +#: Test tier (#1958): checks where ``NoPayload`` lives and that its old paths are +#: gone, a question about the tree. +__tier__ = 'LATEST' + +RUNTIME_DEPS = ('tbtrim', 'aenum', 'chardet', 'dictdumper') +HAS_RUNTIME = all(importlib.util.find_spec(name) is not None for name in RUNTIME_DEPS) + +#: ``(new module, old module)`` for the protocol, its header schema and its data model. +PATHS = ( + ('pcapkit.protocols.misc.no_payload', 'pcapkit.protocols.misc.null'), + ('pcapkit.protocols.schema.misc.no_payload', 'pcapkit.protocols.schema.misc.null'), + ('pcapkit.protocols.data.misc.no_payload', 'pcapkit.protocols.data.misc.null'), +) + +#: The packages that export ``NoPayload``, as ``(package, module it comes from)``. +PACKAGES = ( + ('pcapkit', 'pcapkit.protocols.misc.no_payload'), + ('pcapkit.protocols', 'pcapkit.protocols.misc.no_payload'), + ('pcapkit.protocols.misc', 'pcapkit.protocols.misc.no_payload'), + ('pcapkit.protocols.schema', 'pcapkit.protocols.schema.misc.no_payload'), + ('pcapkit.protocols.schema.misc', 'pcapkit.protocols.schema.misc.no_payload'), + ('pcapkit.protocols.data', 'pcapkit.protocols.data.misc.no_payload'), + ('pcapkit.protocols.data.misc', 'pcapkit.protocols.data.misc.no_payload'), +) + + +@unittest.skipUnless(HAS_RUNTIME, 'runtime dependencies not installed') +class NoPayloadPathTests(unittest.TestCase): + """Pin the ``no_payload`` modules as the only home of ``NoPayload``.""" + + def setUp(self) -> None: + reimport_once_per_class(self) + + def test_the_null_paths_do_not_import(self) -> None: + importlib.import_module('pcapkit.protocols.misc') + for _, old in PATHS: + with self.subTest(path=old): + with self.assertRaises(ModuleNotFoundError) as ctx: + importlib.import_module(old) + self.assertEqual(ctx.exception.name, old) + self.assertIsNone(importlib.util.find_spec(old)) + + def test_each_module_holds_no_payload_alone(self) -> None: + for new, _ in PATHS: + with self.subTest(path=new): + module = importlib.import_module(new) + self.assertEqual(module.__all__, ['NoPayload']) + self.assertEqual(module.NoPayload.__module__, new) + + def test_the_protocol_binds_the_new_schema_and_data_model(self) -> None: + from pcapkit.protocols.data.misc.no_payload import NoPayload as Data_NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload + from pcapkit.protocols.schema.misc.no_payload import NoPayload as Schema_NoPayload + + self.assertIs(NoPayload.__schema__, Schema_NoPayload) + self.assertIs(NoPayload.__data__, Data_NoPayload) + self.assertIsInstance(NoPayload().info, Data_NoPayload) + + def test_every_package_exports_the_new_modules_class(self) -> None: + for package, home in PACKAGES: + with self.subTest(package=package): + module = importlib.import_module(package) + self.assertIn('NoPayload', module.__all__) + self.assertIs(module.NoPayload, importlib.import_module(home).NoPayload) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/protocols/misc/test_raw_linktype_dispatch_1502_unit.py b/tests/protocols/misc/test_raw_linktype_dispatch_1502_unit.py index dc9175510e..aac7785337 100644 --- a/tests/protocols/misc/test_raw_linktype_dispatch_1502_unit.py +++ b/tests/protocols/misc/test_raw_linktype_dispatch_1502_unit.py @@ -57,7 +57,7 @@ def _keywords(frame): # type: ignore[no-untyped-def] return {'num': frame._fnum, 'sct': frame._sect, 'ctx': frame._ctx} def test_version_nibble_selects_the_layer(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload for build, suffix in FORMATS: with self.subTest(format=suffix): diff --git a/tests/protocols/misc/test_raw_null_unit.py b/tests/protocols/misc/test_raw_null_unit.py index b24c123532..47c3c3f4a2 100644 --- a/tests/protocols/misc/test_raw_null_unit.py +++ b/tests/protocols/misc/test_raw_null_unit.py @@ -45,7 +45,7 @@ def test_raw_properties_make_data_and_index_error(self) -> None: self.assertIsNone(raw._info.protocol) def test_no_payload_properties_read_make_and_index_error(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.utilities.exceptions import UnsupportedCall null = object.__new__(NoPayload) diff --git a/tests/protocols/schema/test_schema_field_remainder_unit.py b/tests/protocols/schema/test_schema_field_remainder_unit.py index d0cdebdaf9..c7a9d7cade 100644 --- a/tests/protocols/schema/test_schema_field_remainder_unit.py +++ b/tests/protocols/schema/test_schema_field_remainder_unit.py @@ -93,7 +93,7 @@ def length(self): # type: ignore[no-untyped-def] return len(self.__header__) def read(self, length=None, **kwargs): # type: ignore[no-untyped-def] - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload schema = self.__header__ self._next = NoPayload() diff --git a/tests/protocols/schema/test_schema_unit.py b/tests/protocols/schema/test_schema_unit.py index d329d8ed05..4db8e1ce41 100644 --- a/tests/protocols/schema/test_schema_unit.py +++ b/tests/protocols/schema/test_schema_unit.py @@ -179,7 +179,7 @@ def length(self) -> int: return 0 def read(self, length: int | None = None, **kwargs: object) -> DummyData: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload self._next = NoPayload() self._protos = ProtoChain(self.__class__, self.alias) return DummyData() @@ -311,7 +311,7 @@ class EmptyGeneratedSchema(Schema): def test_generated_init_is_installed_and_runs_post_init(self) -> None: from pcapkit.corekit.fields.collections import ListField from pcapkit.corekit.fields.numbers import UInt8Field, UInt16Field - from pcapkit.protocols.schema.misc.null import NoPayload + from pcapkit.protocols.schema.misc.no_payload import NoPayload from pcapkit.protocols.schema.schema import Schema, schema_final @schema_final diff --git a/tests/protocols/test_capture_roundtrip_runtime.py b/tests/protocols/test_capture_roundtrip_runtime.py index 81b1ccd0b2..971ccd4623 100644 --- a/tests/protocols/test_capture_roundtrip_runtime.py +++ b/tests/protocols/test_capture_roundtrip_runtime.py @@ -117,7 +117,7 @@ def outcome(layer: 'Any', as_dict: 'bool' = False) -> 'str': def walk(frame: 'Any') -> 'Iterator[tuple[str, Any]]': """Yield ``(path, layer)`` for the payload chain and every IPv6 extension header.""" - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload path = '' layer = frame @@ -193,7 +193,7 @@ def test_every_layer_rebuilds_from_its_info(self) -> None: self.assertEqual(set(LAYER_GAPS) - seen, set(), 'LAYER_GAPS names cases that no longer exist') def test_every_layer_rebuilds_from_its_info_as_a_dict(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload hit = set() with time_limit(SWEEP_TIMEOUT): diff --git a/tests/protocols/test_construction_keyword_check_unit.py b/tests/protocols/test_construction_keyword_check_unit.py index d9bc64afe9..50a96b8f87 100644 --- a/tests/protocols/test_construction_keyword_check_unit.py +++ b/tests/protocols/test_construction_keyword_check_unit.py @@ -157,7 +157,7 @@ def length(self) -> 'int': return 2 def read(self, length: 'int | None' = None, **kwargs: 'Any') -> 'DummyData': - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload self._next = NoPayload() self._protos = ProtoChain(type(self), self.alias, basis=self._next.protochain) @@ -381,7 +381,7 @@ def test_a_keyword_only_read_declares_is_accepted_end_to_end(self) -> None: def read(self, length: 'int | None' = None, *, eggs: 'int' = 0, **kwargs: 'Any') -> 'Any': from pcapkit.corekit.protochain import ProtoChain - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload self._next = NoPayload() self._protos = ProtoChain(type(self), self.alias, basis=self._next.protochain) @@ -408,7 +408,7 @@ def test_keywords_declared_by_a_class_attribute_are_accepted(self) -> None: """ def read(self, length: 'int | None' = None, **kwargs: 'Any') -> 'Any': from pcapkit.corekit.protochain import ProtoChain - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload self._next = NoPayload() self._protos = ProtoChain(type(self), self.alias, basis=self._next.protochain) @@ -582,7 +582,7 @@ def test_from_data_survives_the_injected_packet_keyword(self) -> None: default :meth:`ProtocolBase._make_data ` is ``data.to_dict()`` -- so ``from_data`` hands ``packet`` to a ``make`` that very often does not - declare it. :class:`~pcapkit.protocols.misc.null.NoPayload` is the case + declare it. :class:`~pcapkit.protocols.misc.no_payload.NoPayload` is the case that matters, because :meth:`ProtocolBase._make_payload ` reaches it for the innermost layer of every packet: refusing ``packet`` breaks ``from_data`` diff --git a/tests/protocols/test_declarations_match_values_2317_unit.py b/tests/protocols/test_declarations_match_values_2317_unit.py index cc79ab6ad2..6c1e32a74e 100644 --- a/tests/protocols/test_declarations_match_values_2317_unit.py +++ b/tests/protocols/test_declarations_match_values_2317_unit.py @@ -9,7 +9,7 @@ ``Optional`` on an ``RR``/``SSR`` ``route`` that is always built, :attr:`~pcapkit.protocols.protocol.ProtocolBase.protochain` declaring a :class:`~pcapkit.corekit.protochain.ProtoChain` that -:class:`~pcapkit.protocols.misc.null.NoPayload` does not have, a ``pack_flags`` +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` does not have, a ``pack_flags`` constructor stub typing the EPB flags, ``ARP._make_addr_resolve`` leaving out the :obj:`bytearray` its body handles, an undeclared ``entry_raw``, two HIP parameters missing from both ``__all__`` lists, and a ``version`` that one @@ -173,7 +173,7 @@ def setUp(self) -> None: reimport_once_per_class(self) def test_protochain_is_none_and_says_so(self) -> None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.protocol import ProtocolBase self.assertIsNone(NoPayload().protochain) diff --git a/tests/protocols/test_dispatch_default_resolution_unit.py b/tests/protocols/test_dispatch_default_resolution_unit.py index 86bf3413e6..bc1088db2b 100644 --- a/tests/protocols/test_dispatch_default_resolution_unit.py +++ b/tests/protocols/test_dispatch_default_resolution_unit.py @@ -143,7 +143,7 @@ def test_a_missed_code_can_still_be_registered_without_a_warning(self) -> None: """ Dummy = self._dummy_protocol() - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.misc.raw import Raw for _ in range(5): diff --git a/tests/protocols/test_lookup_by_name_2003_unit.py b/tests/protocols/test_lookup_by_name_2003_unit.py index fd4898490e..b5222e211d 100644 --- a/tests/protocols/test_lookup_by_name_2003_unit.py +++ b/tests/protocols/test_lookup_by_name_2003_unit.py @@ -148,7 +148,7 @@ def test_cut_upper_layer_is_found_ahead_of_the_headers(self) -> None: def test_dict_without_the_dispatch_keys_is_not_guessed_at(self) -> None: from pcapkit.protocols.internet.ipv6 import IPv6 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload ip6 = IPv6(HOP_DST_DST) exported = ip6.info.to_dict() diff --git a/tests/protocols/test_next_layer_short_header_unit.py b/tests/protocols/test_next_layer_short_header_unit.py index ade26efd9a..6e159409ef 100644 --- a/tests/protocols/test_next_layer_short_header_unit.py +++ b/tests/protocols/test_next_layer_short_header_unit.py @@ -4,7 +4,7 @@ This guards against GitHub issue #1170, where every ``_import_next_layer`` parsed the next layer from whatever octets were captured, however few, and only picked -:class:`~pcapkit.protocols.misc.null.NoPayload` for a declared length of zero. +:class:`~pcapkit.protocols.misc.no_payload.NoPayload` for a declared length of zero. :meth:`Schema.unpack ` zero-fills the fields the stream ends inside, so :meth:`~pcapkit.protocols.protocol.ProtocolBase.from_data` rebuilt a header that @@ -42,7 +42,7 @@ def setUp(self) -> None: def test_ipv6_header_without_payload_octets(self) -> None: from pcapkit.protocols.internet.ipv6 import IPv6 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload parsed = IPv6(IPV6, len(IPV6)) self.assertIsInstance(parsed.payload, NoPayload) @@ -71,7 +71,7 @@ def test_ipv4_partial_udp_header(self) -> None: def test_udp_header_without_payload_octets(self) -> None: from pcapkit.protocols.internet.ipv4 import IPv4 - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload from pcapkit.protocols.transport.udp import UDP as UDP_ packet = IPV4 + UDP[:8] diff --git a/tests/protocols/test_protocol_base_unit.py b/tests/protocols/test_protocol_base_unit.py index b56b8384ee..20fcb7f93c 100644 --- a/tests/protocols/test_protocol_base_unit.py +++ b/tests/protocols/test_protocol_base_unit.py @@ -64,7 +64,7 @@ def read(self, length: int | None = None, *, value: int = 0, data = DummyData(value=value) self._next = next_protocol if self._next is None: - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload self._next = NoPayload() self._protos = ProtoChain(self.__class__, self.alias, basis=self._next.protochain) return data @@ -340,7 +340,7 @@ def __index__(cls) -> int: DummyProtocol.__proto__ = collections.defaultdict(lambda: BrokenRaw, {2: BrokenRaw, 3: EOFProtocol}) self.assertIsInstance(DummyProtocol.analyze(2, b'bad'), Raw) - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload self.assertIsInstance(DummyProtocol.analyze(3, b''), NoPayload) proto = DummyProtocol(packet=b'abpayload') @@ -527,7 +527,7 @@ def test_make_pack_raises_struct_error_for_every_size(self) -> None: def test_make_payload_branches(self) -> None: DummyProtocol, DummyData, _ = self._make_protocol_class() - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload self.assertIsInstance(DummyProtocol._make_payload({}), NoPayload) # type: ignore[arg-type] self.assertIsInstance(DummyProtocol._make_payload({ # type: ignore[arg-type] diff --git a/tests/protocols/test_register_restores_shipped_descriptor_1504_unit.py b/tests/protocols/test_register_restores_shipped_descriptor_1504_unit.py index c804bdeb6c..9df418179f 100644 --- a/tests/protocols/test_register_restores_shipped_descriptor_1504_unit.py +++ b/tests/protocols/test_register_restores_shipped_descriptor_1504_unit.py @@ -113,7 +113,7 @@ def _sites(self): # type: ignore[no-untyped-def] for module, name, code in SITES: yield name, getattr(importlib.import_module(module), name), _code(code) table = collections.defaultdict(lambda: ModuleDescriptor('pcapkit.protocols.misc.raw', 'Raw'), - {1: ModuleDescriptor('pcapkit.protocols.misc.null', 'NoPayload')}) + {1: ModuleDescriptor('pcapkit.protocols.misc.no_payload', 'NoPayload')}) yield 'ProtocolBase', type('W1504Scratch', (Raw,), {'__module__': __name__, '__proto__': table}), 1 def _each_site(self, check): # type: ignore[no-untyped-def] diff --git a/tests/protocols/test_registry_stored_descriptor_unit.py b/tests/protocols/test_registry_stored_descriptor_unit.py index a0afd868e6..1dee63bd11 100644 --- a/tests/protocols/test_registry_stored_descriptor_unit.py +++ b/tests/protocols/test_registry_stored_descriptor_unit.py @@ -122,7 +122,7 @@ def test_protocol_base_register_keeps_the_stored_descriptor(self) -> None: self.assertIs(scratch.__proto__[1], descriptor) self.assertEqual(self._count(scratch.register, 1, ModuleDescriptor(*descriptor)), 0) self.assertIs(scratch.__proto__[1], descriptor) - other = ModuleDescriptor('pcapkit.protocols.misc.null', 'NoPayload') + other = ModuleDescriptor('pcapkit.protocols.misc.no_payload', 'NoPayload') self.assertEqual(self._count(scratch.register, 1, other), 1) self.assertIs(scratch.__proto__[1], other.klass) diff --git a/tests/protocols/test_to_dict_payload_roundtrip_1447_unit.py b/tests/protocols/test_to_dict_payload_roundtrip_1447_unit.py index df4d34c125..6d1120d16e 100644 --- a/tests/protocols/test_to_dict_payload_roundtrip_1447_unit.py +++ b/tests/protocols/test_to_dict_payload_roundtrip_1447_unit.py @@ -104,7 +104,7 @@ def frame(self, name: str): # type: ignore[no-untyped-def] def layers(self, name: str): # type: ignore[no-untyped-def] """Yield every layer of ``FRAMES[name]``, from the frame down.""" - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload layer = self.frame(name) while not isinstance(layer, NoPayload): @@ -171,7 +171,7 @@ def test_http_dict_keeps_its_version(self) -> None: def test_dict_without_a_payload_key_rebuilds_the_header_alone(self) -> None: from pcapkit.protocols.link.ethernet import Ethernet - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload eth = Ethernet(FRAMES['ipv4-udp']) dict_ = eth.info.to_dict() @@ -183,7 +183,7 @@ def test_dict_without_a_payload_key_rebuilds_the_header_alone(self) -> None: def test_dict_without_the_dispatch_keys_rebuilds_the_header_alone(self) -> None: from pcapkit.protocols.link.ethernet import Ethernet - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload # The payload is still there under its name, but nothing names it. eth = Ethernet(FRAMES['ipv4-udp']) diff --git a/tests/protocols/transport/test_sctp_unit.py b/tests/protocols/transport/test_sctp_unit.py index 26d6fac7cc..633aca8a44 100644 --- a/tests/protocols/transport/test_sctp_unit.py +++ b/tests/protocols/transport/test_sctp_unit.py @@ -1023,7 +1023,7 @@ def test_unregistered_ppid_does_not_mutate_the_class_registry(self) -> None: def test_packet_without_a_data_chunk_has_no_payload(self) -> None: from pcapkit.const.sctp.chunk import Chunk - from pcapkit.protocols.misc.null import NoPayload + from pcapkit.protocols.misc.no_payload import NoPayload raw = self._build([(Chunk.Cookie_Acknowledgement, {})]) proto = self._packet(raw) diff --git a/tests/protocols/transport/test_transport_unit.py b/tests/protocols/transport/test_transport_unit.py index 9f97369ac4..f6aa374f7d 100644 --- a/tests/protocols/transport/test_transport_unit.py +++ b/tests/protocols/transport/test_transport_unit.py @@ -16,7 +16,7 @@ class TransportUnitTests(unittest.TestCase): def setUp(self) -> None: # ``isolate_modules`` rather than ``purge_modules``: tests below bind - # stand-ins over ``pcapkit.protocols.misc.raw`` and ``...misc.null``, which + # stand-ins over ``pcapkit.protocols.misc.raw`` and ``...misc.no_payload``, which # are on the import path of most of the package. See #660. isolate_modules(self)