Closed
Description
Feel free to skip to the bottom of the code. The reset is custom dataclass specification.
import dataclasses
from dataclasses import replace
from typing import (Any, Callable, ClassVar, Protocol, dataclass_transform, overload,
runtime_checkable)
@runtime_checkable
class DataclassInstance(Protocol):
__dataclass_fields__: ClassVar[dict[str, dataclasses.Field[Any]]]
@overload
@dataclass_transform()
def dataclass(*, init: bool = True, repr_: bool = True, eq: bool = True,
order: bool = False) -> Callable[[type[Any]], type[DataclassInstance]]:
...
@overload
@dataclass_transform()
def dataclass(cls: type[Any], /, *, init: bool = True, repr_: bool = True, eq: bool = True,
order: bool = False) -> type[DataclassInstance]:
...
@dataclass_transform()
def dataclass(cls: type[Any] | None = None, /, *, init: bool = True, repr_: bool = True,
eq: bool = True, order: bool = False
) -> type[DataclassInstance] | Callable[[type[Any]], type[DataclassInstance]]:
if cls is None:
def f(x: type[Any], /) -> type[DataclassInstance]:
return dataclass(x, init=init, repr_=repr_, eq=eq, order=order)
return f # Type checking support partial is poor.
return dataclasses.dataclass(init=init, repr=repr_, eq=eq, order=order, frozen=True)(cls)
@dataclass
class X:
a: int
def f(x: X) -> X:
return replace(x, a=1) # [Error](error: Argument 1 to "replace" has incompatible type "X"; expected a dataclass
It appears that MyPy recognizes that something is a dataclass through some means other than the protocol. See here for background: python/cpython#102699