Patching a method onto an Enum subclass fails:
from enum import Enum
from fastcore.basics import patch
class Color(Enum):
RED = 1
GREEN = 2
@patch(cls_method=True)
def from_name(cls: Color, s): return cls[s.upper()]
# AttributeError: 'Color' object has no attribute '__name__'
The cause is in patch_to, which calls tuplify(cls). An Enum class is
iterable, so instead of wrapping the class in a one-element tuple, tuplify
iterates it and returns its members. The loop body then runs against an enum
member instead of the class, and the member has no __name__.
This affects any class whose metaclass makes instances iterable, not just Enums.
A few shapes a fix could take:
-
In patch_to, wrap the class directly instead of tuplifying it:
classes = (cls,) if isinstance(cls, type) else tuplify(cls). This keeps
list and union handling intact, since patch already converts unions to
tuples via union2tuple.
-
Same idea, but guard on tuples instead of types:
classes = cls if isinstance(cls, tuple) else (cls,). Relies on unions
always arriving as tuples, which holds for the patch path but not for
direct patch_to calls with a bare union.
-
Change tuplify (or listify) to not iterate types. Broader blast radius,
since those are used widely.
Patching a method onto an
Enumsubclass fails:The cause is in
patch_to, which callstuplify(cls). AnEnumclass isiterable, so instead of wrapping the class in a one-element tuple,
tuplifyiterates it and returns its members. The loop body then runs against an enum
member instead of the class, and the member has no
__name__.This affects any class whose metaclass makes instances iterable, not just Enums.
A few shapes a fix could take:
In
patch_to, wrap the class directly instead of tuplifying it:classes = (cls,) if isinstance(cls, type) else tuplify(cls). This keepslist and union handling intact, since
patchalready converts unions totuples via
union2tuple.Same idea, but guard on tuples instead of types:
classes = cls if isinstance(cls, tuple) else (cls,). Relies on unionsalways arriving as tuples, which holds for the
patchpath but not fordirect
patch_tocalls with a bare union.Change
tuplify(orlistify) to not iterate types. Broader blast radius,since those are used widely.