From fe68e48bd9906ae2af87f5db70238e153c92ff2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Mon, 19 May 2025 18:13:10 -0400 Subject: [PATCH 1/5] GH1217 Modify items/iterros/itertuples methods to return Iterator --- pandas-stubs/core/frame.pyi | 8 ++++---- pandas-stubs/core/series.pyi | 2 +- tests/test_frame.py | 23 ++++++++++++++++------- tests/test_series.py | 7 +++++++ 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index 1f8a2648..25c47523 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -328,16 +328,16 @@ class DataFrame(NDFrame, OpsMixin, _GetItemHack): def shape(self) -> tuple[int, int]: ... @property def style(self) -> Styler: ... - def items(self) -> Iterable[tuple[Hashable, Series]]: ... - def iterrows(self) -> Iterable[tuple[Hashable, Series]]: ... + def items(self) -> Iterator[tuple[Hashable, Series]]: ... + def iterrows(self) -> Iterator[tuple[Hashable, Series]]: ... @overload def itertuples( self, index: _bool = ..., name: _str = ... - ) -> Iterable[_PandasNamedTuple]: ... + ) -> Iterator[_PandasNamedTuple]: ... @overload def itertuples( self, index: _bool = ..., name: None = None - ) -> Iterable[tuple[Any, ...]]: ... + ) -> Iterator[tuple[Any, ...]]: ... def __len__(self) -> int: ... @overload def dot(self, other: DataFrame | ArrayLike) -> Self: ... diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 85943841..625b2824 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -615,7 +615,7 @@ class Series(IndexOpsMixin[S1], NDFrame): mode: Literal["w"] = ..., ) -> _str: ... def to_xarray(self) -> xr.DataArray: ... - def items(self) -> Iterable[tuple[Hashable, S1]]: ... + def items(self) -> Iterator[tuple[Hashable, S1]]: ... def keys(self) -> Index: ... @overload def to_dict(self, *, into: type[dict] = ...) -> dict[Any, S1]: ... diff --git a/tests/test_frame.py b/tests/test_frame.py index 7d4890ee..8af6a7f6 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -599,7 +599,7 @@ def test_types_median() -> None: def test_types_iterrows() -> None: df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) check( - assert_type(df.iterrows(), "Iterable[tuple[Hashable, pd.Series]]"), + assert_type(df.iterrows(), "Iterator[tuple[Hashable, pd.Series]]"), Iterable, tuple, ) @@ -608,24 +608,33 @@ def test_types_iterrows() -> None: def test_types_itertuples() -> None: df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) check( - assert_type(df.itertuples(), Iterable[_PandasNamedTuple]), - Iterable, + assert_type(df.itertuples(), Iterator[_PandasNamedTuple]), + Iterator, _PandasNamedTuple, ) check( assert_type( - df.itertuples(index=False, name="Foobar"), Iterable[_PandasNamedTuple] + df.itertuples(index=False, name="Foobar"), Iterator[_PandasNamedTuple] ), - Iterable, + Iterator, _PandasNamedTuple, ) check( - assert_type(df.itertuples(index=False, name=None), Iterable[tuple[Any, ...]]), - Iterable, + assert_type(df.itertuples(index=False, name=None), Iterator[tuple[Any, ...]]), + Iterator, object, ) +def test_frame_iterator() -> None: + """Test iterator methods for a dataframe GH1217.""" + df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) + + check(assert_type(next(df.items()), tuple[Hashable, "pd.Series"]), tuple) + check(assert_type(next(df.iterrows()), tuple[Hashable, "pd.Series"]), tuple) + check(assert_type(next(df.itertuples()), _PandasNamedTuple), _PandasNamedTuple) + + def test_types_sum() -> None: df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) df.sum() diff --git a/tests/test_series.py b/tests/test_series.py index 9edc8e06..98cfa65d 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -1,6 +1,7 @@ from __future__ import annotations from collections.abc import ( + Hashable, Iterable, Iterator, Sequence, @@ -3797,3 +3798,9 @@ def foo(sf: pd.Series) -> None: foo(s) check(assert_type(s + pd.Series([1]), pd.Series), pd.Series) + + +def test_series_items() -> None: + s = pd.Series(data=[1, 2, 3, 4], index=["cow", "coal", "coalesce", ""]) + check(assert_type(next(s.items()), tuple[Hashable, int]), tuple) + check(assert_type(s.items(), Iterator[tuple[Hashable, int]]), Iterator) From 6d15f0cd921e36583f12f62a0fd361528657ec29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Tue, 20 May 2025 18:21:25 -0400 Subject: [PATCH 2/5] GH1217 PR feedback --- tests/test_frame.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_frame.py b/tests/test_frame.py index 8af6a7f6..2d191cc1 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -603,6 +603,9 @@ def test_types_iterrows() -> None: Iterable, tuple, ) + for t1, t2 in df.iterrows(): + check(assert_type(t1, Hashable), Hashable) + check(assert_type(t2, pd.Series), pd.Series) def test_types_itertuples() -> None: @@ -625,6 +628,9 @@ def test_types_itertuples() -> None: object, ) + for t1 in df.itertuples(): + check(assert_type(t1, _PandasNamedTuple), _PandasNamedTuple) + def test_frame_iterator() -> None: """Test iterator methods for a dataframe GH1217.""" From 5a7fe4094f99136c0b1926163b29e759b0ef087e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Tue, 20 May 2025 18:58:36 -0400 Subject: [PATCH 3/5] GH1217 PR feedback --- tests/test_frame.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_frame.py b/tests/test_frame.py index 2d191cc1..c663b920 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -632,6 +632,19 @@ def test_types_itertuples() -> None: check(assert_type(t1, _PandasNamedTuple), _PandasNamedTuple) +def test_types_items() -> None: + df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) + check( + assert_type(df.items(), Iterator[tuple[Hashable, pd.Series]]), + Iterator, + tuple, + ) + + for t1, t2 in df.items(): + check(assert_type(t1, Hashable), Hashable) + check(assert_type(t2, pd.Series), pd.Series) + + def test_frame_iterator() -> None: """Test iterator methods for a dataframe GH1217.""" df = pd.DataFrame(data={"col1": [2, 1], "col2": [3, 4]}) From 1f91170ef9b2312f7b91825cd39a724d617fa988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Tue, 20 May 2025 20:55:49 -0400 Subject: [PATCH 4/5] GH1217 PR feedback --- tests/test_frame.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/test_frame.py b/tests/test_frame.py index c663b920..eca71b07 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -629,7 +629,22 @@ def test_types_itertuples() -> None: ) for t1 in df.itertuples(): - check(assert_type(t1, _PandasNamedTuple), _PandasNamedTuple) + assert_type(t1, _PandasNamedTuple) + assert t1.__class__.__name__ == "Pandas" + assert isinstance(t1.Index, int) + assert isinstance(t1.col1, int) + assert isinstance(t1.col2, int) + for k in [0, 1]: + assert isinstance(t1[k], int) + + for t1 in df.itertuples(name="FooBar"): + assert_type(t1, _PandasNamedTuple) + assert t1.__class__.__name__ == "FooBar" + assert isinstance(t1.Index, int) + assert isinstance(t1.col1, int) + assert isinstance(t1.col2, int) + for k in [0, 1]: + assert isinstance(t1[k], int) def test_types_items() -> None: From d0a5bf259f3d52515614a84a9e75accb5a8d3f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Wed, 21 May 2025 17:33:08 -0400 Subject: [PATCH 5/5] GH1217 PR feedback --- tests/test_frame.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_frame.py b/tests/test_frame.py index eca71b07..13f9738d 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -634,7 +634,7 @@ def test_types_itertuples() -> None: assert isinstance(t1.Index, int) assert isinstance(t1.col1, int) assert isinstance(t1.col2, int) - for k in [0, 1]: + for k in [0, 1, 2]: assert isinstance(t1[k], int) for t1 in df.itertuples(name="FooBar"): @@ -643,7 +643,7 @@ def test_types_itertuples() -> None: assert isinstance(t1.Index, int) assert isinstance(t1.col1, int) assert isinstance(t1.col2, int) - for k in [0, 1]: + for k in [0, 1, 2]: assert isinstance(t1[k], int)