In the relevant section of the Python Enum
documentation, it is mentioned that mix-in types can be used to ensure items belong to that type and act as objects of that type, like in the example:
class IntEnum(int, Enum):
pass
However, the documentation does not give any examples on how to use a custom class as a mix-in type, and I've failed miserably at that. Is it even possible? And if so, how do I do it?
The code I'm trying to write is
@dataclass
class Field:
dtype: str
name: str
@dataclass
class FwfField(Field):
width: int
def __post_init__(self):
if self.width <= 0:
raise ValueError("Field width must be positive.")
class CnefeSchema(FwfField, Enum):
state_code = ("int", "Código da UF", 2)
...
When I import CnefeSchema
from another file or run it, I get
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 from src.conf.schemas import CnefeSchema
File src/conf/schemas.py:25, in <module>
21 pass
24 # TODO automatically read schema from Layout
---> 25 class CnefeSchema(EnumFwfField, Enum):
27 @classmethod
28 def parse(cls) -> tuple[list, dict, dict]:
29 """
30 Get field widths, dtypes, and columns from schema.
31
(...)
34 as `pandas.read_fwf`.
35 """
File /usr/lib/python3.10/enum.py:298, in EnumMeta.__new__(metacls, cls, bases, classdict, **kwds)
296 enum_member._name_ = member_name
297 enum_member.__objclass__ = enum_class
--> 298 enum_member.__init__(*args)
299 # If another member with the same value was already defined, the
300 # new member becomes an alias to the existing one.
301 for name, canonical_member in enum_class._member_map_.items():
File <string>:4, in __init__(self, dtype, name, width)
File /usr/lib/python3.10/types.py:187, in DynamicClassAttribute.__set__(self, instance, value)
185 def __set__(self, instance, value):
186 if self.fset is None:
--> 187 raise AttributeError("can't set attribute")
188 self.fset(instance, value)
AttributeError: can't set attribute
I've already tried:
- Defining another class,
EnumFwfField
, and using it as a mix-in, i.e.
but I get the same error as above;class EnumFwfField(FwfField, Enum): pass class CnefeSchema(EnumFwfField, Enum): ...
- Setting the
Enum
fields (in this example,state_code
) toFwfField
, i.e.
but then I getclass CnefeSchema(FwfField, Enum): state_code = FwfField("int", "Código da UF", 2) ...
Traceback (most recent call last): File "src/conf/schemas.py", line 25, in <module> class CnefeSchema(EnumFwfField, Enum): File "/usr/lib/python3.10/enum.py", line 298, in __new__ enum_member.__init__(*args) TypeError: FwfField.__init__() missing 2 required positional arguments: 'name' and 'width'
CodePudding user response:
The issue you are having is because in your above code you have a name
attribute in your Field
dataclass, but Enum
will not let you set a name
attribute.
Rename that field to something else, for example 'dname'
, and it should work.
(The error message in 3.11 is more informative.)