I can’t figure out the correct type annotations for __new__ and a couple of steps within __new__, in a metaclass that wraps dataclasses.dataclass and needs to do some work both before and after the actual creation of the dataclass. Here’s a cut-down version of my code with the errors marked:
import dataclasses
from types import GenericAlias, UnionType
from typing import Any, dataclass_transform
@dataclass_transform()
class DemoMeta(type):
_attributes: dict[str, dataclasses.Field[Any]]
def __new__(
cls,
cname: str,
bases: tuple[type, ...],
body: dict[str, Any]
) -> "DemoMeta":
annotations = body.setdefault("__annotations__", {})
for fname, ty in annotations.items():
adj_default = adjust_field(ty, body.get(fname, dataclasses.MISSING))
if adj_default is not dataclasses.MISSING:
body[fname] = adj_default
# error: incompatible types in assignment (expression has type
# "type[Never]", variable has type "DemoMeta")
klass: "DemoMeta" = dataclasses.dataclass()(
# error: Argument 1 has incompatible type "DemoMeta";
# expected "type[Never]"
type.__new__(cls, cname, bases, body)
)
# error: argument 1 to "fields" has incompatible type "DemoMeta";
# expected "DataclassInstance | type[DataclassInstance]"
fields = dataclasses.fields(klass)
attributes = { field.name: field for field in fields }
klass._attributes = attributes
return klass
def adjust_field(ty: type | GenericAlias | UnionType, default: Any) -> Any:
# in the real program, this is not just a stub
return default
class Demo(metaclass=DemoMeta):
errors: list[tuple[str, str]]
If I remove the type annotation on klass, then it stops complaining about the call to dataclasses.fields, but instead it tells me klass needs a type annotation.
This code needs to work, and typecheck, in Python 3.11 and higher.