Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,925 changes: 1,048 additions & 877 deletions pcapkit/const/reg/apptype/apptype.py

Large diffs are not rendered by default.

28 changes: 20 additions & 8 deletions pcapkit/corekit/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ class will do its necessary overrides and dispatching logic; AppType subclasses
:mod:`pcapkit.const` inherits them from here.
2. ``AppType``'s sub-base -- overrides all four to route through its
``_dispatch``, because a port lookup needs a transport protocol to be
answerable at all. Not in this module, and not yet written: today's
:class:`pcapkit.const.reg.apptype.apptype.AppType` carries that logic
directly and stays as it is until tier two lands.
answerable at all. Landed as of GitHub issue #860: not in this module, but
in :class:`pcapkit.const.reg.apptype.apptype.AppType` itself, which now
mixes in :class:`EnumRegistry` directly and overrides ``get``, ``get_all``,
``register`` and ``register_alias`` with that dispatch, plus
``_unregistered_member`` for its own three extra attributes (``svc``,
``port``, ``proto``) that the generic one below does not know to set.
3. The ``AppType`` transport subclasses -- ``TCP``, ``UDP``, ``SCTP``, ``DCCP``
-- override again for their own contracts.
-- turned out to need no override of their own at all: ``_dispatch``
already returns ``cls`` unchanged the moment ``cls.__registry__`` is not
:obj:`None`, which is true for exactly these four, so tier 2's methods
already answer correctly on each of them without a further layer.

Before this, the four methods lived as generated *text*: written out longhand in
:data:`pcapkit.vendor.default.LINE` and copied verbatim into each of the eleven
Expand Down Expand Up @@ -293,12 +299,18 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'Self':
unrecognised value, routing a failed *name* lookup through the
constructor would let a mere ``get()`` call mint a permanent member
where it previously just raised. Defensive rather than observed: of
the 119 classes that mix in this base, the ``str``-valued ones
the 124 classes that mix in this base, the ``str``-valued ones
(:class:`~pcapkit.const.ftp.command.Command`, :class:`~pcapkit.const.
ftp.command.FEATCode`, :class:`~pcapkit.const.http.method.Method`,
:class:`~pcapkit.const.pcapng.option_type.OptionType`) no longer mint
on any path as of GitHub issue #860, so no live witness exists in
this tree today. The registries that still mint directly via
:class:`~pcapkit.const.pcapng.option_type.OptionType`, and --
completing the count as of GitHub issue #860's own PR 2 --
:class:`~pcapkit.const.reg.apptype.apptype.AppType` and its four
transport subclasses :class:`~pcapkit.const.reg.apptype.tcp.TCP`,
:class:`~pcapkit.const.reg.apptype.udp.UDP`,
:class:`~pcapkit.const.reg.apptype.sctp.SCTP` and
:class:`~pcapkit.const.reg.apptype.dccp.DCCP`) no longer mint
on any path, so no live witness exists in this tree today. The
registries that still mint directly via
:func:`~aenum.extend_enum` --
:class:`~pcapkit.const.ipx.socket.Socket`,
:class:`~pcapkit.const.mh.cga_type.CGAType` and
Expand Down
413 changes: 298 additions & 115 deletions pcapkit/vendor/reg/apptype/apptype.py

Large diffs are not rendered by default.

177 changes: 138 additions & 39 deletions tests/const/test_const_apptype_split_unit.py

Large diffs are not rendered by default.

46 changes: 32 additions & 14 deletions tests/const/test_const_enum_builtin_parity.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,15 +635,18 @@ class ConstEnumRegisterFallbackTests(unittest.TestCase):
In the owner's words, the const enums used to mirror the built-in "with
one exception: they contain the missing then register fallback (mutable
enums)". :class:`~pcapkit.const.http.method.Method`,
:class:`~pcapkit.const.ftp.command.Command` and
:class:`~pcapkit.const.ftp.command.FEATCode` were, until GitHub issue
#860 step 2, the last three registries still living that divergence for
an *unrecognised* value (every numeric registry had already lost it
under #775/#847's ruling). The owner's #860 ruling retired it for these
three too, verbatim: *"I think we should not mint on get still
actually. For all three, only IANA registered ones are legit values and
we need register to properly create new entries. get will not have
sufficient information to create new ones."* Concretely,
:class:`~pcapkit.const.ftp.command.Command`,
:class:`~pcapkit.const.ftp.command.FEATCode` and
:class:`~pcapkit.const.reg.apptype.apptype.AppType` (with its four
transport subclasses) were, until GitHub issue #860 step 2, the last
registries still living that divergence for an *unrecognised* value
(every numeric registry had already lost it under #775/#847's ruling).
The owner's #860 ruling retired it for all of them, verbatim: *"I think
we should not mint on get still actually. For all three, only IANA
registered ones are legit values and we need register to properly
create new entries. get will not have sufficient information to create
new ones."* Stated for the three PR 1 converted, but the reasoning is
unconditional and PR 2 applies it to ``AppType`` identically. Concretely,
:class:`Command` needs :attr:`~pcapkit.const.ftp.command.Command.feat`/
:attr:`~pcapkit.const.ftp.command.Command.desc`/
:attr:`~pcapkit.const.ftp.command.Command.type`/
Expand Down Expand Up @@ -793,13 +796,28 @@ def test_protection_authority_now_resolves_without_extending(self) -> None:
with self.assertRaises(ValueError):
ProtectionAuthority(-1)

def test_apptype_still_registers_an_unassigned_port(self) -> None:
"""GitHub issue #584's machinery, which runs through ``_missing_``."""
def test_apptype_no_longer_registers_an_unassigned_port(self) -> None:
"""GitHub issue #584's machinery, which used to run through
``_missing_``'s fallthrough and :meth:`AppType.get`'s own second
mint site -- both retired by GitHub issue #860 step 2 PR 2, on the
same ruling this class's docstring quotes. Renamed from
``test_apptype_still_registers_an_unassigned_port``: 65000 is not in
any declared range, so this used to mint a permanent
``PORT_65000_tcp`` member every process keeps forever; it now
resolves to an equal-but-not-identical unregistered one instead,
the same shape as :meth:`test_a_string_registry_no_longer_
registers_an_unknown_name` above."""
from pcapkit.const.reg.apptype import AppType, TransportProtocol

registered = AppType.get(65000, proto=TransportProtocol.tcp)
self.assertEqual(int(registered), 65000)
self.assertIs(AppType.get(65000, proto=TransportProtocol.tcp), registered)
before = len(AppType.__registries__[TransportProtocol.tcp].__members__)
first = AppType.get(65000, proto=TransportProtocol.tcp)
after = len(AppType.__registries__[TransportProtocol.tcp].__members__)
second = AppType.get(65000, proto=TransportProtocol.tcp)

self.assertEqual(before, after, 'AppType.get(65000, ...) registered; see GitHub issue #860')
self.assertEqual(int(first), 65000)
self.assertEqual(first, second)
self.assertIsNot(first, second)

def test_transport_protocol_can_no_longer_be_extended_at_runtime(self) -> None:
"""Maintainer ruling on PR #836: extension refused, not renumbered.
Expand Down
Loading
Loading