Reputation: 2307
Now that I have finally dropped support for Python 2, I am migrating from attrs
to Python 3 dataclasses
and there is one issue I am particularly struggling with.
Let's say I have a frozen and hashable class MyClass
with one field my_field
of type tuple
.
Thanks to attrs
converters, I was able to provide a flexible API, with clients able to instantiate my_field
with a variety of types like list
, set
or dict_keys
. They would all be automatically converted to a tuple
before the class creation.
Can I preserve this API with dataclasses
?
As requested, a small code sample:
@attr.s(frozen=True, hash=True)
class MyClass:
my_field = attr.ib(default=tuple(), converter=tuple)
print(MyClass([1, 2, 3]))
Upvotes: 3
Views: 1968
Reputation: 2307
Setting the attribute value through the base class in post_init step seems to work:
@dataclass(frozen=True)
class MyClass:
my_field: Sequence[str]
def __post_init__(self):
super().__setattr__('my_field', tuple(getattr(self, 'my_field')))
Mixin implementation:
class ValidationError(AttributeError):
pass
class ConversionValidationField(Field):
def __init__(self, default=MISSING, default_factory=MISSING, init=True, repr=True,
hash=None, compare=True, metadata=None, converter=None, validator=None):
self.converter = converter
self.validator = validator
super().__init__(default, default_factory, init, repr, hash, compare, metadata)
class ConversionValidationMixin:
def __post_init__(self):
for field in fields(self):
if isinstance(field, ConversionValidationField):
if field.converter:
super().__setattr__(field.name, field.converter(getattr(self, field.name)))
if field.validator:
if not field.validator(getattr(self, field.name)):
raise ValidationError('Validation failed for {}.'.format(field.name))
Upvotes: 3
Reputation: 4166
No, converters are one of the things the dataclass PEP chose not to implement to keep is simple. http://www.attrs.org/en/stable/why.html#data-classes mentions a few more.
DCs are strictly a subset of attrs
and it's unlikely that it'll ever change.
Upvotes: 1