Follow-up from #860, moved here so the discussion has its own thread. 120 of 123 const enum classes inherit EnumRegistry; the three that do not are ftp/command.py::CommandType (IntFlag), ftp/command.py::ConformanceRequirement (IntEnum) and reg/apptype/apptype.py::TransportProtocol (IntEnum).
The owner's framing, verbatim:
IntFlag is expected to expand with its combination values; not a bug. what im thinking is, should we change those IntEnum based helper enums to base registry; giving them a shared interface. or we should strip those .get from helper methods and removing minting logic (if any) so that they stay immutable. and if we do decided to go with base registry, we can probably create another subclass from there with only necessary shared auxiliary methods, like get/register-only, no unregistered/unmited value return, nor _missing_/aliasing handlers.
So: (a) helpers onto EnumRegistry; (b) strip their .get and any minting so they stay immutable; (c) a slimmer base carrying only the shared auxiliaries.
Three measurements that constrain the answer. EnumRegistry is exactly seven classmethods — get, get_all, register, _extend, register_alias, register_aliases, _unregistered_member — and defines no _missing_: those hooks live in the generated const classes, so "no _missing_ handler" is not something a new base has to avoid.
get is already registry-free. Its body touches only cls._member_map_, cls._value2member_map_, cls(key) and the default sentinel; it never calls _unregistered_member and never mints. It is generic enum sugar, and strictly richer than the helpers' hand-rolled versions (name lookup and value lookup and a default).
get/register-only is self-contradictory, though. register guards a duplicate then calls _extend, and _extend is the mutation — registering is minting, deliberate rather than accidental. A base that registers is not immutable.
And a slim variant cannot be a subclass of EnumRegistry. Inherited methods cannot be removed, and overriding _unregistered_member to raise yields a class advertising the method it forbids. The coherent shape is a parent: EnumLookup carrying get/get_all, then EnumRegistry(EnumLookup) adding the mutating half.
That makes (c) viable only along the get line, where it converges with (b): if the helpers keep just a lookup, the only question left is whether that lookup is shared or duplicated. A repo-wide census — how many non-registry enums exist outside pcapkit/const/, and whether their .gets are the same function modulo names — is in flight and will decide it; a shared base earns its keep at 10 classes and not at 3.
Follow-up from #860, moved here so the discussion has its own thread. 120 of 123 const enum classes inherit
EnumRegistry; the three that do not areftp/command.py::CommandType(IntFlag),ftp/command.py::ConformanceRequirement(IntEnum) andreg/apptype/apptype.py::TransportProtocol(IntEnum).The owner's framing, verbatim:
So: (a) helpers onto
EnumRegistry; (b) strip their.getand any minting so they stay immutable; (c) a slimmer base carrying only the shared auxiliaries.Three measurements that constrain the answer.
EnumRegistryis exactly seven classmethods —get,get_all,register,_extend,register_alias,register_aliases,_unregistered_member— and defines no_missing_: those hooks live in the generated const classes, so "no_missing_handler" is not something a new base has to avoid.getis already registry-free. Its body touches onlycls._member_map_,cls._value2member_map_,cls(key)and thedefaultsentinel; it never calls_unregistered_memberand never mints. It is generic enum sugar, and strictly richer than the helpers' hand-rolled versions (name lookup and value lookup and adefault).get/register-only is self-contradictory, though.registerguards a duplicate then calls_extend, and_extendis the mutation — registering is minting, deliberate rather than accidental. A base that registers is not immutable.And a slim variant cannot be a subclass of
EnumRegistry. Inherited methods cannot be removed, and overriding_unregistered_memberto raise yields a class advertising the method it forbids. The coherent shape is a parent:EnumLookupcarryingget/get_all, thenEnumRegistry(EnumLookup)adding the mutating half.That makes (c) viable only along the
getline, where it converges with (b): if the helpers keep just a lookup, the only question left is whether that lookup is shared or duplicated. A repo-wide census — how many non-registry enums exist outsidepcapkit/const/, and whether their.gets are the same function modulo names — is in flight and will decide it; a shared base earns its keep at 10 classes and not at 3.