Skip to content
Open
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
28 changes: 28 additions & 0 deletions pyflp/_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ def __contains__(self, obj: object) -> bool:
"""
return obj in tuple(self)

def __call__(cls, value: object, *args: object, **kwds: object) -> object:
"""Look up ``value`` even when ``cls`` (typically the base
``EventEnum`` itself) defines no members of its own.

``EventEnum`` is intentionally empty -- real event IDs only exist on
its subclasses (``ChannelID``, ``PluginID``, etc) -- and callers are
expected to be able to do ``EventEnum(raw_id)`` and have
:meth:`EventEnum._missing_` dispatch to whichever subclass defines
that value. Since Python 3.12, ``enum.EnumMeta.__call__`` raises
``TypeError`` before ever reaching ``_missing_`` when called on an
aggregate enum class with zero direct members, which breaks this
pattern. Detect exactly that case and route to ``_missing_``
ourselves; everything else (name-based construction, lookups on
non-empty subclasses, etc.) is left to the normal enum machinery.
"""
if (
not args
and not kwds
and not len(cls)
and isinstance(value, int)
and hasattr(cls, "_missing_")
):
member = cls._missing_(value)
if member is not None:
return member
raise ValueError(f"{value!r} is not a valid {cls.__qualname__}")
return super().__call__(value, *args, **kwds)


class EventEnum(int, enum.Enum, metaclass=_EventEnumMeta):
"""IDs used by events.
Expand Down