Установка значения атрибута через базовый класс в шаге post_init, кажется, работает:
@dataclass(frozen=True)
class MyClass:
my_field: Sequence[str]
def __post_init__(self):
super().__setattr__('my_field', tuple(getattr(self, 'my_field')))
Реализация миксина:
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))