Skip to content

design: should the non-registry helper enums share a lookup interface, or be made strictly immutable? #877

Description

@JarryShaw

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    designA design or decision issue: a pattern being decided rather than a defect or a requestenhancementIssues requesting a new capability (set by the feature request template)refactorRestructuring for its own sake — neither a fix nor a new capability (refactor: prefix)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions