From 76e21ea54cf9c630edf2b3958798293e5ccb38f9 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sat, 17 Sep 2022 15:43:00 -0400 Subject: [PATCH 1/5] Fix IndexSlice --- pandas-stubs/_typing.pyi | 2 ++ pandas-stubs/core/indexing.pyi | 17 +++++------------ tests/test_frame.py | 12 ++++++++++++ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index f67b3f908..9dd3760ec 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -175,6 +175,8 @@ NDFrameT = TypeVar("NDFrameT", bound=NDFrame) IndexT = TypeVar("IndexT", bound=Index) +IndexSliceTuple = slice | tuple[Index | MaskType | Scalar | list[Scalar] | slice, ...] + # Interval closed type IntervalClosedType = Literal["left", "right", "both", "neither"] diff --git a/pandas-stubs/core/indexing.pyi b/pandas-stubs/core/indexing.pyi index 938696292..a158b874c 100644 --- a/pandas-stubs/core/indexing.pyi +++ b/pandas-stubs/core/indexing.pyi @@ -1,22 +1,15 @@ -from typing import ( - Generic, - TypeVar, - Union, -) +from typing import TypeVar import numpy as np from pandas.core.indexes.api import Index from pandas._libs.indexing import _NDFrameIndexerBase -from pandas._typing import ( - Scalar, - StrLike, -) +from pandas._typing import IndexSliceTuple -_IndexSliceT = TypeVar("_IndexSliceT", bound=Union[StrLike, Scalar, slice]) +_IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=IndexSliceTuple) -class _IndexSlice(Generic[_IndexSliceT]): - def __getitem__(self, arg) -> tuple[_IndexSliceT, ...]: ... +class _IndexSlice: + def __getitem__(self, arg: _IndexSliceTupleT) -> _IndexSliceTupleT: ... IndexSlice: _IndexSlice diff --git a/tests/test_frame.py b/tests/test_frame.py index c1e66c3fe..f46ef2b16 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1278,6 +1278,18 @@ def test_indexslice_setitem(): df.loc[pd.IndexSlice[2, :], "z"] = [200, 300] +def test_indexslice_getitem(): + # GH 300 + df = ( + pd.DataFrame({"x": [1, 2, 2, 3, 4], "y": [10, 20, 30, 40, 10]}) + .assign(z=lambda df: df.x * df.y) + .set_index(["x", "y"]) + ) + ind = pd.Index([2, 3]) + check(assert_type(pd.IndexSlice[ind, :], tuple[pd.Index, slice]), tuple) + check(assert_type(df.loc[pd.IndexSlice[ind, :]], pd.DataFrame), pd.DataFrame) + + def test_compute_values(): df = pd.DataFrame({"x": [1, 2, 3, 4]}) s: pd.Series = pd.Series([10, 20, 30, 40]) From 3519805015073359c66d968f6e75a3cec2a6c019 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sat, 17 Sep 2022 15:47:44 -0400 Subject: [PATCH 2/5] Move IndexSliceTuple over to indexing.pyi --- pandas-stubs/_typing.pyi | 2 -- pandas-stubs/core/indexing.pyi | 9 +++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index 9dd3760ec..f67b3f908 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -175,8 +175,6 @@ NDFrameT = TypeVar("NDFrameT", bound=NDFrame) IndexT = TypeVar("IndexT", bound=Index) -IndexSliceTuple = slice | tuple[Index | MaskType | Scalar | list[Scalar] | slice, ...] - # Interval closed type IntervalClosedType = Literal["left", "right", "both", "neither"] diff --git a/pandas-stubs/core/indexing.pyi b/pandas-stubs/core/indexing.pyi index a158b874c..a18b8f80b 100644 --- a/pandas-stubs/core/indexing.pyi +++ b/pandas-stubs/core/indexing.pyi @@ -4,9 +4,14 @@ import numpy as np from pandas.core.indexes.api import Index from pandas._libs.indexing import _NDFrameIndexerBase -from pandas._typing import IndexSliceTuple +from pandas._typing import ( + MaskType, + Scalar, +) -_IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=IndexSliceTuple) +_IndexSliceTuple = slice | tuple[Index | MaskType | Scalar | list[Scalar] | slice, ...] + +_IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=_IndexSliceTuple) class _IndexSlice: def __getitem__(self, arg: _IndexSliceTupleT) -> _IndexSliceTupleT: ... From bc44d011c309a38657120f7c62f8801fa55bcb41 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sat, 17 Sep 2022 16:13:14 -0400 Subject: [PATCH 3/5] fix for python 3.8 --- pandas-stubs/core/indexing.pyi | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/core/indexing.pyi b/pandas-stubs/core/indexing.pyi index a18b8f80b..ef03a6233 100644 --- a/pandas-stubs/core/indexing.pyi +++ b/pandas-stubs/core/indexing.pyi @@ -1,4 +1,7 @@ -from typing import TypeVar +from typing import ( + TypeVar, + Union, +) import numpy as np from pandas.core.indexes.api import Index @@ -9,7 +12,9 @@ from pandas._typing import ( Scalar, ) -_IndexSliceTuple = slice | tuple[Index | MaskType | Scalar | list[Scalar] | slice, ...] +_IndexSliceTuple = Union[ + slice, tuple[Union[Index, MaskType, Scalar, list[Scalar], slice], ...] +] _IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=_IndexSliceTuple) From e843c9679fb21f97cde7263236a798dd084dee6c Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sat, 17 Sep 2022 19:09:29 -0400 Subject: [PATCH 4/5] add tests. Move IndexSlice to typing so flake8 is happy --- pandas-stubs/_typing.pyi | 3 +++ pandas-stubs/core/indexing.pyi | 16 +++------------- tests/test_frame.py | 10 ++++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index f67b3f908..c82b02e5b 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -175,6 +175,9 @@ NDFrameT = TypeVar("NDFrameT", bound=NDFrame) IndexT = TypeVar("IndexT", bound=Index) +IndexSliceTuple = Union[ + slice, tuple[Union[Index, MaskType, Scalar, list[ScalarT], slice], ...] +] # Interval closed type IntervalClosedType = Literal["left", "right", "both", "neither"] diff --git a/pandas-stubs/core/indexing.pyi b/pandas-stubs/core/indexing.pyi index ef03a6233..a158b874c 100644 --- a/pandas-stubs/core/indexing.pyi +++ b/pandas-stubs/core/indexing.pyi @@ -1,22 +1,12 @@ -from typing import ( - TypeVar, - Union, -) +from typing import TypeVar import numpy as np from pandas.core.indexes.api import Index from pandas._libs.indexing import _NDFrameIndexerBase -from pandas._typing import ( - MaskType, - Scalar, -) +from pandas._typing import IndexSliceTuple -_IndexSliceTuple = Union[ - slice, tuple[Union[Index, MaskType, Scalar, list[Scalar], slice], ...] -] - -_IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=_IndexSliceTuple) +_IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=IndexSliceTuple) class _IndexSlice: def __getitem__(self, arg: _IndexSliceTupleT) -> _IndexSliceTupleT: ... diff --git a/tests/test_frame.py b/tests/test_frame.py index f46ef2b16..feb5ed3c6 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1288,6 +1288,16 @@ def test_indexslice_getitem(): ind = pd.Index([2, 3]) check(assert_type(pd.IndexSlice[ind, :], tuple[pd.Index, slice]), tuple) check(assert_type(df.loc[pd.IndexSlice[ind, :]], pd.DataFrame), pd.DataFrame) + check(assert_type(df.loc[pd.IndexSlice[1:2]], pd.DataFrame), pd.DataFrame) + check( + assert_type(df.loc[pd.IndexSlice[:, df["z"] > 40], :], pd.DataFrame), + pd.DataFrame, + ) + check(assert_type(df.loc[pd.IndexSlice[2, 30], "z"], Scalar), np.int64) + check( + assert_type(df.loc[pd.IndexSlice[[2, 4], [20, 40]], :], pd.DataFrame), + pd.DataFrame, + ) def test_compute_values(): From 486fdf8813e7b2c48d0c2dec0dec60fe839fa324 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sun, 18 Sep 2022 00:29:20 -0400 Subject: [PATCH 5/5] fix test to surround tuple with quotes --- pandas-stubs/_typing.pyi | 3 --- pandas-stubs/core/indexing.pyi | 17 ++++++++++++++--- tests/test_frame.py | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/pandas-stubs/_typing.pyi b/pandas-stubs/_typing.pyi index c82b02e5b..f67b3f908 100644 --- a/pandas-stubs/_typing.pyi +++ b/pandas-stubs/_typing.pyi @@ -175,9 +175,6 @@ NDFrameT = TypeVar("NDFrameT", bound=NDFrame) IndexT = TypeVar("IndexT", bound=Index) -IndexSliceTuple = Union[ - slice, tuple[Union[Index, MaskType, Scalar, list[ScalarT], slice], ...] -] # Interval closed type IntervalClosedType = Literal["left", "right", "both", "neither"] diff --git a/pandas-stubs/core/indexing.pyi b/pandas-stubs/core/indexing.pyi index a158b874c..90374106b 100644 --- a/pandas-stubs/core/indexing.pyi +++ b/pandas-stubs/core/indexing.pyi @@ -1,12 +1,23 @@ -from typing import TypeVar +from typing import ( + TypeVar, + Union, +) import numpy as np from pandas.core.indexes.api import Index from pandas._libs.indexing import _NDFrameIndexerBase -from pandas._typing import IndexSliceTuple +from pandas._typing import ( + MaskType, + Scalar, + ScalarT, +) -_IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=IndexSliceTuple) +_IndexSliceTuple = Union[ + slice, tuple[Union[Index, MaskType, Scalar, list[ScalarT], slice], ...] +] + +_IndexSliceTupleT = TypeVar("_IndexSliceTupleT", bound=_IndexSliceTuple) class _IndexSlice: def __getitem__(self, arg: _IndexSliceTupleT) -> _IndexSliceTupleT: ... diff --git a/tests/test_frame.py b/tests/test_frame.py index feb5ed3c6..d4c4f2f6c 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1286,7 +1286,7 @@ def test_indexslice_getitem(): .set_index(["x", "y"]) ) ind = pd.Index([2, 3]) - check(assert_type(pd.IndexSlice[ind, :], tuple[pd.Index, slice]), tuple) + check(assert_type(pd.IndexSlice[ind, :], "tuple[pd.Index, slice]"), tuple) check(assert_type(df.loc[pd.IndexSlice[ind, :]], pd.DataFrame), pd.DataFrame) check(assert_type(df.loc[pd.IndexSlice[1:2]], pd.DataFrame), pd.DataFrame) check(