pandas-dev / pandas-stubs

Public type stubs for pandas
BSD 3-Clause "New" or "Revised" License
229 stars 122 forks source link

Series constructor does not accept TypedDict #978

Closed BobVitorBob closed 11 hours ago

BobVitorBob commented 4 weeks ago

Describe the bug When creating a series from a TypedDict, Pyright reports

No overloads for "__new__" match the provided arguments. Argument of type (TypedDict) cannot be assigned to parameter "data" of type "Scalar | _ListLike[Unknown] | dict[HashableT1@__new__, Any] | BaseGroupBy[Unknown] | NaTType | NAType | None" in function "__new__"

To Reproduce

from typing import TypedDict
import pandas as pd
class MyDict(TypedDict):
    a: str
    b: str

my_dict = MyDict(a="", b="")
pd.Series(my_dict)

Pyright yields

error: No overloads for "__new__" match the provided arguments (reportCallIssue)
error: Argument of type "MyDict" cannot be assigned to parameter "data" of type "Scalar | _ListLike[Unknown] | dict[HashableT1@__new__, Any] | BaseGroupBy[Unknown] | NaTType | NAType | None" in function "__new__"
    Type "MyDict" is incompatible with type "Scalar | _ListLike[Unknown] | dict[HashableT1@__new__, Any] | BaseGroupBy[Unknown] | NaTType | NAType | None"
      "MyDict" is incompatible with "ExtensionArray"
      "MyDict" is incompatible with "NAType"
      "MyDict" is incompatible with "NaTType"
      "MyDict" is incompatible with "Timedelta"
      "MyDict" is incompatible with "Timestamp"
      "MyDict" is incompatible with "bool"
      "MyDict" is incompatible with "bytes"
    ... (reportArgumentType)

Please complete the following information:

Additional context Seems like TypedDict is incompatible with dict, but I don't see why it matters in this specific example. Changing overload 8 (series.pyi(332, 9))

@overload
    def __new__(
        cls,
        data: (
            Scalar
            | _ListLike
            | dict[HashableT1, Any]
            | BaseGroupBy
            | NaTType
            | NAType
            | None
        ) = ...,
        index: Axes | None = ...,
        *,
        dtype: Dtype = ...,
        name: Hashable = ...,
        copy: bool = ...,
    ) -> Series: ...

to

@overload
    def __new__(
        cls,
        data: (
            Scalar
            | _ListLike
            | Mapping[HashableT1, Any]
            | BaseGroupBy
            | NaTType
            | NAType
            | None
        ) = ...,
        index: Axes | None = ...,
        *,
        dtype: Dtype = ...,
        name: Hashable = ...,
        copy: bool = ...,
    ) -> Series: ...

fixes this specific example but I don't know if it breaks something elsewhere.

Dr-Irv commented 4 weeks ago

I think that if you changed all the Series.__new__() overloads to use Mapping instead of dict, it would work and handle your use case.

PR with tests welcome.