from typing import Union, List from dataclasses import dataclass class Validations: def __post_init__(self): """Run validation methods if declared. The validation method can be a simple check that raises ValueError or a transformation to the field value. The validation is performed by calling a function named: `validate_<field_name>(self, value, field) -> field.type` """ for name, field in self.__dataclass_fields__.items(): if (method := getattr(self, f"validate_{name}", None)): setattr(self, name, method(getattr(self, name), field=field)) @dataclass class Product(Validations): name: str tags: Union[str, List[str]] def validate_name(self, value, **_) -> str: if len(value) < 3 or len(value) > 20: raise ValueError("name must have between 3 and 20 chars.") return value def validate_tags(self, value, **_) -> List[str]: """Ensure tags are always List[str] even if "tag1,tag2" is passed""" if isinstance(value, str): value = [v.strip() for v in value.split(",")] return value if __name__ == "__main__": product = Product(name="product", tags="tag1, tag2") assert product.tags == ["tag1", "tag2"] # transformed to List[str] try: product = Product(name="pr", tags="tag1, tag2, tag3") except ValueError as e: assert str(e) == "name must have between 3 and 20 chars."