Skip to content

Custom dataclasses are not recognized as dataclasses #15843

Closed
@NeilGirdhar

Description

@NeilGirdhar

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions