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
Feel free to skip to the bottom of the code. The reset is custom dataclass specification.
It appears that MyPy recognizes that something is a dataclass through some means other than the protocol. See here for background: python/cpython#102699