4141:class:`EnumRegistry` subclasses outside :mod:`pcapkit.const`. The mutating half
4242therefore had no users to serve among the classes being re-parented.
4343
44- .. note::
45-
46- Re-parenting every non-registry enumeration onto :class:`EnumLookup` was
47- **phase 2** of GitHub issue :issue:`877`, and it is now **complete**:
48- introducing the base above was deliberately behaviour-preserving on its
49- own, so that it could land while other work was still in flight on the
50- files the re-parent touches, and the phase itself landed in two pull
51- requests for exactly that reason -- the first for the 17 enumerations that
52- were free to move at once, and the second, :issue:`930`, for the remaining
53- seven once the files holding them freed up.
54-
5544The registry tier's own shape is the earlier design settled in GitHub issue
5645:issue:`842`: ``get``, ``get_all``, ``register`` and ``register_alias`` are to
5746exist on every const registry, so the abstraction is finished by moving them to
7059 overrides below and a few hand-written ``get`` overrides.
71602. ``AppType``'s sub-base -- overrides all four, routing the two lookups
7261 through its ``_dispatch``, because a port lookup needs a transport protocol
73- to be answerable at all. Landed as of GitHub issue :issue:`860`: not in this
74- module, but in :class:`pcapkit.const.reg.apptype.apptype.AppType` itself,
75- which mixes in :class:`EnumRegistry` directly. ``register`` and
62+ to be answerable at all. Defined not in this module but in
63+ :class:`pcapkit.const.reg.apptype.apptype.AppType` itself (GitHub issue
64+ :issue:`860`), which mixes in :class:`EnumRegistry` directly. ``register`` and
7665 ``register_alias`` are overridden without that dispatch, staying on the
7766 registry they are called on, so that a write never leaks onto a transport
7867 IANA never assigned the service to -- a minted member for the first, an
7968 alias for the second. Plus ``_unregistered_member``, for its own three extra
8069 attributes (``svc``, ``port``, ``proto``) that the generic one below does
8170 not know to set.
82713. The ``AppType`` transport subclasses -- ``TCP``, ``UDP``, ``SCTP``, ``DCCP``
83- -- turned out to need no override of their own at all: ``_dispatch``
72+ -- need no override of their own at all: ``_dispatch``
8473 already returns ``cls`` unchanged the moment ``cls.__registry__`` is not
8574 :obj:`None`, which is true for exactly these four, so tier 2's lookups
8675 already answer correctly on each of them without a further layer.
8776
88- Before this, the four methods lived as generated *text*: written out longhand in
89- :data:`pcapkit.vendor.default.LINE` and copied verbatim into each of the eleven
90- crawlers that replace that template wholesale, none of which carried
91- ``register``, ``register_alias`` or ``get_all`` at all. Adding one method meant
92- editing every bespoke template by hand, which is the cost :issue:`775` asks to
93- remove.
77+ Defining the four methods here, rather than as generated *text* written out
78+ longhand in :data:`pcapkit.vendor.default.LINE` and copied into each crawler
79+ that replaces that template wholesale, is what :issue:`775` asks for: as text,
80+ adding one method means editing every bespoke template by hand.
9481
9582The contracts are those set out on GitHub issue :issue:`842`: ``get`` is a
9683shortcut for the ``[]`` operation and returns the canonical enumeration member;
@@ -177,8 +164,7 @@ def _validate_value(cls, value: 'Any') -> 'None':
177164
178165 The base implementation accepts everything, because a base cannot know
179166 any subclass's range. Overriding it is how a subclass states one -- the
180- shape ``_missing_`` spells by hand across the generated registries
181- today::
167+ shape ``_missing_`` spells by hand across the generated registries::
182168
183169 @classmethod
184170 def _validate_value(cls, value: 'Any') -> 'None':
@@ -258,10 +244,7 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'Self':
258244
259245 It never mints while resolving ``default``; ``key`` may still mint
260246 through a ``_missing_`` that GitHub issue :issue:`775`'s ruling
261- deliberately kept minting, on one registry (``CGAType``) -- the
262- ruling's final round converted the other two it originally held out,
263- ``EtherType`` and ``Socket``, so they no longer mint on any path
264- either. Registering a member any other way is :meth:`register`'s job
247+ deliberately kept minting, on one registry (``CGAType``). Registering a member any other way is :meth:`register`'s job
265248 and nobody else's, which is the ruling :issue:`775` exists to carry
266249 out: an unrecognised or unregistered value does not become a registered
267250 member unless a user or caller explicitly creates one. A value inside a
@@ -279,49 +262,37 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'Self':
279262
280263 For a ``str`` key, a name match wins over a value match -- the two are
281264 checked in that order, so a string that happens to be both a member's
282- name and a *different* member's value resolves to the name's member,
283- matching what already happened for a name that resolves today. The
284- value side of that check is a plain ``_value2member_map_`` lookup, not
285- ``cls(key)``: on a registry whose own ``_missing_`` mints for an
265+ name and a *different* member's value resolves to the name's member.
266+ The value side of that check is a plain ``_value2member_map_`` lookup,
267+ not ``cls(key)``: on a registry whose own ``_missing_`` mints for an
286268 unrecognised value, routing a failed *name* lookup through the
287269 constructor would let a mere ``get()`` call mint a permanent member
288- where it previously just raised. Defensive rather than observed: of
289- the 127 classes that reach this method -- 125 until GitHub issue
290- :issue:`880`'s own PR added ``pcapkit/const/ngap/procedure_code.py``
291- and ``pcapkit/const/ngap/protocol_ie.py``, remeasured while auditing
292- GitHub issue :issue:`903` -- the ``str``-valued ones
270+ where it should just raise. Defensive rather than observed: none of
271+ the ``str``-valued registries that reach this method
293272 (:class:`~pcapkit.const.ftp.command.Command`, :class:`~pcapkit.const.
294273 ftp.command.FEATCode`, :class:`~pcapkit.const.http.method.Method`,
295274 :class:`~pcapkit.const.pcapng.option_type.OptionType`,
296275 :class:`~pcapkit.const.reg.apptype.apptype.AppType` and its four
297276 transport subclasses :class:`~pcapkit.const.reg.apptype.tcp.TCP`,
298277 :class:`~pcapkit.const.reg.apptype.udp.UDP`,
299278 :class:`~pcapkit.const.reg.apptype.sctp.SCTP` and
300- :class:`~pcapkit.const.reg.apptype.dccp.DCCP` -- completing that set as
301- of GitHub issue :issue:`860`'s own PR 2 -- and, newest of them,
302- :class:`~pcapkit.const.pcapng.tls_key_label.TLSKeyLabel`, which GitHub
303- issue :issue:`877`'s own thread reclassified from a hand-written helper
304- to a generated registry once RFC 9850 §4.2 turned its member list into
305- a live IANA registry) no longer mint on any path, so no live witness
306- exists in this tree today. The one registry that still mints directly
307- via :func:`~aenum.extend_enum`,
279+ :class:`~pcapkit.const.reg.apptype.dccp.DCCP`, and
280+ :class:`~pcapkit.const.pcapng.tls_key_label.TLSKeyLabel`) mints on
281+ any path, so no live witness exists in this tree. The one registry
282+ that still mints directly via :func:`~aenum.extend_enum`,
308283 :class:`~pcapkit.const.mh.cga_type.CGAType`, is :class:`int`-valued, so
309284 a ``str`` name could not reach its mint branch even if this restriction
310285 did not exist; it is not an exception to it, just not reachable by it.
311- GitHub issue :issue:`775`'s final round converted the other two that
312- used to share this footnote, :class:`~pcapkit.const.ipx.socket.Socket`
313- and :class:`~pcapkit.const.reg.ethertype.EtherType`, so ``CGAType`` is
314- now the only one left. This is about a future ``str``-valued registry
315- (or a present one whose ``_missing_`` someday changes) reaching this
316- base with a minting ``_missing_`` of its own, which the restriction
317- below is written to stay correct for regardless. Restricting the value
318- side of ``key`` to an already-registered value keeps *that side*
319- non-minting on every ``str``-valued registry, not only the ones without
320- a minting ``_missing_``. Since :issue:`864`, that is no longer merely a
321- claim about the value side alone: ``default`` resolves through the same
322- kind of ``_value2member_map_`` lookup rather than ``cls(default)``, so
323- for a ``str`` key every path through this method -- name, value and
324- ``default`` alike -- is non-minting.
286+ This is about a future ``str``-valued registry (or a present one whose
287+ ``_missing_`` someday changes) reaching this base with a minting
288+ ``_missing_`` of its own, which the restriction below is written to
289+ stay correct for regardless. Restricting the value side of ``key`` to
290+ an already-registered value keeps *that side* non-minting on every
291+ ``str``-valued registry, not only the ones without a minting
292+ ``_missing_``; and ``default`` resolves through the same kind of
293+ ``_value2member_map_`` lookup rather than ``cls(default)``
294+ (:issue:`864`), so for a ``str`` key every path through this method --
295+ name, value and ``default`` alike -- is non-minting.
325296
326297 That restriction has a cost the paragraph above glosses over: a
327298 *declared-but-unassigned* value -- the case resolved there through
@@ -351,25 +322,23 @@ def get(cls, key: 'Any', default: 'Any' = NO_DEFAULT) -> 'Self':
351322 rather than a builtin, per the ruling recorded on GitHub issue
352323 :issue:`923`: in-library code raises from ``pcapkit.utilities.exceptions``
353324 rather than a builtin, and whether ``ValueError`` or ``KeyError`` applies
354- follows what stdlib's ``Enum`` raises in the same circumstance. The *shape*
355- is unchanged by that ruling and deliberately so -- a name miss stays
356- :exc:`KeyError`-derived and a value miss :exc:`ValueError`-derived,
325+ follows what stdlib's ``Enum`` raises in the same circumstance: a name
326+ miss is :exc:`KeyError`-derived and a value miss :exc:`ValueError`-derived,
357327 matching ``E['nosuch']`` and ``E(999)`` on a stdlib :class:`~enum.Enum`,
358- and matching the 119 of this tree's 127 concrete subclasses that already
359- answered a name miss that way. Only the provenance changed, so every
360- ``except KeyError`` and ``except ValueError`` around a call to this method
361- keeps catching.
328+ so every ``except KeyError`` and ``except ValueError`` around a call to
329+ this method catches.
362330
363- Two details of that conversion are worth stating, since neither is
364- visible from the exception type alone:
331+ Two details are worth stating, since neither is visible from the
332+ exception type alone:
365333
366334 * **The name miss is raised quietly** --
367335 :exc:`~pcapkit.utilities.exceptions.EnumKeyError` with ``quiet=True``,
368336 so nothing is logged and :data:`sys.tracebacklimit` is left alone.
369337 That is not a cosmetic choice: this method's name miss is in-library
370338 control flow at six call sites, and at
371339 :meth:`~pcapkit.const.http.method.Method.get` it is part of a
372- *successful* call -- that override catches it in order to mint. A loud
340+ *successful* call -- that override catches it in order to build an
341+ unregistered member. A loud
373342 error there would put a :data:`logging.CRITICAL` record on every such
374343 call and set :data:`sys.tracebacklimit` to ``0`` process-wide, which
375344 is exactly the GitHub issue :issue:`362` defect
@@ -551,7 +520,7 @@ def _extend(cls, value: 'Any', name: 'str') -> 'Self':
551520 """The raw :func:`~aenum.extend_enum` call, shared by :meth:`register`
552521 and :meth:`register_alias`.
553522
554- Neither public method calls the other: :meth:`register` now refuses an
523+ Neither public method calls the other: :meth:`register` refuses an
555524 already-registered ``value`` before it would ever reach here, and
556525 :meth:`register_alias` depends on the opposite of that -- it verifies
557526 ``value`` *is* already registered and then relies on exactly the
@@ -603,9 +572,9 @@ def register_alias(cls, value: 'Any', name: 'str') -> 'Self':
603572 On this base, an alias adds a *name*, not a member: ``__members__`` grows
604573 by one while ``_member_names_``, iteration and ``_value2member_map_`` are
605574 untouched. Calls :meth:`_extend` directly rather than :meth:`register`, which
606- would now refuse this call outright -- :meth:`register` and
575+ would refuse this call outright -- :meth:`register` and
607576 :meth:`register_alias` test ``value``'s membership for opposite
608- outcomes, so neither can be the other's implementation any more .
577+ outcomes, so neither can be the other's implementation.
609578 ``AppType``'s override differs: it mints a real member through
610579 :func:`~aenum.extend_enum`, so its iteration grows too.
611580
@@ -651,9 +620,9 @@ def _unregistered_member(cls, value: 'Any', name: 'str') -> 'Self':
651620 """Build a member absent from this registry's own lookup tables.
652621
653622 Used by a registry's ``_missing_`` for a declared-but-unassigned value
654- it resolves without anyone asking for a name, so that such a lookup no
655- longer grows the registry -- contrast :meth:`register`, the explicit
656- path that still does.
623+ it resolves without anyone asking for a name, so that such a lookup does
624+ not grow the registry -- contrast :meth:`register`, the explicit path
625+ that does.
657626
658627 The member is constructed through ``cls._member_type_``, which
659628 :mod:`aenum` sets from the enumeration base, so this serves ``int``- and
0 commit comments