typeshed icon indicating copy to clipboard operation
typeshed copied to clipboard

`dataclasses.asdict` definition is not correct

Open sobolevn opened this issue 3 years ago • 3 comments

Example:

from dataclasses import dataclass, asdict

@dataclass
class D:
    x: int

asdict(D(1), dict_factory=dict)  # Argument "dict_factory" to "asdict" has incompatible type "Type[Dict[Any, Any]]"; expected "Callable[[List[Tuple[str, Any]]], Dict[_KT, _VT]]"

But, since dict is used a default implementation, it should be valid. Source: https://github.com/python/cpython/blob/325ae93b6b7113cd4a4c2ce441615ae7def779e2/Lib/dataclasses.py#L1254

Found in https://github.com/python/mypy/pull/13367

sobolevn avatar Aug 10 '22 09:08 sobolevn

Changing list to Iterable does not work as well:

from dataclasses import dataclass, astuple, asdict

@dataclass
class D:
    x: int

from typing import Callable, Any, TypeVar, Iterable, Tuple
_T = TypeVar('_T')
def asdict2(obj: Any, *, dict_factory: Callable[[Iterable[Tuple[str, Any]]], _T]) -> _T: ...

asdict2(D(3), dict_factory=dict)  #  error: Argument "dict_factory" to "asdict2" has incompatible type "Type[Dict[Any, Any]]"; expected "Callable[[Iterable[Tuple[str, Any]]], Dict[_KT, _VT]]"

sobolevn avatar Aug 10 '22 09:08 sobolevn

As a workaround, I have noticed that annotating the return value will succeed with mypy.

from typing import Any, Dict
from dataclasses import dataclass, asdict

@dataclass
class D:
    x: int

out: Dict[str, Any] = asdict(D(1), dict_factory=dict)  # Success: no issues found in 1 source file

5tefan avatar Sep 09 '22 23:09 5tefan