from dataclasses import dataclass class ADTMeta(type): def __new__(mcs, name, bases, namespace: dict): adtc_class = super().__new__(mcs, name, bases, namespace) if "__is_adt_variant__" in namespace: if namespace["__is_adt_variant__"]: return adtc_class for member_name, member in namespace.items(): if isinstance(member, type): variant_class = dataclass(type(member_name, (adtc_class,), { "__qualname__": f"{adtc_class.__qualname__}.{member_name}", "__is_adt_variant__": True, "__annotations__": member.__annotations__ })) setattr(adtc_class, member_name, variant_class) annotations = namespace.pop("__annotations__", {}) for variant_name, variant_annotation in annotations.items(): variant_class = type(variant_name, (adtc_class,), { "__qualname__": f"{adtc_class.__qualname__}.{variant_name}", "__is_adt_variant__": True }) if (variant_annotation is Ellipsis) or (variant_annotation is None): variant_class.__repr__ = lambda self: f"<{self.__class__.__qualname__}>" else: variant_class.__init__ = create_init(variant_class, variant_annotation) variant_class.__repr__ = lambda self: f"<{self.__class__.__qualname__} {repr(self.value)}>" variant_class.__match_args__ = ("value",) setattr(adtc_class, variant_name, variant_class) return adtc_class def create_init(klass, annotation): def __init__(self: klass, value: annotation) -> None: self.value = value return __init__