diff --git a/pcapkit/const/ftp/command.py b/pcapkit/const/ftp/command.py index 19627efa94..05ad4bb487 100644 --- a/pcapkit/const/ftp/command.py +++ b/pcapkit/const/ftp/command.py @@ -43,7 +43,7 @@ class FEATCode(EnumRegistry, StrEnum): turns up on the wire but names none of these -- the extendability the owner conditionally asked to keep on GitHub issue :issue:`860`: unsure what a FEAT value absent from the RFC's list means in the CSV table, the owner - said that if the expected handling is our current approach, as industry + said that if the expected handling is this registry's approach, as industry convention has it, the registry stays extendable as is, and then approved declaring the registry's keywords as real members with ``_missing_`` still covering the rest. No custom ``__new__`` here, so the base's @@ -120,7 +120,7 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'FEATCode': recommendation, while some of this registry's codes are registered in lower case -- measured on the IANA CSV: ``base``, ``feat``, ``hist``, ``nat6`` and ``secu``, against all-upper-case keywords for the rest, - with none mixed. Without this override ``get('BASE')`` raised + with none mixed. Without this override ``get('BASE')`` raises :exc:`KeyError`, which is the defect GitHub issue :issue:`903`'s audit found. The obvious objection, answered: :rfc:`5797` uses case *presentationally* @@ -141,9 +141,9 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'FEATCode': own precedence -- name before value -- and its non-minting ``str`` path both survive: nothing here calls ``cls(key)``, so a key matching no member, folded or not, still raises rather than growing the - registry. ``get('ZZ-NOT-REAL')`` therefore still raises - :exc:`KeyError` while ``FEATCode('ZZ-NOT-REAL')`` still yields an - unregistered member, exactly as before. + registry. ``get('ZZ-NOT-REAL')`` therefore raises + :exc:`KeyError` while ``FEATCode('ZZ-NOT-REAL')`` yields an + unregistered member. Args: key: Name or value to look up. A non-``str`` key is passed @@ -214,12 +214,11 @@ def _missing_(cls, value: 'str') -> 'FEATCode': class CommandType(EnumLookup, IntFlag): """Type of "kind" of command, based on :rfc:`959#section-4`. - Re-parented onto :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub - issue :issue:`930`, finishing :issue:`877`'s phase 2. Pure re-parenting as far as - ``get``/``get_all`` are concerned -- this class defines no ``get`` of its - own to reconcile with the base -- and its own :meth:`_missing_` range - guard below is untouched, since :class:`~pcapkit.corekit.enum.EnumLookup` does not touch that - hook. + Built on :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub issue + :issue:`930`, which finished :issue:`877`'s phase 2. This class defines no + ``get`` of its own, so ``get``/``get_all`` are the base's, and its own + :meth:`_missing_` range guard below stands as written, since + :class:`~pcapkit.corekit.enum.EnumLookup` does not touch that hook. """ @@ -248,10 +247,9 @@ def _missing_(cls, value: 'int') -> 'CommandType': class ConformanceRequirement(EnumLookup, IntEnum): """Expectation for support in modern FTP implementations. - Re-parented onto :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub - issue :issue:`930`, finishing :issue:`877`'s phase 2 -- pure re-parenting, since this - class defines neither ``get`` nor ``_missing_`` of its own to reconcile - with the base. + Built on :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub issue + :issue:`930`, which finished :issue:`877`'s phase 2. This class defines + neither ``get`` nor ``_missing_`` of its own. """ @@ -611,8 +609,7 @@ def get(cls, key: 'str', default: 'Optional[str]' = None) -> 'Command': """ if not isinstance(key, str): # NOTE: unreachable only by the ``str`` annotation, which a caller - # at run time need not honour -- this is the path GitHub issue - # #1824 fixed. + # at run time need not honour (GitHub issue #1824). return super().get(key) # type: ignore[unreachable] name = key.upper() if name not in cls._member_map_: # pylint: disable=no-member @@ -620,14 +617,13 @@ def get(cls, key: 'str', default: 'Optional[str]' = None) -> 'Command': # else ``key`` exactly as given -- never ``name`` -- so an # unregistered member's value is the caller's own casing, the # same convention :meth:`_unregistered_member` documents and - # :class:`~pcapkit.const.ftp.command.FEATCode` already followed + # :class:`~pcapkit.const.ftp.command.FEATCode` follows # unchanged. Two calls naming the same command in different # case, e.g. ``get('xyzw')`` and ``get('XYZW')``, therefore build # results that are *not* equal -- each is exactly what its own - # caller passed. Minting instead returned, through the + # caller passed. Minting instead would return, through the # ``_member_map_`` cache, the *first* casing seen for every later - # call regardless of case; that is the one observable behaviour - # change in GitHub issue #860's conversion. + # call regardless of case (GitHub issue #860). return cls._unregistered_member(default if default is not None else key, name) return cls._member_map_[name] # pylint: disable=no-member diff --git a/pcapkit/const/http/method.py b/pcapkit/const/http/method.py index ed392ff116..3ea2bd3f74 100644 --- a/pcapkit/const/http/method.py +++ b/pcapkit/const/http/method.py @@ -279,13 +279,13 @@ def get(cls, key: 'str', default: 'Optional[str]' = None) -> 'Method': # else ``key`` exactly as given -- never its upper-cased form -- # so an unregistered member's value is the caller's own casing, # the same convention :meth:`_unregistered_member` documents and - # :class:`~pcapkit.const.ftp.command.FEATCode` already followed. + # :class:`~pcapkit.const.ftp.command.FEATCode` follows. # The name is always the canonical upper-case form, matching # :meth:`_missing_` and every registered member's own name. Two # calls naming the same method in different case, e.g. # ``get('frob')`` and ``get('FROB')``, therefore build results # that are *not* equal -- each is exactly what its own caller - # passed, per GitHub issue #860's conversion away from minting. + # passed, since ``get`` does not mint (GitHub issue #860). return cls._unregistered_member(default if default is not None else key, key.upper()) @classmethod diff --git a/pcapkit/const/reg/apptype/__init__.py b/pcapkit/const/reg/apptype/__init__.py index 6292eb91ee..228dd7acb9 100644 --- a/pcapkit/const/reg/apptype/__init__.py +++ b/pcapkit/const/reg/apptype/__init__.py @@ -59,9 +59,9 @@ #: Registries imported on first use rather than with this package, as submodule #: name to class name -- GitHub issue :issue:`1538`. Generated from IANA's -#: registry, the two hold about 49,700 lines of members and were about 30% of -#: ``import pcapkit``, while SCTP's and DCCP's cost a few milliseconds and stay -#: eager. +#: registry, the two hold about 49,700 lines of members, about 30% of +#: ``import pcapkit`` when imported eagerly, while SCTP's and DCCP's cost a few +#: milliseconds and stay eager. _LAZY = {'tcp': 'TCP', 'udp': 'UDP'} @@ -69,8 +69,9 @@ class _Registries(dict): """:attr:`AppType.__registries__ `, importing a lazy registry the first time its value is read. - Every key is present from the start, in the order the eager imports used to - insert them, so :func:`len`, ``in`` and iteration import nothing. A lazy + Every key is present from the start, in the order + :class:`~pcapkit.const.reg.apptype.apptype.TransportProtocol` declares them, + so :func:`len`, ``in`` and iteration import nothing. A lazy registry's value is a :class:`~pcapkit.corekit.module.ModuleDescriptor` until the first read replaces it with the class. Every way of reading a value is overridden, :meth:`__iter__` included: overriding it is what makes diff --git a/pcapkit/const/reg/apptype/apptype.py b/pcapkit/const/reg/apptype/apptype.py index 8a9a26bb88..5069ee268c 100644 --- a/pcapkit/const/reg/apptype/apptype.py +++ b/pcapkit/const/reg/apptype/apptype.py @@ -40,42 +40,35 @@ class TransportProtocol(EnumLookup, IntEnum): # ever ships type stubs letting it infer TransportProtocol on its own, # these casts start erroring instead of lingering as dead scaffolding. # - # Values are sequential from 0 rather than the power-of-two spacing this - # class carried while it still mixed in ``IntFlag`` -- ``undefined`` is - # declared explicitly as ``0`` and every other member is ``auto()``, which - # continues from the preceding explicit value rather than needing its own - # ``_start_ = 0`` to begin there. A ruling given in review of the work for - # #860 is explicit that ``undefined`` stays a direct ``0`` for that reason: - # the other, real transports use ``auto()``, so no ``_start_`` has to be - # defined and the declaration of ``undefined`` stays explicit. GitHub issue - # #808 already dropped the ``IntFlag`` base once nothing built a composite, - # and a ruling given in review of that work later retired ``|``-composite - # decoding entirely: once it is no longer a Flag, a ``|``-joined value is no - # longer parsed and accepted as a composite, and is treated as a whole - # instead of being split. With no decoding left to protect, the owner's own - # further ruling on GitHub issue #860 retired the power-of-two spacing - # itself too: that spacing existed mainly for code that composed values like - # ``tcp | udp``, which the whole-value lookup does not accept, so sequential - # ``auto()`` values are the expected behaviour. :meth:`AppType._dispatch` - # never decodes an ``int`` -- composed by hand with ``|`` or passed bare -- - # into anything narrower than the whole value it already is, on either - # numbering; a plain ``dict.get`` lookup cannot tell a composed ``int`` from - # any other one that happens to equal it. Treating every int as a whole is - # exactly what that ruling above asks for, and it is also why this - # renumbering changes what specific ints mean, not only what composed ones - # do: ``tcp | udp`` (``3``) used to name no registry and resolves as - # ``sctp``'s own value, and a bare, uncomposed ``4`` -- previously - # ``sctp``'s value -- resolves as ``dccp``'s, silently, with no - # exception, since a real member sits at ``4`` either way. A caller holding - # an integer under the old spacing (composed or not) can therefore land on a - # different real transport's registry under the sequential numbering, not - # merely be refused where it previously resolved. + # Values are sequential from 0: ``undefined`` is declared explicitly as + # ``0`` and every other member is ``auto()``, which continues from the + # preceding explicit value rather than needing its own ``_start_ = 0`` to + # begin there. A ruling given in review of the work for #860 is explicit + # that ``undefined`` stays a direct ``0`` for that reason: the other, real + # transports use ``auto()``, so no ``_start_`` has to be defined and the + # declaration of ``undefined`` stays explicit. The class is an ``IntEnum`` + # rather than an ``IntFlag`` (GitHub issue #808), and a ruling given in + # review of that work treats a ``|``-joined value as a whole rather than + # parsing it as a composite. With no composite decoding to serve, the + # owner's further ruling on GitHub issue #860 makes the values sequential + # rather than powers of two: that spacing existed mainly for code that + # composed values like ``tcp | udp``, which the whole-value lookup does not + # accept. :meth:`AppType._dispatch` never decodes an ``int`` -- composed by + # hand with ``|`` or passed bare -- into anything narrower than the whole + # value it already is; a plain ``dict.get`` lookup cannot tell a composed + # ``int`` from any other one that happens to equal it. So ``tcp | udp`` + # (``3``) resolves as ``sctp``'s own value, silently, with no exception. + # Before 1.5.0 the class was an ``IntFlag`` with ``sctp`` at ``4`` and + # ``dccp`` at ``8``, so an integer held from that numbering (composed or + # not) can land on a different real transport's registry rather than + # merely be refused: a bare ``4`` resolves as ``dccp``'s. #: No transport protocol. ``TransportProtocol(0) is undefined`` and #: ``bool(undefined)`` is ``False``; it is the ``proto`` sentinel default #: for ``__transport__``, ``__new__``, ``get`` and ``get_all``. The base - #: registry's ``_missing_`` answered its unassigned and reserved spans with - #: it until :issue:`2048`; they answer with the asking registry's transport. + #: registry's ``_missing_`` does not answer with it: its unassigned and + #: reserved spans answer with the asking registry's transport + #: (:issue:`2048`). undefined = cast('TransportProtocol', 0) #: Transmission Control Protocol. @@ -94,20 +87,19 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco Delegates to :meth:`~pcapkit.corekit.enum.EnumLookup.get` for GitHub issue :issue:`877`'s re-parenting, but keeps this override rather than dropping it, for one behaviour the base does not reproduce on its own: **case - folding**. This class has always matched a name case-insensitively + folding**. This class matches a name case-insensitively (``key.lower()``); the base's own ``str`` branch is case-sensitive. Lowering ``key`` before delegating reproduces that: every member name here is already lower-case, so a lowered ``key`` still hits the base's exact ``_member_map_`` lookup. - Case folding is the *only* thing this override adds. It used to - convert the base's name-miss exception as well -- this class raised - :exc:`ValueError` where the base raised :exc:`KeyError` -- and the - ruling given in review of the work for :issue:`877`, implemented in GitHub issue - :issue:`923`, retired that conversion: the exception is to follow what stdlib's - ``Enum`` would raise in the circumstances, :exc:`ValueError` or - :exc:`KeyError` as the case may be, and is to come from - :mod:`pcapkit.utilities.exceptions` rather than being a builtin. A + Case folding is the *only* thing this override adds. It does not + convert the base's name-miss exception: the ruling given in review of + the work for :issue:`877`, implemented in GitHub issue :issue:`923`, is + that the exception follows what stdlib's ``Enum`` would raise in the + circumstances, :exc:`ValueError` or :exc:`KeyError` as the case may + be, and comes from :mod:`pcapkit.utilities.exceptions` rather than + being a builtin. A stdlib ``E['nosuch']`` raises :exc:`KeyError`, and :issue:`923`'s census found :class:`~pcapkit.corekit.enum.EnumLookup` subclasses answering a name miss that way. The exceptions were :class:`AppType` and its @@ -117,31 +109,29 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco preserve, and a name miss reaches the caller as :exc:`~pcapkit.utilities.exceptions.EnumKeyError` from the base. The maintainer's ruling given in review of the work for :issue:`808`, that - :class:`TransportProtocol` is not to be extended at all, is untouched by - that: the refusal is still a refusal and still mints nothing, only its - exception class moved. + :class:`TransportProtocol` is not to be extended at all, holds either + way: the refusal is a refusal and mints nothing, whichever exception + class it raises. The base is a :class:`classmethod` - (:meth:`~pcapkit.corekit.enum.EnumLookup.get`), so this override - moves from :class:`staticmethod` to :class:`classmethod` to - delegate at all -- the same move GitHub issue :issue:`908` made for - :meth:`~pcapkit.const.http.method.Method.get`. A caller invoking it by - name sees no difference between the two; only code taking it as a bare - callable or introspecting ``__func__`` could tell them apart. + (:meth:`~pcapkit.corekit.enum.EnumLookup.get`), so this override is + one too, to delegate at all -- as + :meth:`~pcapkit.const.http.method.Method.get` is (GitHub issue + :issue:`908`). A caller invoking it by name cannot tell it from a + :class:`staticmethod`; only code taking it as a bare callable or + introspecting ``__func__`` could. - ``default`` is accepted here because the original override had no - such parameter at all, which is a genuine LSP violation once this - class' ``get`` is a :class:`classmethod` override of one that has - it: a caller holding a :class:`~pcapkit.corekit.enum.EnumLookup`-typed - reference could pass ``default=`` and hit a :exc:`TypeError` at this + ``default`` is accepted here because an override without it would be + a genuine LSP violation, this class' ``get`` being a + :class:`classmethod` override of one that has it: a caller holding a + :class:`~pcapkit.corekit.enum.EnumLookup`-typed reference could pass ``default=`` and hit a :exc:`TypeError` at this subclass. Forwarded verbatim to :meth:`~pcapkit.corekit.enum.EnumLookup.get` rather than reimplemented, so it behaves exactly as the base's own ``default`` does: a fallback to an *already-registered* value, resolved through ``_value2member_map_`` and never through the constructor, so - passing one still cannot mint. A call that omits it resolves exactly - as one made without the parameter did, so it is purely an added, - backward-compatible capability. + passing one cannot mint either. A call that omits it resolves as if + the parameter did not exist. Args: key: Key to get enum item. @@ -152,9 +142,8 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco Raises: EnumKeyError: If ``key`` names no member and there is no usable - ``default``. A :exc:`KeyError`, from the base, since GitHub - issue :issue:`923` -- it used to be a plain :exc:`ValueError` raised - here. + ``default``. A :exc:`KeyError`, from the base (GitHub issue + :issue:`923`). EnumValueError: If ``key`` is a value no member carries and there is no usable ``default``. A :exc:`ValueError`, from the base. @@ -162,30 +151,24 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco if isinstance(key, str): return super().get(key.lower(), default) # NOTE: the maintainer ruled in review of the work for #808 that - # TransportProtocol is not to be extended at all. A name that is not a - # declared member used to mint a brand-new one here, at ``max_val + 1`` - # (before that, ``max_val * 2``) -- an unbounded, ever-growing set of - # transport protocols nothing ever asked for. There is nothing left to walk: - # it is simply refused, exactly like any other unrecognised name -- - # including one spelling a composite, e.g. ``'tcp|udp'``. ``'|'`` used to be - # intercepted here on its own, so a composite in disguise never got minted - # into a member whose own name lied about being a single transport; a - # further ruling given in review of the work for #808 retired that special - # case along with the rest of the composite handling once TransportProtocol - # stopped being a Flag at all: a ``|``-joined value is no longer parsed and - # accepted as a composite, and is treated as a whole instead of being split. - # A ``'|'``-joined name is therefore not special any more -- it is simply - # not the name of a declared member, and gets the same message as any other - # one that is not. + # TransportProtocol is not to be extended at all, so a name that is not + # a declared member is refused rather than minted -- minting would grow + # an unbounded set of transport protocols nothing ever asked for. That + # includes one spelling a composite, e.g. ``'tcp|udp'``: a further + # ruling given in review of the work for #808 treats a ``|``-joined + # value as a whole rather than parsing it as a composite, so a + # ``'|'``-joined name is not special -- it is simply not the name of a + # declared member, and gets the same message as any other one that is + # not. # # NOTE: the delegation below is exception-compatible for the keys this - # signature admits -- an unrecognised :class:`int` still reaches the + # signature admits -- an unrecognised :class:`int` reaches the # caller as a :exc:`ValueError`, the base's own - # :exc:`~pcapkit.utilities.exceptions.EnumValueError` since GitHub issue - # #923 rather than ``aenum``'s bare one. It is not compatible for - # keys outside it: ``None``, a :class:`float` and an unhashable key - # raised :exc:`AttributeError` from ``key.lower()`` before the - # delegation, and raise :exc:`ValueError` through it (or, for a + # :exc:`~pcapkit.utilities.exceptions.EnumValueError` (GitHub issue + # #923) rather than ``aenum``'s bare one. It is not compatible for + # keys outside it: ``None``, a :class:`float` and an unhashable key, + # on which a ``key.lower()`` would raise :exc:`AttributeError`, raise + # :exc:`ValueError` through it (or, for a # :class:`float`, resolve -- ``get(1.0)`` answers ``tcp``, since # ``cls(key)`` accepts whatever :class:`int` equality accepts). No # caller inside :mod:`pcapkit` can reach any of those: the only live call @@ -193,16 +176,13 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco # what every other ``EnumLookup`` subclass does. return super().get(key, default) - # NOTE: ``_missing_`` used to range-check ``value`` and then defer to - # ``aenum``'s own ``Flag._missing_``, which is what composed an - # unrecognised bit combination into a pseudo-member -- ``TransportProtocol(3)`` - # returning ``tcp|udp`` -- GitHub issue #647's guard against that composing - # *anything*, including values no member declares. GitHub issue #808 removed - # the ``IntFlag`` base once nothing built a composite, and with it the only - # reason this method existed: a plain ``aenum.IntEnum`` already raises - # ``ValueError`` for a value no member declares, with no ``_missing_`` of - # its own needed to get there, so declaring one here would only be - # reproducing what the base class already does. + # NOTE: no ``_missing_`` is declared: a plain ``aenum.IntEnum`` already + # raises ``ValueError`` for a value no member declares. Under an + # ``IntFlag`` base, which this class is not (GitHub issue #808), + # ``Flag._missing_`` would compose an unrecognised bit combination into a + # pseudo-member -- ``TransportProtocol(3)`` returning ``tcp|udp`` -- and a + # range-checking ``_missing_`` would be needed to stop it composing + # *anything*, including values no member declares (GitHub issue #647). class AppType(EnumRegistry, StrEnum): @@ -2389,8 +2369,8 @@ class AppType(EnumRegistry, StrEnum): #: #: Declared here as :obj:`None` and overridden in each subclass: a mutable #: class attribute declared on this class would be *shared* by every - #: subclass, so they would collide with each other exactly as the ports of - #: one transport used to collide inside the old flat registry. + #: subclass, so every transport's ports would collide with each other in + #: one mapping. __registry__: 'Optional[MultiDict[int, AppType]]' = None #: Registry class owning each transport protocol, i.e. what @@ -2464,11 +2444,11 @@ def aliases(self) -> 'tuple[AppType, ...]': def __repr__(self) -> 'str': """Show the member as ````, listing its :attr:`aliases` before the closing bracket when it has any.""" - # NOTE: GitHub issue #807. The suffix below is the only difference from - # the plain form GitHub issue #806 already fixed: it is appended only + # NOTE: GitHub issue #807. The suffix below is the only addition to + # the plain form of GitHub issue #806: it is appended only # when :attr:`aliases` is non-empty, so every member that does not # share its port with another service -- the vast majority -- renders - # in the plain form unchanged. Registering a new alias through + # in the plain form. Registering a new alias through # :meth:`register_alias` changes what *every* member already on that # port renders, immediately, since :attr:`aliases` is derived fresh on # each call rather than fixed at construction. @@ -2559,12 +2539,11 @@ def _dispatch(cls, key: 'int', proto: 'TransportProtocol | str | int') -> 'Type[ delegate to. """ - # NOTE: this registry resolves ports, not service names. The old string - # branch tested ``key in __members_proto__``, which is keyed by transport - # protocol, so a name never matched and the miss path minted a brand-new - # member with port -1 -- GitHub issue #734's silent junk. Rejecting a - # non-port outright is the honest answer, and it has to happen before the - # miss path, which formats ``key`` into an f-string. + # NOTE: this registry resolves ports, not service names, so a non-port + # is rejected outright -- GitHub issue #734, where a name reached the + # miss path and minted a member with port -1, silent junk. Rejecting it + # is the honest answer, and it has to happen before the miss path, + # which formats ``key`` into an f-string. if not isinstance(key, int): raise ValueError(f'{key!r} is not a valid port number for {cls.__name__}') if cls.__registry__ is not None: @@ -2580,43 +2559,34 @@ def _dispatch(cls, key: 'int', proto: 'TransportProtocol | str | int') -> 'Type[ # cast is for mypy alone: ``dict.get`` accepts any hashable key at run # time regardless of its declared key type, but mypy holds ``.get`` to # the dict's own ``TransportProtocol`` keys, and does not know ``proto`` - # can genuinely be a bare :class:`int` here, since GitHub issue #808 - # dropped the ``IntFlag`` base -- see the annotation on ``proto`` above. + # can genuinely be a bare :class:`int` here, TransportProtocol not being + # an ``IntFlag`` (GitHub issue #808) -- see the annotation on ``proto`` + # above. subclass = cls.__registries__.get(cast('TransportProtocol', proto)) if subclass is not None: return subclass # NOTE: everything that reaches here has already failed to match a real # member's value at the dict lookup above, and nothing below decodes - # ``proto``'s bits looking for a partial answer either -- on either - # numbering. A genuine member reaching this point is ``undefined`` -- - # a real transport would already have resolved above, and - # :meth:`TransportProtocol.get` cannot mint anything else, per the - # maintainer ruling given in review of the work for #808, against - # extending TransportProtocol at all -- and a bare :class:`int` reaches - # here whenever it matches no real member's value, e.g. a stray bit like - # ``17``. A composite built by hand used to reach here just as reliably, - # since no combination of the old power-of-two bits ever equalled a - # single real member's value; that is not true under this class's - # sequential numbering -- + # ``proto``'s bits looking for a partial answer. A genuine member + # reaching this point is ``undefined`` -- a real transport would already + # have resolved above, and :meth:`TransportProtocol.get` cannot mint + # anything else, per the maintainer ruling given in review of the work + # for #808, against extending TransportProtocol at all -- and a bare + # :class:`int` reaches here whenever it matches no real member's value, + # e.g. a stray bit like ``17``. A composite built by hand need not: + # under the sequential numbering, # ``TransportProtocol.tcp | TransportProtocol.udp`` (``3``) is - # ``sctp``'s own value, so it resolves at the dict lookup above - # instead of reaching this point at all. A composite used to get its own - # :exc:`~pcapkit.utilities.exceptions.ProtocolError`, decoded through - # :func:`~pcapkit.utilities.compat.show_flag_values` and naming every - # transport whose bit was set -- the fix for GitHub issue #759, where - # resolving a composite by picking its lowest set bit dispatched every - # one containing ``tcp`` into the TCP registry regardless of what else - # it named. A further ruling given in review of the work for #808 - # retired that decoding along with the rest of the composite handling: - # once it is no longer a Flag, a ``|``-joined value is no longer parsed - # and accepted as a composite, and is treated as a whole instead of - # being split. So a composite's bits are never decoded looking for a - # partial answer any more, on either numbering -- it is looked up as the - # one whole value it already is, exactly like any int a caller might - # have written directly, and whether that whole value resolves or - # reaches this point depends only on whether some real member happens to - # equal it, never on whether a caller built it with ``|`` by hand. + # ``sctp``'s own value, so it resolves at the dict lookup above instead. + # A further ruling given in review of the work for #808 treats a + # ``|``-joined value as a whole rather than decoding it -- resolving a + # composite by picking its lowest set bit would dispatch every one + # containing ``tcp`` into the TCP registry regardless of what else it + # named, GitHub issue #759 -- so a composite is looked up as the one + # whole value it is, exactly like any int a caller might have written + # directly, and whether that whole value resolves or reaches this point + # depends only on whether some real member happens to equal it, never + # on whether a caller built it with ``|`` by hand. raise ValueError(f'{proto!r} names no transport protocol registry of ' f'{cls.__name__}') @@ -2684,23 +2654,21 @@ def get(cls, key: 'int', *, # type: ignore[override] # pylint: disable=argument return matched[0] # NOTE: :meth:`_missing_` answers :obj:`None` for a port it holds no row - # for -- GitHub issue #860 stopped that from minting, following the + # for, and that answer does not mint (GitHub issue #860), following the # owner's ruling there that ``get`` should not mint because it lacks the # information to create a new member: only IANA-registered values are # legitimate, and ``register`` is the proper way to add one. That ruling - # was given for the FEATCode, Command and Method branches, and this - # family was brought in line with it under the same issue. A port outside - # ``0..65535`` still *raises* rather than reaching here at all. Before - # #860, catching the ``None`` answer minted ``PORT_{key}_{transport}`` - # here directly -- GitHub issue #758's defect (it also minted for - # ``PORT_999999_tcp`` and ``PORT_-1_tcp``, the latter a name no attribute - # access could reach) -- and this was the second, independent mint site - # on this method, distinct from the one inside :meth:`_missing_` itself: - # neither is a value anyone asked to be named, so both build an - # unregistered member instead of registering one. A port IANA lists on - # other transports only is in no span on this one: 8011, reserved on - # TCP and ``bier-echo`` on UDP, answers ``unknown`` on DCCP and SCTP - # (#2048). + # was given for the FEATCode, Command and Method branches, and covers + # this family under the same issue. A port outside ``0..65535`` *raises* + # rather than reaching here at all. Minting on the ``None`` answer would + # name a member ``PORT_{key}_{transport}`` -- GitHub issue #758's + # defect, which also minted ``PORT_999999_tcp`` and ``PORT_-1_tcp``, the + # latter a name no attribute access could reach -- so, as inside + # :meth:`_missing_` itself, the port gets an unregistered member + # instead: neither is a value anyone asked to be named. A port IANA + # lists on other transports only is in no span on this one: 8011, + # reserved on TCP and ``bier-echo`` on UDP, answers ``unknown`` on DCCP + # and SCTP (#2048). ret = owner._missing_(key) if ret is None: ret = owner._unregistered_member(key, 'unknown', owner.__transport__) @@ -3018,8 +2986,8 @@ def _missing_(cls, value: 'int') -> 'Optional[AppType]': # GitHub issue #760, where source order decided instead and a UDP lookup in # 6000-6063 came back carrying ``tcp``. A registry a named span excludes # falls through to :meth:`_unregistered_member`, which is what IANA - # assigning it nothing means -- GitHub issue #860 stopped this from - # growing either lookup table or :data:`__registry__`, on the owner's + # assigning it nothing means, and grows neither lookup table nor + # :data:`__registry__` (GitHub issue #860), on the owner's # ruling there that only IANA-registered values are legitimate and a new # entry is properly created through ``register``; that ruling was given for # the FEATCode, Command and Method branches, and this family follows it. diff --git a/pcapkit/corekit/fields/field.py b/pcapkit/corekit/fields/field.py index 841555b9a1..6888e882b0 100644 --- a/pcapkit/corekit/fields/field.py +++ b/pcapkit/corekit/fields/field.py @@ -300,8 +300,9 @@ def __copy__(self) -> 'Self': :attr:`~object.__dict__` shallow-updated from this one. Note: - Every ``__call__`` override in this module calls ``self.__copy__()`` - directly rather than :func:`copy.copy(self) `. + Every ``__call__`` in :mod:`pcapkit.corekit.fields` copies through + ``self.__copy__()`` -- directly, or by way of ``super().__call__`` -- + rather than :func:`copy.copy(self) `. :func:`copy.copy` still has to *find* this method before it can call it -- ``getattr(cls, '__copy__', None)`` -- and that lookup alone was profiled at 55,846 calls (~1.7% of an @@ -309,8 +310,8 @@ def __copy__(self) -> 'Self': ``examples/captures/http.pcap``, one per field per packet, all from this exact path. Calling ``__copy__`` directly is exactly what :func:`copy.copy` would have done once it - found it, so this changes nothing about *when* a field is copied or - what the copy contains -- only the redundant dispatch is removed. + found it, so a field is copied at the same points and to the same + contents either way -- only the redundant dispatch is skipped. See GitHub issue :issue:`730`. Returns: @@ -436,7 +437,7 @@ def unpack(self, buffer: 'bytes | IO[bytes]', packet: 'dict[str, Any]') -> '_T': # ``secrets_data: BytesField(length=lambda pkt: pkt['__length__'])``) -- # and is thus attacker-controlled: a corrupt or hostile capture can # declare an arbitrarily large one. Past :data:`~pcapkit.utilities.config.MAX_ZERO_PAD_LENGTH`, a - # length short of what ``buffer`` holds is provably bogus: the padding + # length that ``buffer`` falls short of is provably bogus: the padding # cannot recover data that was never in the buffer, only zero-fill for # it, and no field this large is legitimate to begin with. Honouring it # would allocate and zero-fill up to ``length`` octets on nothing but @@ -491,7 +492,7 @@ def unpack(self, buffer: 'bytes | IO[bytes]', packet: 'dict[str, Any]') -> '_T': # A shortfall no larger than :data:`~pcapkit.utilities.config.MAX_ZERO_PAD_SHORTFALL` is padded # without consulting the budget, and is not charged to it either. That is - # the load-bearing half of this fix rather than a concession in it: it is + # load-bearing rather than a concession: it is # what keeps the answer a function of *this* read rather than of # everything read before it. No shortfall a 16-bit wire length can produce # -- which is every shortfall a snapshot-truncated capture, a truncated @@ -502,8 +503,8 @@ def unpack(self, buffer: 'bytes | IO[bytes]', packet: 'dict[str, Any]') -> '_T': # not tallied against it. A snapshot-truncated capture of offload-sized # frames pads some 935 octets for every octet it reads, all of it in this # band; charging that to the same ledger would exhaust it within a few - # frames and refuse the next large shortfall -- reintroducing exactly the - # history-dependence the band exists to remove. + # frames and refuse the next large shortfall -- making the answer depend on + # history, which is exactly what the band exists to prevent. shortfall, ratio = config.MAX_ZERO_PAD_SHORTFALL, config.ZERO_PAD_BUDGET_RATIO if shortfall != -1 and padding > shortfall: # NOTE: ``-1`` for either term of the allowance lifts the budget. diff --git a/pcapkit/corekit/fields/misc.py b/pcapkit/corekit/fields/misc.py index 5356f65455..12cafdaf60 100644 --- a/pcapkit/corekit/fields/misc.py +++ b/pcapkit/corekit/fields/misc.py @@ -80,8 +80,7 @@ class ConditionalField(FieldBase[_TC]): Args: field: Field instance. condition: Field condition function (this function should return a bool - value and accept the current packet :class:`pcapkit.corekit.infoclass.Info` - as its only argument). + value and accept the current packet data as its only argument). """ @@ -572,9 +571,8 @@ def nested_packet_context(packet: 'dict[str, Any]') -> 'dict[str, Any]': declare a given field -- see :func:`pcapkit.corekit.fields.byteorder.packet_byteorder` and :meth:`~pcapkit.protocols.schema.misc.pcapng.BlockType.post_process` - for why that distinction matters, and note that both already - hand-roll this exact fallback and so are unaffected by (and do not - need to route through) this function. + for why that distinction matters; both hand-roll this exact fallback + themselves rather than route through this function. Nothing written through the returned mapping reaches ``packet``, because the returned mapping *is* a copy: a nested schema can set -- @@ -602,22 +600,22 @@ def nested_packet_context(packet: 'dict[str, Any]') -> 'dict[str, Any]': :class:`~abc.ABCMeta` at all because :class:`dict` is not an :class:`~abc.ABCMeta`-based class. That also settles a suspicion, raised on :issue:`439`, that a :class:`~collections.ChainMap` here - corrupted the :class:`~abc.ABCMeta` cache :class:`Schema + would corrupt the :class:`~abc.ABCMeta` cache :class:`Schema ` subclasses shared on CPython <= 3.10. The suspicion is *probably* wrong, and this code cannot test it: the cache keys on the **exact type queried**, so asking about a :class:`~collections.ChainMap` instance caches lookups for :class:`~collections.ChainMap` and not for :class:`dict`, the poisoning observed in :issue:`439` came from ordinary code asking - :func:`isinstance` about a plain :class:`dict`, and :issue:`439` has - been fixed directly -- every :class:`~pcapkit.protocols.schema.schema.Schema` subclass gets its own - ``_abc_impl``. Against that, swapping the ``ChainMap`` for a plain - literal on CPython 3.10 once moved + :func:`isinstance` about a plain :class:`dict`, and :issue:`439` is + fixed directly -- every :class:`~pcapkit.protocols.schema.schema.Schema` subclass gets its own + ``_abc_impl``. Against that, on CPython 3.10 choosing between a + ``ChainMap`` and a plain literal here was observed to flip ``test_pcapng_remaining_constructor_branches_and_custom_dispatch`` - between passing and failing, both ways; the likeliest reading is that - it changed which types flowed through unrelated :func:`isinstance` - calls rather than causing the corruption. It does not affect - correctness either way. + between passing and failing, in both directions; the likeliest reading + is that the choice changes which types flow through unrelated + :func:`isinstance` calls rather than causing the corruption. It does + not affect correctness either way. """ return {**packet, '__packet__': packet} diff --git a/pcapkit/corekit/fields/numbers.py b/pcapkit/corekit/fields/numbers.py index d63c4f3264..83a81540b4 100644 --- a/pcapkit/corekit/fields/numbers.py +++ b/pcapkit/corekit/fields/numbers.py @@ -1068,8 +1068,7 @@ def pre_process(self, value: 'int | AppType', packet: 'dict[str, Any]') -> 'int """ # NOTE: imported here rather than at module level, as # :mod:`pcapkit.const` itself imports :mod:`pcapkit.corekit`; and tested - # against AppType rather than ``self._namespace``, as the - # per-transport copies this class replaced did (#1516). + # against AppType rather than ``self._namespace`` (#1516). from pcapkit.const.reg.apptype import AppType # pylint: disable=import-outside-toplevel if isinstance(value, AppType): diff --git a/pcapkit/corekit/fields/strings.py b/pcapkit/corekit/fields/strings.py index a3ee132b1e..cd22e7267a 100644 --- a/pcapkit/corekit/fields/strings.py +++ b/pcapkit/corekit/fields/strings.py @@ -177,7 +177,7 @@ def pre_process(self, value: 'str', packet: 'dict[str, Any]') -> 'bytes': # pyl # NOTE: A negative length is resolved from the *encoded* octets, not from # the character count -- the ``Ns`` template counts octets, so counting - # characters truncated any text that does not encode one octet per + # characters would truncate any text that does not encode one octet per # character. if self._length < 0: self._length = len(buffer) diff --git a/pcapkit/corekit/infoclass.py b/pcapkit/corekit/infoclass.py index 9026cfebcd..b640616d20 100644 --- a/pcapkit/corekit/infoclass.py +++ b/pcapkit/corekit/infoclass.py @@ -177,8 +177,8 @@ def info_final(cls: 'ST', *, _finalised: 'bool' = True) -> 'ST': # contributes only the annotations it declares itself, on every # Python version: below 3.10 (bpo-43901), ``__annotations__`` of a # class declaring none is its nearest base's, so a field-less - # subclass read Info's ``__finalised__``, ``__additional__`` and - # ``__excluded__`` as its fields (#1692). See + # subclass would read Info's ``__finalised__``, ``__additional__`` + # and ``__excluded__`` as its fields (#1692). See # :func:`~pcapkit.utilities.compat.get_annotations`. for key in reversed(get_annotations(cls_)): # NOTE: We skip duplicated annotations to avoid duplicate @@ -283,8 +283,8 @@ class C(B): __additional__ = ['e', 'f'] print(A.__additional__) # ['a', 'b'] - print(B.__additional__) # ['a', 'b', 'c', 'd'] - print(C.__additional__) # ['a', 'b', 'c', 'd', 'e', 'f'] + print(B.__additional__) # ['c', 'd', 'a', 'b'] + print(C.__additional__) # ['e', 'f', 'c', 'd', 'a', 'b'] """ @@ -479,8 +479,8 @@ class is finalised on its first construction, whatever its # ``info_final`` writes ``BASE`` or ``FINAL`` onto the class it # finalises, and a subclass reading that state through inheritance was # never finalised itself -- it would keep the ``__excluded__`` it copied - # at declaration, without the names ``info_final`` adds, which once - # leaked ``__map__``, ``__map_reverse__`` and ``__multi__`` from + # at declaration, without the names ``info_final`` adds, which would + # leak ``__map__``, ``__map_reverse__`` and ``__multi__`` from # ``to_dict()`` (GitHub issue #1490). The inner one: an ancestor hand-marked bare # ``@final`` passes its marker to every subclass declared before it # landed, and ``getattr`` would blame such a subclass for a mismarking @@ -814,9 +814,9 @@ class _OrderedMultiDict(OrderedMultiDict[KT, VT]): :mod:`~pcapkit.corekit.multidict` classes are Werkzeug's, kept verbatim, and Werkzeug's :class:`~pcapkit.corekit.multidict.OrderedMultiDict` defines ``__eq__`` but no ``__ne__``: ``!=`` falls back to :obj:`dict`'s, - which compares the internal buckets, so two equal exports compared + which compares the internal buckets, so two equal exports would compare ``!=`` as well as ``==`` -- and, since ``__eq__`` compares the values with - ``!=``, two exports holding a nested export compared unequal + ``!=``, two exports holding a nested export would compare unequal (:issue:`1484`). Its copies, deep copies and pickles stay of this class, as Werkzeug's build them from ``type(self)``, and :meth:`__repr__` writes it as the :class:`~pcapkit.corekit.multidict.OrderedMultiDict` it is. @@ -1019,8 +1019,8 @@ class MultiInfo(_MultiInfo[KT, VT], MultiDict[KT, VT]): def __eq__(self, other: 'object') -> 'bool': # NOTE: MultiDict's ``__eq__`` is :obj:`dict`'s, which compares the # internal storage, so against an OrderedMultiDict -- whose values sit - # in buckets -- it answered False where the OrderedMultiDict, asked the - # other way round, answered True. The ordered side decides, as it does + # in buckets -- it answers False where the OrderedMultiDict, asked the + # other way round, answers True. The ordered side decides, as it does # for a bare MultiDict, which Python asks it first for being its # subclass (#1484). if isinstance(other, OrderedMultiDict): @@ -1091,8 +1091,8 @@ class OrderedMultiInfo(_MultiInfo[KT, VT], OrderedMultiDict[KT, VT]): # NOTE: as for :class:`MultiInfo`, the mapping protocol is bound back to # OrderedMultiDict's own. ``__ne__`` is not: OrderedMultiDict has none, and - # dict's compares the internal buckets, so two equal option lists compared - # ``!=`` as well as ``==``. It is :func:`_ne`, as for the exports + # dict's compares the internal buckets, so two equal option lists would + # compare ``!=`` as well as ``==``. It is :func:`_ne`, as for the exports # (#1484). __getitem__ = OrderedMultiDict.__getitem__ # type: ignore[assignment] __iter__ = OrderedMultiDict.__iter__ # type: ignore[assignment] diff --git a/pcapkit/corekit/io.py b/pcapkit/corekit/io.py index a9da1623a0..f3a07ced12 100644 --- a/pcapkit/corekit/io.py +++ b/pcapkit/corekit/io.py @@ -220,7 +220,7 @@ def _fill(self, size: 'int', minimum: 'Optional[int]' = None, /, *, One read may return fewer octets than asked for at any point -- a pipe hands over what has been written so far, a raw stream what one system call returned -- and only an empty one means the stream has ended. Taking the first answer - for all there is ended a capture at a chunk boundary (:issue:`1586`), so this + for all there is would end a capture at a chunk boundary (:issue:`1586`), so this reads until ``minimum`` octets are in hand. Past that it does not wait: ``read1``, where the stream has it, returns what is already there. A non-blocking stream's :obj:`None` stops the reading. No one read asks for @@ -338,7 +338,7 @@ def _take_buffer(self, size: 'int', /, *, line: 'bool' = False) -> 'bytes': :meth:`io.BytesIO.read`, ``read1`` or ``readline``. On GraalPy those can hand back :obj:`bytes` that share the memory of a :class:`io.BytesIO` whose buffer is exported, as this one's is, so the next :meth:`_write_buffer`, which writes - through the view, changed octets that had already been returned + through the view, would change octets that had already been returned (:issue:`1963`). A slice of the view, copied, is a copy on every interpreter. """ diff --git a/pcapkit/corekit/sentinels.py b/pcapkit/corekit/sentinels.py index eea62b1fdd..3a753fe554 100644 --- a/pcapkit/corekit/sentinels.py +++ b/pcapkit/corekit/sentinels.py @@ -382,9 +382,9 @@ def __bool__(self) -> 'Literal[False]': def _get_null() -> 'NullType': """Return :data:`NULL`, for a pickle written before :issue:`1842`. - ``NullType.__reduce__`` used to name this function, so such a pickle - calls it to load. Nothing here calls it any more; it stays so that those - pickles keep loading, as :data:`NULL` itself. + Such a pickle of :data:`NULL` names this function, so loading one calls + it. Nothing in the package calls it; it exists so that those pickles keep + loading, as :data:`NULL` itself. """ return NULL diff --git a/pcapkit/vendor/__main__.py b/pcapkit/vendor/__main__.py index a85cfe46cf..a0f1d5fa84 100644 --- a/pcapkit/vendor/__main__.py +++ b/pcapkit/vendor/__main__.py @@ -72,8 +72,8 @@ def _snapshot_and_restore(vendor: 'Type[Vendor]') -> 'Iterator[None]': If that resolution fails -- a crawler outside the real :mod:`pcapkit.vendor` tree, such as a test double, or one whose ``_dest_path`` genuinely cannot be resolved without instance state -- - the snapshot is skipped and ``vendor()`` runs unprotected, exactly as it - always did; not being able to *name* the file is not itself a reason to + the snapshot is skipped and ``vendor()`` runs unprotected; not being able + to *name* the file is not itself a reason to fail the target. The two triggers diverge from there. A crawler outside the real tree fails loudly anyway: :meth:`Vendor.__init__` calls the exact same ``_dest_path`` on itself and hits the exact same resolution @@ -111,7 +111,7 @@ def _snapshot_and_restore(vendor: 'Type[Vendor]') -> 'Iterator[None]': here restores the file the symlink pointed at), ``link.py`` is a regular file holding the backup's content, and ``os.path.islink(link.py)`` is :data:`False`. ``find pcapkit/const - -type l`` is still empty, so this remains latent. + -type l`` is empty, so this is latent. Nothing is copied at all when the destination does not exist yet: there is no previous file for a failure to discard, so there is nothing this @@ -154,12 +154,12 @@ def _snapshot_and_restore(vendor: 'Type[Vendor]') -> 'Iterator[None]': # pick: collapsing it into an unindented statement after this whole # `try` makes "cleanup only runs on success" a fact that has to be # re-derived from "`raise` never falls through", rather than one the - # structure states directly -- and it silently stopped being true the moment - # someone deleted that `raise`. A mutation test proved it: with the + # structure states directly -- and it would silently stop being true the + # moment someone deleted that `raise`. A mutation test showed it: with the # `raise` gone, the unindented `os.remove(backup)` still ran, after # `os.replace` had already renamed the backup away, so it raised - # FileNotFoundError instead of the crawler's real error -- and every - # existing test still passed, because run() catches that too. + # FileNotFoundError instead of the crawler's real error -- and the rest + # of the suite passed regardless, because run() catches that too. os.replace(backup, const_file) raise else: diff --git a/pcapkit/vendor/default.py b/pcapkit/vendor/default.py index 097a9e773c..cde5ed205e 100644 --- a/pcapkit/vendor/default.py +++ b/pcapkit/vendor/default.py @@ -325,7 +325,7 @@ def split_references(text: 'str') -> 'list[str]': ``RFC-ietf-tcpm-accurate-ecn-34`` are left as they are. Any other segment, including text outside the brackets, is returned - verbatim and in order, as :func:`re.split` on the brackets alone did. + verbatim and in order, as :func:`re.split` on the brackets alone gives it. Args: text: Raw reference cell. @@ -574,11 +574,10 @@ def _dest_path(cls) -> 'str': raising. So the escape is rejected outright, rather than trusted to produce a harmless-looking wrong path. - This is a classmethod, not an instance method, deliberately: nothing - in the body ever needed instance state -- it only ever consulted - ``type(self)``, so ``cls`` is exactly that, with no instance required - to obtain it. That lets a caller resolve a crawler's destination - *without* instantiating it, and so without triggering + This is a classmethod, not an instance method, deliberately: the body + needs no instance state, only the crawler's class, which ``cls`` is + with no instance required to obtain it. That lets a caller resolve a + crawler's destination *without* instantiating it, and so without triggering :meth:`Vendor.__init__`'s network fetch, render and write -- the pre-run snapshot that ``run()`` in :mod:`pcapkit.vendor.__main__` takes (GitHub issue :issue:`872`) is exactly such a caller. Every crawler defined in this @@ -742,10 +741,10 @@ def _request(self) -> 'list[str]': # NOTE: whatever stopped the prompt, ``input()`` is no # longer waiting -- and this loop only waits because # ``input()`` does, so the file it waits for can never - # arrive. Discarding the exception, as this used to, - # left a ``while True`` that printed three lines per - # iteration at full speed: 26.7 million lines and 2.6 GB - # measured in #522. The terminal this started on can + # arrive. Discarding the exception would leave a + # ``while True`` printing three lines per iteration at + # full speed: 26.7 million lines and 2.6 GB measured in + # #522. The terminal this started on can # still go away mid-wait -- a closed ``stdin`` raises # :exc:`ValueError`, a dropped one :exc:`EOFError`, a # vanished :data:`sys.stdin` :exc:`RuntimeError` -- so the diff --git a/pcapkit/vendor/ftp/command.py b/pcapkit/vendor/ftp/command.py index f385a4cd48..47eae9441d 100644 --- a/pcapkit/vendor/ftp/command.py +++ b/pcapkit/vendor/ftp/command.py @@ -83,7 +83,7 @@ class FEATCode(EnumRegistry, StrEnum): turns up on the wire but names none of these -- the extendability the owner conditionally asked to keep on GitHub issue :issue:`860`: unsure what a FEAT value absent from the RFC's list means in the CSV table, the owner - said that if the expected handling is our current approach, as industry + said that if the expected handling is this registry's approach, as industry convention has it, the registry stays extendable as is, and then approved declaring the registry's keywords as real members with ``_missing_`` still covering the rest. No custom ``__new__`` here, so the base's @@ -132,7 +132,7 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'FEATCode': recommendation, while some of this registry's codes are registered in lower case -- measured on the IANA CSV: ``base``, ``feat``, ``hist``, ``nat6`` and ``secu``, against all-upper-case keywords for the rest, - with none mixed. Without this override ``get('BASE')`` raised + with none mixed. Without this override ``get('BASE')`` raises :exc:`KeyError`, which is the defect GitHub issue :issue:`903`'s audit found. The obvious objection, answered: :rfc:`5797` uses case *presentationally* @@ -153,9 +153,9 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'FEATCode': own precedence -- name before value -- and its non-minting ``str`` path both survive: nothing here calls ``cls(key)``, so a key matching no member, folded or not, still raises rather than growing the - registry. ``get('ZZ-NOT-REAL')`` therefore still raises - :exc:`KeyError` while ``FEATCode('ZZ-NOT-REAL')`` still yields an - unregistered member, exactly as before. + registry. ``get('ZZ-NOT-REAL')`` therefore raises + :exc:`KeyError` while ``FEATCode('ZZ-NOT-REAL')`` yields an + unregistered member. Args: key: Name or value to look up. A non-``str`` key is passed @@ -226,12 +226,11 @@ def _missing_(cls, value: 'str') -> 'FEATCode': class CommandType(EnumLookup, IntFlag): """Type of "kind" of command, based on :rfc:`959#section-4`. - Re-parented onto :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub - issue :issue:`930`, finishing :issue:`877`'s phase 2. Pure re-parenting as far as - ``get``/``get_all`` are concerned -- this class defines no ``get`` of its - own to reconcile with the base -- and its own :meth:`_missing_` range - guard below is untouched, since :class:`~pcapkit.corekit.enum.EnumLookup` does not touch that - hook. + Built on :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub issue + :issue:`930`, which finished :issue:`877`'s phase 2. This class defines no + ``get`` of its own, so ``get``/``get_all`` are the base's, and its own + :meth:`_missing_` range guard below stands as written, since + :class:`~pcapkit.corekit.enum.EnumLookup` does not touch that hook. """ @@ -260,10 +259,9 @@ def _missing_(cls, value: 'int') -> 'CommandType': class ConformanceRequirement(EnumLookup, IntEnum): """Expectation for support in modern FTP implementations. - Re-parented onto :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub - issue :issue:`930`, finishing :issue:`877`'s phase 2 -- pure re-parenting, since this - class defines neither ``get`` nor ``_missing_`` of its own to reconcile - with the base. + Built on :class:`~pcapkit.corekit.enum.EnumLookup` per GitHub issue + :issue:`930`, which finished :issue:`877`'s phase 2. This class defines + neither ``get`` nor ``_missing_`` of its own. """ @@ -445,8 +443,7 @@ def get(cls, key: 'str', default: 'Optional[str]' = None) -> '{NAME}': """ if not isinstance(key, str): # NOTE: unreachable only by the ``str`` annotation, which a caller - # at run time need not honour -- this is the path GitHub issue - # #1824 fixed. + # at run time need not honour (GitHub issue #1824). return super().get(key) # type: ignore[unreachable] name = key.upper() if name not in cls._member_map_: # pylint: disable=no-member @@ -454,14 +451,13 @@ def get(cls, key: 'str', default: 'Optional[str]' = None) -> '{NAME}': # else ``key`` exactly as given -- never ``name`` -- so an # unregistered member's value is the caller's own casing, the # same convention :meth:`_unregistered_member` documents and - # :class:`~pcapkit.const.ftp.command.FEATCode` already followed + # :class:`~pcapkit.const.ftp.command.FEATCode` follows # unchanged. Two calls naming the same command in different # case, e.g. ``get('xyzw')`` and ``get('XYZW')``, therefore build # results that are *not* equal -- each is exactly what its own - # caller passed. Minting instead returned, through the + # caller passed. Minting instead would return, through the # ``_member_map_`` cache, the *first* casing seen for every later - # call regardless of case; that is the one observable behaviour - # change in GitHub issue #860's conversion. + # call regardless of case (GitHub issue #860). return cls._unregistered_member(default if default is not None else key, name) return cls._member_map_[name] # pylint: disable=no-member @@ -523,9 +519,9 @@ def process(self, data: 'list[str]') -> 'tuple[list[str], list[str]]': :class:`Command`'s enumeration fields, and every distinct per-command keyword the ``FEAT code`` column names -- :class:`~pcapkit.const.ftp.command.FEATCode` must declare these as real members (GitHub - issue :issue:`860`), rather than the old approach of minting one as an - incidental side effect the first time a :class:`Command` row - referencing it was evaluated at import time. + issue :issue:`860`), rather than minting one as an incidental side + effect the first time a :class:`Command` row referencing it is + evaluated at import time. """ reader = csv.reader(data) diff --git a/pcapkit/vendor/ftp/return_code.py b/pcapkit/vendor/ftp/return_code.py index fe3afb86b4..4163b85b67 100644 --- a/pcapkit/vendor/ftp/return_code.py +++ b/pcapkit/vendor/ftp/return_code.py @@ -321,9 +321,9 @@ def process(self, soup: 'BeautifulSoup') -> 'list[str]': # type: ignore[overrid # NOTE: MediaWiki renders a trailing ``|-`` row separator in the # wikitext as an empty ````, which revision # 1354125851 of the article carries at the end of this table. It has - # no cells at all, so reading ``line[0]`` raised ``IndexError`` and - # took the whole crawler down. Skipping cell-less rows is the fix - # rather than indexing defensively further down, because a row that + # no cells at all, so reading ``line[0]`` would raise ``IndexError`` + # and take the whole crawler down. Cell-less rows are skipped + # rather than indexed defensively further down, because a row that # cannot supply both a code and an explanation has nothing to # contribute either way; see #518. if len(line) < 2: diff --git a/pcapkit/vendor/http/method.py b/pcapkit/vendor/http/method.py index e126123254..5262213224 100644 --- a/pcapkit/vendor/http/method.py +++ b/pcapkit/vendor/http/method.py @@ -184,13 +184,13 @@ def get(cls, key: 'str', default: 'Optional[str]' = None) -> '{NAME}': # else ``key`` exactly as given -- never its upper-cased form -- # so an unregistered member's value is the caller's own casing, # the same convention :meth:`_unregistered_member` documents and - # :class:`~pcapkit.const.ftp.command.FEATCode` already followed. + # :class:`~pcapkit.const.ftp.command.FEATCode` follows. # The name is always the canonical upper-case form, matching # :meth:`_missing_` and every registered member's own name. Two # calls naming the same method in different case, e.g. # ``get('frob')`` and ``get('FROB')``, therefore build results # that are *not* equal -- each is exactly what its own caller - # passed, per GitHub issue #860's conversion away from minting. + # passed, since ``get`` does not mint (GitHub issue #860). return cls._unregistered_member(default if default is not None else key, key.upper()) @classmethod diff --git a/pcapkit/vendor/ipx/socket.py b/pcapkit/vendor/ipx/socket.py index ab2078fd64..469f9b9ea4 100644 --- a/pcapkit/vendor/ipx/socket.py +++ b/pcapkit/vendor/ipx/socket.py @@ -256,11 +256,11 @@ #: fix for :issue:`841`, is whether a label is the final concrete assigned name or only #: a notation for readers; the ruling on :issue:`775` kept ``Registered by Xerox`` out #: of this set on that test, because a proprietary protocol may expose no name -#: of its own, so the company name serves as its name. :issue:`775`'s final round -#: converts it too, so this set does not decide *whether* a range registers -- -#: only *how its name is spelled*: these keep the bare label with no hex -#: suffix, since the label itself already says nothing was assigned, while -#: ``Registered by Xerox`` keeps the hex-suffixed name it always rendered. +#: of its own, so the company name serves as its name. :issue:`775` settled on +#: an unregistered member for that range too, so this set does not decide +#: *whether* a range registers -- only *how its name is spelled*: these keep the +#: bare label with no hex suffix, since the label itself already says nothing +#: was assigned, while ``Registered by Xerox`` keeps a hex-suffixed name. UNASSIGNED_RANGE_NAMES = frozenset({ 'Experimental', 'Dynamically Assigned Socket Numbers', @@ -318,7 +318,7 @@ def process(self, data: 'dict[int, tuple[str, str]]') -> 'tuple[list[str], list[ # NOTE: the range names are emitted raw, spaces and all, rather than # through ``safe_name``, because that is what the scrape did and what # the shipped constant file contains; sanitising them here would rename - # every member ``_missing_`` extends the enumeration with; see #507. + # every member ``_missing_`` builds for a range; see #507. for start, stop, name in RANGES: miss.append(f'if 0x{start:04X} <= value <= 0x{stop:04X}:') miss.append(f' #: {self.wrap_comment(name)}') diff --git a/pcapkit/vendor/reg/apptype/apptype.py b/pcapkit/vendor/reg/apptype/apptype.py index f4b29ef8c5..193be0cdf8 100644 --- a/pcapkit/vendor/reg/apptype/apptype.py +++ b/pcapkit/vendor/reg/apptype/apptype.py @@ -132,42 +132,35 @@ class TransportProtocol(EnumLookup, IntEnum): # ever ships type stubs letting it infer TransportProtocol on its own, # these casts start erroring instead of lingering as dead scaffolding. # - # Values are sequential from 0 rather than the power-of-two spacing this - # class carried while it still mixed in ``IntFlag`` -- ``undefined`` is - # declared explicitly as ``0`` and every other member is ``auto()``, which - # continues from the preceding explicit value rather than needing its own - # ``_start_ = 0`` to begin there. A ruling given in review of the work for - # #860 is explicit that ``undefined`` stays a direct ``0`` for that reason: - # the other, real transports use ``auto()``, so no ``_start_`` has to be - # defined and the declaration of ``undefined`` stays explicit. GitHub issue - # #808 already dropped the ``IntFlag`` base once nothing built a composite, - # and a ruling given in review of that work later retired ``|``-composite - # decoding entirely: once it is no longer a Flag, a ``|``-joined value is no - # longer parsed and accepted as a composite, and is treated as a whole - # instead of being split. With no decoding left to protect, the owner's own - # further ruling on GitHub issue #860 retired the power-of-two spacing - # itself too: that spacing existed mainly for code that composed values like - # ``tcp | udp``, which the whole-value lookup does not accept, so sequential - # ``auto()`` values are the expected behaviour. :meth:`AppType._dispatch` - # never decodes an ``int`` -- composed by hand with ``|`` or passed bare -- - # into anything narrower than the whole value it already is, on either - # numbering; a plain ``dict.get`` lookup cannot tell a composed ``int`` from - # any other one that happens to equal it. Treating every int as a whole is - # exactly what that ruling above asks for, and it is also why this - # renumbering changes what specific ints mean, not only what composed ones - # do: ``tcp | udp`` (``3``) used to name no registry and resolves as - # ``sctp``'s own value, and a bare, uncomposed ``4`` -- previously - # ``sctp``'s value -- resolves as ``dccp``'s, silently, with no - # exception, since a real member sits at ``4`` either way. A caller holding - # an integer under the old spacing (composed or not) can therefore land on a - # different real transport's registry under the sequential numbering, not - # merely be refused where it previously resolved. + # Values are sequential from 0: ``undefined`` is declared explicitly as + # ``0`` and every other member is ``auto()``, which continues from the + # preceding explicit value rather than needing its own ``_start_ = 0`` to + # begin there. A ruling given in review of the work for #860 is explicit + # that ``undefined`` stays a direct ``0`` for that reason: the other, real + # transports use ``auto()``, so no ``_start_`` has to be defined and the + # declaration of ``undefined`` stays explicit. The class is an ``IntEnum`` + # rather than an ``IntFlag`` (GitHub issue #808), and a ruling given in + # review of that work treats a ``|``-joined value as a whole rather than + # parsing it as a composite. With no composite decoding to serve, the + # owner's further ruling on GitHub issue #860 makes the values sequential + # rather than powers of two: that spacing existed mainly for code that + # composed values like ``tcp | udp``, which the whole-value lookup does not + # accept. :meth:`AppType._dispatch` never decodes an ``int`` -- composed by + # hand with ``|`` or passed bare -- into anything narrower than the whole + # value it already is; a plain ``dict.get`` lookup cannot tell a composed + # ``int`` from any other one that happens to equal it. So ``tcp | udp`` + # (``3``) resolves as ``sctp``'s own value, silently, with no exception. + # Before 1.5.0 the class was an ``IntFlag`` with ``sctp`` at ``4`` and + # ``dccp`` at ``8``, so an integer held from that numbering (composed or + # not) can land on a different real transport's registry rather than + # merely be refused: a bare ``4`` resolves as ``dccp``'s. #: No transport protocol. ``TransportProtocol(0) is undefined`` and #: ``bool(undefined)`` is ``False``; it is the ``proto`` sentinel default #: for ``__transport__``, ``__new__``, ``get`` and ``get_all``. The base - #: registry's ``_missing_`` answered its unassigned and reserved spans with - #: it until :issue:`2048`; they answer with the asking registry's transport. + #: registry's ``_missing_`` does not answer with it: its unassigned and + #: reserved spans answer with the asking registry's transport + #: (:issue:`2048`). undefined = cast('TransportProtocol', 0) #: Transmission Control Protocol. @@ -186,20 +179,19 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco Delegates to :meth:`~pcapkit.corekit.enum.EnumLookup.get` for GitHub issue :issue:`877`'s re-parenting, but keeps this override rather than dropping it, for one behaviour the base does not reproduce on its own: **case - folding**. This class has always matched a name case-insensitively + folding**. This class matches a name case-insensitively (``key.lower()``); the base's own ``str`` branch is case-sensitive. Lowering ``key`` before delegating reproduces that: every member name here is already lower-case, so a lowered ``key`` still hits the base's exact ``_member_map_`` lookup. - Case folding is the *only* thing this override adds. It used to - convert the base's name-miss exception as well -- this class raised - :exc:`ValueError` where the base raised :exc:`KeyError` -- and the - ruling given in review of the work for :issue:`877`, implemented in GitHub issue - :issue:`923`, retired that conversion: the exception is to follow what stdlib's - ``Enum`` would raise in the circumstances, :exc:`ValueError` or - :exc:`KeyError` as the case may be, and is to come from - :mod:`pcapkit.utilities.exceptions` rather than being a builtin. A + Case folding is the *only* thing this override adds. It does not + convert the base's name-miss exception: the ruling given in review of + the work for :issue:`877`, implemented in GitHub issue :issue:`923`, is + that the exception follows what stdlib's ``Enum`` would raise in the + circumstances, :exc:`ValueError` or :exc:`KeyError` as the case may + be, and comes from :mod:`pcapkit.utilities.exceptions` rather than + being a builtin. A stdlib ``E['nosuch']`` raises :exc:`KeyError`, and :issue:`923`'s census found :class:`~pcapkit.corekit.enum.EnumLookup` subclasses answering a name miss that way. The exceptions were :class:`AppType` and its @@ -209,31 +201,29 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco preserve, and a name miss reaches the caller as :exc:`~pcapkit.utilities.exceptions.EnumKeyError` from the base. The maintainer's ruling given in review of the work for :issue:`808`, that - :class:`TransportProtocol` is not to be extended at all, is untouched by - that: the refusal is still a refusal and still mints nothing, only its - exception class moved. + :class:`TransportProtocol` is not to be extended at all, holds either + way: the refusal is a refusal and mints nothing, whichever exception + class it raises. The base is a :class:`classmethod` - (:meth:`~pcapkit.corekit.enum.EnumLookup.get`), so this override - moves from :class:`staticmethod` to :class:`classmethod` to - delegate at all -- the same move GitHub issue :issue:`908` made for - :meth:`~pcapkit.const.http.method.Method.get`. A caller invoking it by - name sees no difference between the two; only code taking it as a bare - callable or introspecting ``__func__`` could tell them apart. - - ``default`` is accepted here because the original override had no - such parameter at all, which is a genuine LSP violation once this - class' ``get`` is a :class:`classmethod` override of one that has - it: a caller holding a :class:`~pcapkit.corekit.enum.EnumLookup`-typed - reference could pass ``default=`` and hit a :exc:`TypeError` at this + (:meth:`~pcapkit.corekit.enum.EnumLookup.get`), so this override is + one too, to delegate at all -- as + :meth:`~pcapkit.const.http.method.Method.get` is (GitHub issue + :issue:`908`). A caller invoking it by name cannot tell it from a + :class:`staticmethod`; only code taking it as a bare callable or + introspecting ``__func__`` could. + + ``default`` is accepted here because an override without it would be + a genuine LSP violation, this class' ``get`` being a + :class:`classmethod` override of one that has it: a caller holding a + :class:`~pcapkit.corekit.enum.EnumLookup`-typed reference could pass ``default=`` and hit a :exc:`TypeError` at this subclass. Forwarded verbatim to :meth:`~pcapkit.corekit.enum.EnumLookup.get` rather than reimplemented, so it behaves exactly as the base's own ``default`` does: a fallback to an *already-registered* value, resolved through ``_value2member_map_`` and never through the constructor, so - passing one still cannot mint. A call that omits it resolves exactly - as one made without the parameter did, so it is purely an added, - backward-compatible capability. + passing one cannot mint either. A call that omits it resolves as if + the parameter did not exist. Args: key: Key to get enum item. @@ -244,9 +234,8 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco Raises: EnumKeyError: If ``key`` names no member and there is no usable - ``default``. A :exc:`KeyError`, from the base, since GitHub - issue :issue:`923` -- it used to be a plain :exc:`ValueError` raised - here. + ``default``. A :exc:`KeyError`, from the base (GitHub issue + :issue:`923`). EnumValueError: If ``key`` is a value no member carries and there is no usable ``default``. A :exc:`ValueError`, from the base. @@ -254,30 +243,24 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco if isinstance(key, str): return super().get(key.lower(), default) # NOTE: the maintainer ruled in review of the work for #808 that - # TransportProtocol is not to be extended at all. A name that is not a - # declared member used to mint a brand-new one here, at ``max_val + 1`` - # (before that, ``max_val * 2``) -- an unbounded, ever-growing set of - # transport protocols nothing ever asked for. There is nothing left to walk: - # it is simply refused, exactly like any other unrecognised name -- - # including one spelling a composite, e.g. ``'tcp|udp'``. ``'|'`` used to be - # intercepted here on its own, so a composite in disguise never got minted - # into a member whose own name lied about being a single transport; a - # further ruling given in review of the work for #808 retired that special - # case along with the rest of the composite handling once TransportProtocol - # stopped being a Flag at all: a ``|``-joined value is no longer parsed and - # accepted as a composite, and is treated as a whole instead of being split. - # A ``'|'``-joined name is therefore not special any more -- it is simply - # not the name of a declared member, and gets the same message as any other - # one that is not. + # TransportProtocol is not to be extended at all, so a name that is not + # a declared member is refused rather than minted -- minting would grow + # an unbounded set of transport protocols nothing ever asked for. That + # includes one spelling a composite, e.g. ``'tcp|udp'``: a further + # ruling given in review of the work for #808 treats a ``|``-joined + # value as a whole rather than parsing it as a composite, so a + # ``'|'``-joined name is not special -- it is simply not the name of a + # declared member, and gets the same message as any other one that is + # not. # # NOTE: the delegation below is exception-compatible for the keys this - # signature admits -- an unrecognised :class:`int` still reaches the + # signature admits -- an unrecognised :class:`int` reaches the # caller as a :exc:`ValueError`, the base's own - # :exc:`~pcapkit.utilities.exceptions.EnumValueError` since GitHub issue - # #923 rather than ``aenum``'s bare one. It is not compatible for - # keys outside it: ``None``, a :class:`float` and an unhashable key - # raised :exc:`AttributeError` from ``key.lower()`` before the - # delegation, and raise :exc:`ValueError` through it (or, for a + # :exc:`~pcapkit.utilities.exceptions.EnumValueError` (GitHub issue + # #923) rather than ``aenum``'s bare one. It is not compatible for + # keys outside it: ``None``, a :class:`float` and an unhashable key, + # on which a ``key.lower()`` would raise :exc:`AttributeError`, raise + # :exc:`ValueError` through it (or, for a # :class:`float`, resolve -- ``get(1.0)`` answers ``tcp``, since # ``cls(key)`` accepts whatever :class:`int` equality accepts). No # caller inside :mod:`pcapkit` can reach any of those: the only live call @@ -285,16 +268,13 @@ def get(cls, key: 'int | str', default: 'Any' = NO_DEFAULT) -> 'TransportProtoco # what every other ``EnumLookup`` subclass does. return super().get(key, default) - # NOTE: ``_missing_`` used to range-check ``value`` and then defer to - # ``aenum``'s own ``Flag._missing_``, which is what composed an - # unrecognised bit combination into a pseudo-member -- ``TransportProtocol(3)`` - # returning ``tcp|udp`` -- GitHub issue #647's guard against that composing - # *anything*, including values no member declares. GitHub issue #808 removed - # the ``IntFlag`` base once nothing built a composite, and with it the only - # reason this method existed: a plain ``aenum.IntEnum`` already raises - # ``ValueError`` for a value no member declares, with no ``_missing_`` of - # its own needed to get there, so declaring one here would only be - # reproducing what the base class already does. + # NOTE: no ``_missing_`` is declared: a plain ``aenum.IntEnum`` already + # raises ``ValueError`` for a value no member declares. Under an + # ``IntFlag`` base, which this class is not (GitHub issue #808), + # ``Flag._missing_`` would compose an unrecognised bit combination into a + # pseudo-member -- ``TransportProtocol(3)`` returning ``tcp|udp`` -- and a + # range-checking ``_missing_`` would be needed to stop it composing + # *anything*, including values no member declares (GitHub issue #647). class {NAME}(EnumRegistry, StrEnum): @@ -343,8 +323,8 @@ class {NAME}(EnumRegistry, StrEnum): #: #: Declared here as :obj:`None` and overridden in each subclass: a mutable #: class attribute declared on this class would be *shared* by every - #: subclass, so they would collide with each other exactly as the ports of - #: one transport used to collide inside the old flat registry. + #: subclass, so every transport's ports would collide with each other in + #: one mapping. __registry__: 'Optional[MultiDict[int, {NAME}]]' = None #: Registry class owning each transport protocol, i.e. what @@ -418,11 +398,11 @@ def aliases(self) -> 'tuple[{NAME}, ...]': def __repr__(self) -> 'str': """Show the member as ````, listing its :attr:`aliases` before the closing bracket when it has any.""" - # NOTE: GitHub issue #807. The suffix below is the only difference from - # the plain form GitHub issue #806 already fixed: it is appended only + # NOTE: GitHub issue #807. The suffix below is the only addition to + # the plain form of GitHub issue #806: it is appended only # when :attr:`aliases` is non-empty, so every member that does not # share its port with another service -- the vast majority -- renders - # in the plain form unchanged. Registering a new alias through + # in the plain form. Registering a new alias through # :meth:`register_alias` changes what *every* member already on that # port renders, immediately, since :attr:`aliases` is derived fresh on # each call rather than fixed at construction. @@ -513,12 +493,11 @@ def _dispatch(cls, key: 'int', proto: 'TransportProtocol | str | int') -> 'Type[ delegate to. """ - # NOTE: this registry resolves ports, not service names. The old string - # branch tested ``key in __members_proto__``, which is keyed by transport - # protocol, so a name never matched and the miss path minted a brand-new - # member with port -1 -- GitHub issue #734's silent junk. Rejecting a - # non-port outright is the honest answer, and it has to happen before the - # miss path, which formats ``key`` into an f-string. + # NOTE: this registry resolves ports, not service names, so a non-port + # is rejected outright -- GitHub issue #734, where a name reached the + # miss path and minted a member with port -1, silent junk. Rejecting it + # is the honest answer, and it has to happen before the miss path, + # which formats ``key`` into an f-string. if not isinstance(key, int): raise ValueError(f'{{key!r}} is not a valid port number for {{cls.__name__}}') if cls.__registry__ is not None: @@ -534,43 +513,34 @@ def _dispatch(cls, key: 'int', proto: 'TransportProtocol | str | int') -> 'Type[ # cast is for mypy alone: ``dict.get`` accepts any hashable key at run # time regardless of its declared key type, but mypy holds ``.get`` to # the dict's own ``TransportProtocol`` keys, and does not know ``proto`` - # can genuinely be a bare :class:`int` here, since GitHub issue #808 - # dropped the ``IntFlag`` base -- see the annotation on ``proto`` above. + # can genuinely be a bare :class:`int` here, TransportProtocol not being + # an ``IntFlag`` (GitHub issue #808) -- see the annotation on ``proto`` + # above. subclass = cls.__registries__.get(cast('TransportProtocol', proto)) if subclass is not None: return subclass # NOTE: everything that reaches here has already failed to match a real # member's value at the dict lookup above, and nothing below decodes - # ``proto``'s bits looking for a partial answer either -- on either - # numbering. A genuine member reaching this point is ``undefined`` -- - # a real transport would already have resolved above, and - # :meth:`TransportProtocol.get` cannot mint anything else, per the - # maintainer ruling given in review of the work for #808, against - # extending TransportProtocol at all -- and a bare :class:`int` reaches - # here whenever it matches no real member's value, e.g. a stray bit like - # ``17``. A composite built by hand used to reach here just as reliably, - # since no combination of the old power-of-two bits ever equalled a - # single real member's value; that is not true under this class's - # sequential numbering -- + # ``proto``'s bits looking for a partial answer. A genuine member + # reaching this point is ``undefined`` -- a real transport would already + # have resolved above, and :meth:`TransportProtocol.get` cannot mint + # anything else, per the maintainer ruling given in review of the work + # for #808, against extending TransportProtocol at all -- and a bare + # :class:`int` reaches here whenever it matches no real member's value, + # e.g. a stray bit like ``17``. A composite built by hand need not: + # under the sequential numbering, # ``TransportProtocol.tcp | TransportProtocol.udp`` (``3``) is - # ``sctp``'s own value, so it resolves at the dict lookup above - # instead of reaching this point at all. A composite used to get its own - # :exc:`~pcapkit.utilities.exceptions.ProtocolError`, decoded through - # :func:`~pcapkit.utilities.compat.show_flag_values` and naming every - # transport whose bit was set -- the fix for GitHub issue #759, where - # resolving a composite by picking its lowest set bit dispatched every - # one containing ``tcp`` into the TCP registry regardless of what else - # it named. A further ruling given in review of the work for #808 - # retired that decoding along with the rest of the composite handling: - # once it is no longer a Flag, a ``|``-joined value is no longer parsed - # and accepted as a composite, and is treated as a whole instead of - # being split. So a composite's bits are never decoded looking for a - # partial answer any more, on either numbering -- it is looked up as the - # one whole value it already is, exactly like any int a caller might - # have written directly, and whether that whole value resolves or - # reaches this point depends only on whether some real member happens to - # equal it, never on whether a caller built it with ``|`` by hand. + # ``sctp``'s own value, so it resolves at the dict lookup above instead. + # A further ruling given in review of the work for #808 treats a + # ``|``-joined value as a whole rather than decoding it -- resolving a + # composite by picking its lowest set bit would dispatch every one + # containing ``tcp`` into the TCP registry regardless of what else it + # named, GitHub issue #759 -- so a composite is looked up as the one + # whole value it is, exactly like any int a caller might have written + # directly, and whether that whole value resolves or reaches this point + # depends only on whether some real member happens to equal it, never + # on whether a caller built it with ``|`` by hand. raise ValueError(f'{{proto!r}} names no transport protocol registry of ' f'{{cls.__name__}}') @@ -638,23 +608,21 @@ def get(cls, key: 'int', *, # type: ignore[override] # pylint: disable=argument return matched[0] # NOTE: :meth:`_missing_` answers :obj:`None` for a port it holds no row - # for -- GitHub issue #860 stopped that from minting, following the + # for, and that answer does not mint (GitHub issue #860), following the # owner's ruling there that ``get`` should not mint because it lacks the # information to create a new member: only IANA-registered values are # legitimate, and ``register`` is the proper way to add one. That ruling - # was given for the FEATCode, Command and Method branches, and this - # family was brought in line with it under the same issue. A port outside - # ``0..65535`` still *raises* rather than reaching here at all. Before - # #860, catching the ``None`` answer minted ``PORT_{{key}}_{{transport}}`` - # here directly -- GitHub issue #758's defect (it also minted for - # ``PORT_999999_tcp`` and ``PORT_-1_tcp``, the latter a name no attribute - # access could reach) -- and this was the second, independent mint site - # on this method, distinct from the one inside :meth:`_missing_` itself: - # neither is a value anyone asked to be named, so both build an - # unregistered member instead of registering one. A port IANA lists on - # other transports only is in no span on this one: 8011, reserved on - # TCP and ``bier-echo`` on UDP, answers ``unknown`` on DCCP and SCTP - # (#2048). + # was given for the FEATCode, Command and Method branches, and covers + # this family under the same issue. A port outside ``0..65535`` *raises* + # rather than reaching here at all. Minting on the ``None`` answer would + # name a member ``PORT_{{key}}_{{transport}}`` -- GitHub issue #758's + # defect, which also minted ``PORT_999999_tcp`` and ``PORT_-1_tcp``, the + # latter a name no attribute access could reach -- so, as inside + # :meth:`_missing_` itself, the port gets an unregistered member + # instead: neither is a value anyone asked to be named. A port IANA + # lists on other transports only is in no span on this one: 8011, + # reserved on TCP and ``bier-echo`` on UDP, answers ``unknown`` on DCCP + # and SCTP (#2048). ret = owner._missing_(key) if ret is None: ret = owner._unregistered_member(key, 'unknown', owner.__transport__) @@ -972,8 +940,8 @@ def _missing_(cls, value: 'int') -> 'Optional[{NAME}]': # GitHub issue #760, where source order decided instead and a UDP lookup in # 6000-6063 came back carrying ``tcp``. A registry a named span excludes # falls through to :meth:`_unregistered_member`, which is what IANA - # assigning it nothing means -- GitHub issue #860 stopped this from - # growing either lookup table or :data:`__registry__`, on the owner's + # assigning it nothing means, and grows neither lookup table nor + # :data:`__registry__` (GitHub issue #860), on the owner's # ruling there that only IANA-registered values are legitimate and a new # entry is properly created through ``register``; that ruling was given for # the FEATCode, Command and Method branches, and this family follows it. @@ -1051,8 +1019,8 @@ class Record(Info): Every field a merge has to grow is a container, appended to in place, because :class:`~pcapkit.corekit.infoclass.Info` refuses attribute assignment. That is - the right shape here anyway: the comment used to be accumulated by string - surgery, re-deriving from its own output whether it had been merged already. + the right shape here anyway: accumulating the comment by string surgery would + have to re-derive, from its own output, whether it had been merged already. """ @@ -1062,7 +1030,7 @@ class Record(Info): port: 'str' #: Transport protocol names carrying the service, normalised to a set. The #: registry repeats a transport across rows often enough that accumulating - #: the expression as text produced ``tcp | tcp | udp | udp``. + #: the expression as text would produce ``tcp | tcp | udp | udp``. protos: 'set[str]' #: Wrapped ``#:`` comment, one per merged registry row. parts: 'list[str]' @@ -1267,11 +1235,11 @@ def records(self, data: 'list[str]') -> 'tuple[OrderedDict[str, Record], list[st # NOTE: a span IANA assigns to a transport protocol is claimed by # that registry alone, through a test on ``cls.__transport__``. - # Source order decided instead until GitHub issue #760: the - # spans registered on more than one transport -- 6000-6063 and - # 6665-6669 -- rendered the same condition twice, leaving the - # second copy unreachable, so *every* registry answered with the - # first row's. That is not merely a duplicate to collapse: the + # Letting source order decide instead (GitHub issue #760) would + # render the same condition twice for the spans registered on + # more than one transport -- 6000-6063 and 6665-6669 -- leaving + # the second copy unreachable, so *every* registry would answer + # with the first row's. That is not merely a duplicate to collapse: the # 6665-6669 rows are two different services, ``ircu`` on TCP and # IANA's ``reserved`` marker on UDP, so one merged branch carrying # ``tcp | udp`` would have to discard one of them. @@ -1326,14 +1294,13 @@ def process(self, data: 'list[str]') -> 'tuple[list[str], list[str]]': # protocol and nothing else, so it names one transport rather # than the whole IANA set -- GitHub issue #806, and what makes # ``flag([self.TRANSPORT])`` below render a single name; the - # values are no longer bit-flags at all since GitHub issue #860 - # dropped the power-of-two spacing they used to need. Rendering - # ``record.protos`` here instead put the whole - # ``(service, port)`` IANA set on every member, which made - # ``TCP.http.proto`` name UDP and SCTP as well. That was a second - # copy of what the per-transport registries already encode, it is the copy - # that could drift, and being multi-bit it was refused by every - # entry point that consumed it. + # values are sequential rather than bit-flags (GitHub issue + # #860). Rendering ``record.protos`` here instead would put the + # whole ``(service, port)`` IANA set on every member, making + # ``TCP.http.proto`` name UDP and SCTP as well: a second copy of + # what the per-transport registries already encode, the copy that + # could drift, and, being multi-bit, one every entry point that + # consumed it would refuse. pres = f"{key} = {record.port}, {record.svc!r}, {self.flag([self.TRANSPORT])}" if len(record.parts) > 1: # NOTE: a merged entry describes each registry row it came from, diff --git a/pcapkit/vendor/reg/ethertype.py b/pcapkit/vendor/reg/ethertype.py index f9472ec4ad..ffe19b8be8 100644 --- a/pcapkit/vendor/reg/ethertype.py +++ b/pcapkit/vendor/reg/ethertype.py @@ -36,16 +36,16 @@ class EtherType(Vendor): #: carrying no real assignment -- a company holding the block but naming #: nothing (``DEC Unassigned``), or a range the list says is dead/invalid #: outright -- rather than a proprietary protocol's real name. The owner's - #: original ruling on :issue:`775`/:issue:`841` held these out as the only rows to - #: convert to + #: first ruling on :issue:`775`/:issue:`841` held these out as the only rows to + #: resolve to #: :meth:`~pcapkit.corekit.enum.EnumRegistry._unregistered_member`, on the #: theory that a proprietary protocol's company name IS - #: the final concrete name for every other row. :issue:`775`'s final round - #: converts every row alike, so this set does not decide *whether* a + #: the final concrete name for every other row. :issue:`775` settled on + #: resolving every row alike, so this set does not decide *whether* a #: row registers -- only *how its name is spelled*: these keep the #: bare label with no hex suffix, since the label itself already says - #: nothing was assigned, while every other row keeps the hex-suffixed - #: name it always rendered. + #: nothing was assigned, while every other row keeps a hex-suffixed + #: name. UNASSIGNED_ROW_NAMES = frozenset({ 'DEC Unassigned', 'Old Xerox Experimental values. Invalid as an Ethertype since 1983.', diff --git a/pcapkit/vendor/reg/linktype.py b/pcapkit/vendor/reg/linktype.py index b8760ded41..1705124f20 100644 --- a/pcapkit/vendor/reg/linktype.py +++ b/pcapkit/vendor/reg/linktype.py @@ -86,8 +86,8 @@ def process(self, data: 'list[Tag]') -> 'tuple[list[str], list[str]]': # through ``sink`` (see item 2 in #852), but its *expanded* values # still have to count here: a single-value row can legitimately # duplicate one of the values a range expands to, and missing that - # would silently under-count the duplicate the same way the - # word-only rule did before #852. + # would silently under-count the duplicate the same way a + # word-only rule would (#852). # # The single-value branch accepts whatever ``int()`` accepts -- # a leading sign, PEP 515 underscores -- rather than the narrower