Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 14 additions & 39 deletions pandas-stubs/_libs/missing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ from typing_extensions import Self
class NAType:
def __new__(cls, *args: Any, **kwargs: Any) -> Self: ...
def __format__(self, format_spec: str) -> str: ...
def __bool__(self) -> None: ...
def __hash__(self) -> int: ...
def __reduce__(self) -> str: ...
@overload
Expand Down Expand Up @@ -135,7 +134,7 @@ class NAType:
@overload # type: ignore[override]
def __eq__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
) -> Series[bool]: ...
@overload
def __eq__(self, other: Index, /) -> BooleanArray: ... # type: ignore[overload-overlap]
@overload
Expand All @@ -145,7 +144,7 @@ class NAType:
@overload # type: ignore[override]
def __ne__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
) -> Series[bool]: ...
@overload
def __ne__(self, other: Index, /) -> BooleanArray: ... # type: ignore[overload-overlap]
@overload
Expand All @@ -155,31 +154,31 @@ class NAType:
@overload
def __le__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
) -> Series[bool]: ...
@overload
def __le__(self, other: Index, /) -> BooleanArray: ... # type: ignore[overload-overlap]
@overload
def __le__(self, other: object, /) -> NAType: ...
@overload
def __lt__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
) -> Series[bool]: ...
@overload
def __lt__(self, other: Index, /) -> BooleanArray: ... # type: ignore[overload-overlap]
@overload
def __lt__(self, other: object, /) -> NAType: ...
@overload
def __gt__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
) -> Series[bool]: ...
@overload
def __gt__(self, other: Index, /) -> BooleanArray: ... # type: ignore[overload-overlap]
@overload
def __gt__(self, other: object, /) -> NAType: ...
@overload
def __ge__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
) -> Series[bool]: ...
@overload
def __ge__(self, other: Index, /) -> BooleanArray: ... # type: ignore[overload-overlap]
@overload
Expand All @@ -205,45 +204,21 @@ class NAType:
@overload
def __rpow__(self, other: object, /) -> NAType: ...
@overload
def __and__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
@overload
def __and__(self, other: Index, /) -> Index: ... # type: ignore[overload-overlap]
@overload
def __and__(self, other: Literal[False], /) -> Literal[False]: ... # type: ignore[overload-overlap]
@overload
def __and__(self, other: object, /) -> NAType: ...
def __and__(self, other: Literal[False], /) -> Literal[False]: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
@overload
def __rand__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
@overload
def __rand__(self, other: Index, /) -> Index: ... # type: ignore[overload-overlap]
def __and__(self, other: bool | NAType, /) -> NAType: ...
@overload
def __rand__(self, other: Literal[False], /) -> Literal[False]: ... # type: ignore[overload-overlap]
def __rand__(self, other: Literal[False], /) -> Literal[False]: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
@overload
def __rand__(self, other: object, /) -> NAType: ...
@overload
def __or__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
def __rand__(self, other: bool, /) -> NAType: ...
@overload
def __or__(self, other: Index, /) -> Index: ... # type: ignore[overload-overlap]
@overload
def __or__(self, other: Literal[True], /) -> Literal[True]: ... # type: ignore[overload-overlap]
@overload
def __or__(self, other: object, /) -> NAType: ...
@overload
def __ror__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
) -> Series: ...
def __or__(self, other: Literal[True], /) -> Literal[True]: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
@overload
def __ror__(self, other: Index, /) -> Index: ... # type: ignore[overload-overlap]
def __or__(self, other: bool | NAType, /) -> NAType: ...
@overload
def __ror__(self, other: Literal[True], /) -> Literal[True]: ... # type: ignore[overload-overlap]
def __ror__(self, other: Literal[True], /) -> Literal[True]: ... # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
@overload
def __ror__(self, other: object, /) -> NAType: ...
def __ror__(self, other: bool | NAType, /) -> NAType: ...
@overload
def __xor__( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
self, other: Series, /
Expand Down
97 changes: 42 additions & 55 deletions tests/test_natype.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import pandas as pd
from pandas.api.typing import NAType
from pandas.core.arrays.boolean import BooleanArray
import pytest
from typing_extensions import assert_type

from tests import check
Expand All @@ -14,7 +13,7 @@
def test_arithmetic() -> None:
na = pd.NA

s_int: pd.Series[int] = pd.Series([1, 2, 3], dtype="Int64")
s_int = pd.Series([1, 2, 3], dtype="Int64")
idx_int: pd.Index[int] = pd.Index([1, 2, 3], dtype="Int64")

# __add__
Expand All @@ -24,8 +23,8 @@ def test_arithmetic() -> None:

# __radd__
check(assert_type(s_int + na, pd.Series), pd.Series)
# https://github.com/pandas-dev/pandas-stubs/issues/1347
check(assert_type(idx_int + na, pd.Index), pd.Index) # type: ignore[assert-type] # pyright: ignore[reportAssertTypeFailure]
# requires orthogonal fix: https://github.com/pandas-dev/pandas-stubs/issues/1347
# check(assert_type(idx_int + na, pd.Index), pd.Index)
check(assert_type(1 + na, NAType), NAType)

# __sub__
Expand All @@ -35,8 +34,8 @@ def test_arithmetic() -> None:

# __rsub__
check(assert_type(s_int - na, pd.Series), pd.Series)
# https://github.com/pandas-dev/pandas-stubs/issues/1347
check(assert_type(idx_int - na, pd.Index), pd.Index) # type: ignore[assert-type]# pyright: ignore[reportAssertTypeFailure]
# requires orthogonal fix: https://github.com/pandas-dev/pandas-stubs/issues/1347
# check(assert_type(idx_int - na, pd.Index), pd.Index)
check(assert_type(1 - na, NAType), NAType)

# __mul__
Expand All @@ -46,8 +45,8 @@ def test_arithmetic() -> None:

# __rmul__
check(assert_type(s_int * na, pd.Series), pd.Series)
# https://github.com/pandas-dev/pandas-stubs/issues/1347
check(assert_type(idx_int * na, pd.Index), pd.Index) # type: ignore[assert-type]# pyright: ignore[reportAssertTypeFailure]
# requires orthogonal fix: https://github.com/pandas-dev/pandas-stubs/issues/1347
# check(assert_type(idx_int * na, pd.Index), pd.Index)
check(assert_type(1 * na, NAType), NAType)

# __matmul__
Expand Down Expand Up @@ -83,72 +82,68 @@ def test_arithmetic() -> None:

# __rmod__
check(assert_type(s_int % na, pd.Series), pd.Series)
# https://github.com/pandas-dev/pandas-stubs/issues/1347
check(assert_type(idx_int % na, pd.Index), pd.Index) # type: ignore[assert-type] # pyright: ignore[reportAssertTypeFailure]
# requires orthogonal fix: https://github.com/pandas-dev/pandas-stubs/issues/1347
# check(assert_type(idx_int % na, pd.Index), pd.Index)
check(assert_type(1 % na, NAType), NAType)

# __divmod__
with pytest.raises(RuntimeError):
# bug upstream: https://github.com/pandas-dev/pandas/issues/62196
check(
assert_type(
divmod(na, s_int), # pyright: ignore[reportAssertTypeFailure]
tuple[pd.Series, pd.Series],
),
tuple,
)
with pytest.raises(RuntimeError):
check(
assert_type(
divmod(na, idx_int), # pyright: ignore[reportAssertTypeFailure]
tuple[pd.Index, pd.Index],
),
tuple,
)
# bug upstream: https://github.com/pandas-dev/pandas/issues/62196
# check(
# assert_type(
# divmod(na, s_int),
# tuple[pd.Series, pd.Series],
# ),
# tuple,
# )
# check(
# assert_type(
# divmod(na, idx_int),
# tuple[pd.Index, pd.Index],
# ),
# tuple,
# )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK to leave this in, with the #pyright: ignore, because it works with mypy. Then just make the comment about how pyright has the bug.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pyright 1.1.405 should fix this, so can you try changing pyproject.toml to use that version and see if you can put the test back?

check(assert_type(divmod(na, 1), tuple[NAType, NAType]), tuple)

# __rdivmod__
with pytest.raises(RuntimeError):
# bug upstream: https://github.com/pandas-dev/pandas/issues/62196
check(
assert_type(divmod(s_int, na), tuple[pd.Series, pd.Series]), # type: ignore[assert-type] # pyright: ignore[reportAssertTypeFailure]
tuple,
)
with pytest.raises(RuntimeError):
# https://github.com/pandas-dev/pandas-stubs/issues/1347
check(
assert_type(divmod(idx_int, na), tuple[pd.Index, pd.Index]), # type: ignore[assert-type] # pyright: ignore[reportAssertTypeFailure]
tuple,
)
# bug upstream: https://github.com/pandas-dev/pandas/issues/62196
# check(
# assert_type(divmod(s_int, na), tuple[pd.Series, pd.Series]),
# tuple,
# )
# https://github.com/pandas-dev/pandas-stubs/issues/1347
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the bug upstream in pandas, not the orthogonal issue?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say this is both, here

# check(
# assert_type(divmod(idx_int, na), tuple[pd.Index, pd.Index]),
# tuple,
# )
check(assert_type(divmod(1, na), tuple[NAType, NAType]), tuple)

# __eq__
check(assert_type(na == s_int, pd.Series), pd.Series)
check(assert_type(na == s_int, "pd.Series[bool]"), pd.Series)
check(assert_type(na == idx_int, BooleanArray), BooleanArray)
check(assert_type(na == 1, NAType), NAType)

# __ne__
check(assert_type(na != s_int, pd.Series), pd.Series)
check(assert_type(na != s_int, "pd.Series[bool]"), pd.Series)
check(assert_type(na != idx_int, BooleanArray), BooleanArray)
check(assert_type(na != 1, NAType), NAType)

# __le__
check(assert_type(na <= s_int, pd.Series), pd.Series)
check(assert_type(na <= s_int, "pd.Series[bool]"), pd.Series)
check(assert_type(na <= idx_int, BooleanArray), BooleanArray)
check(assert_type(na <= 1, NAType), NAType)

# __lt__
check(assert_type(na < s_int, pd.Series), pd.Series)
check(assert_type(na < s_int, "pd.Series[bool]"), pd.Series)
check(assert_type(na < idx_int, BooleanArray), BooleanArray)
check(assert_type(na < 1, NAType), NAType)

# __gt__
check(assert_type(na > s_int, pd.Series), pd.Series)
check(assert_type(na > s_int, "pd.Series[bool]"), pd.Series)
check(assert_type(na > idx_int, BooleanArray), BooleanArray)
check(assert_type(na > 1, NAType), NAType)

# __ge__
check(assert_type(na >= s_int, pd.Series), pd.Series)
check(assert_type(na >= s_int, "pd.Series[bool]"), pd.Series)
check(assert_type(na >= idx_int, BooleanArray), BooleanArray)
check(assert_type(na >= 1, NAType), NAType)

Expand All @@ -159,32 +154,24 @@ def test_arithmetic() -> None:

# __rpow__
check(assert_type(s_int**na, pd.Series), pd.Series)
# https://github.com/pandas-dev/pandas-stubs/issues/1347
check(assert_type(idx_int**na, pd.Index), pd.Index) # type: ignore[assert-type] # pyright: ignore[reportAssertTypeFailure]
# requires orthogonal fix: https://github.com/pandas-dev/pandas-stubs/issues/1347
# check(assert_type(idx_int**na, pd.Index), pd.Index)
check(assert_type(2**na, NAType), NAType)

# __and__
check(assert_type(na & s_int, pd.Series), pd.Series)
check(assert_type(na & idx_int, pd.Index), pd.Index)
check(assert_type(na & False, Literal[False]), bool)
check(assert_type(na & True, NAType), NAType)
check(assert_type(na & na, NAType), NAType)

# __rand__
check(assert_type(s_int & na, pd.Series), pd.Series)
check(assert_type(idx_int & na, pd.Index), pd.Index)
check(assert_type(False & na, Literal[False]), bool)
check(assert_type(True & na, NAType), NAType)

# __or__
check(assert_type(na | s_int, pd.Series), pd.Series)
check(assert_type(na | idx_int, pd.Index), pd.Index)
check(assert_type(na | False, NAType), NAType)
check(assert_type(na | True, Literal[True]), bool)

# __ror__
check(assert_type(s_int | na, pd.Series), pd.Series)
check(assert_type(idx_int | na, pd.Index), pd.Index)
check(assert_type(False | na, NAType), NAType)
check(assert_type(True | na, Literal[True]), bool)

Expand Down
Loading