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:
EnumFwfField, and using it as a mix-in, i.e.
class EnumFwfField(FwfField, Enum):
pass
class CnefeSchema(EnumFwfField, Enum):
...
but I get the same error as above;Enum fields (in this example, state_code) to FwfField, i.e.
class CnefeSchema(FwfField, Enum):
state_code = FwfField("int", "Código da UF", 2)
...
but then I get
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'
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With