From 4d93e7c52b39c636762f39e64323afaade43d9b1 Mon Sep 17 00:00:00 2001 From: David Poznik Date: Thu, 21 Nov 2024 13:23:06 -0800 Subject: [PATCH 1/8] Add `hdf5` requirement to setup instructions --- docs/setup.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/setup.md b/docs/setup.md index 402a18ecb..27cf9cf91 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -1,6 +1,7 @@ ## Set Up Environment - Make sure you have `python >= 3.10` installed. +- Make sure you have `hdf5` installed. - Install poetry: `pip install 'poetry>=1.8'` - Install the project dependencies: `poetry update` - Enter the virtual environment: `poetry shell` From b038f5bb9d9fd12b47073b5dc1e53440113ef602 Mon Sep 17 00:00:00 2001 From: David Poznik Date: Thu, 21 Nov 2024 14:16:05 -0800 Subject: [PATCH 2/8] Fix `Series.rename_axis` and `DataFrame.rename_axis` typing --- pandas-stubs/core/frame.pyi | 16 ++++++++++------ pandas-stubs/core/series.pyi | 29 +++++++++++++++++++++++------ tests/test_frame.py | 21 +++++++++++++++++++++ tests/test_series.py | 15 ++++++++++++++- 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/pandas-stubs/core/frame.pyi b/pandas-stubs/core/frame.pyi index b574fb213..c179b755f 100644 --- a/pandas-stubs/core/frame.pyi +++ b/pandas-stubs/core/frame.pyi @@ -2070,40 +2070,44 @@ class DataFrame(NDFrame, OpsMixin): limit: int | None = ..., tolerance=..., ) -> DataFrame: ... + # Rename axis with `mapper`, `axis`, and `inplace=True` @overload def rename_axis( self, - mapper=..., + mapper: Scalar | ListLike | None = ..., + *, axis: Axis | None = ..., copy: _bool = ..., - *, inplace: Literal[True], ) -> None: ... + # Rename axis with `mapper`, `axis`, and `inplace=False` @overload def rename_axis( self, - mapper=..., + mapper: Scalar | ListLike | None = ..., + *, axis: Axis | None = ..., copy: _bool = ..., - *, inplace: Literal[False] = ..., ) -> DataFrame: ... + # Rename axis with `index` and/or `columns` and `inplace=True` @overload def rename_axis( self, + *, index: _str | Sequence[_str] | dict[_str | int, _str] | Callable | None = ..., columns: _str | Sequence[_str] | dict[_str | int, _str] | Callable | None = ..., copy: _bool = ..., - *, inplace: Literal[True], ) -> None: ... + # Rename axis with `index` and/or `columns` and `inplace=False` @overload def rename_axis( self, + *, index: _str | Sequence[_str] | dict[_str | int, _str] | Callable | None = ..., columns: _str | Sequence[_str] | dict[_str | int, _str] | Callable | None = ..., copy: _bool = ..., - *, inplace: Literal[False] = ..., ) -> DataFrame: ... def rfloordiv( diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index e629c5e01..cc8ceecb3 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2076,24 +2076,41 @@ class Series(IndexOpsMixin[S1], NDFrame): numeric_only: _bool = ..., **kwargs, ) -> Scalar: ... + # Rename axis with `mapper`, `axis`, and `inplace=True` @overload def rename_axis( self, - mapper: Scalar | ListLike = ..., - index: Scalar | ListLike | Callable | dict | None = ..., - columns: Scalar | ListLike | Callable | dict | None = ..., + mapper: Scalar | ListLike | None = ..., + *, axis: AxisIndex | None = ..., copy: _bool = ..., + inplace: Literal[True], + ) -> None: ... + # Rename axis with `mapper`, `axis`, and `inplace=False` + @overload + def rename_axis( + self, + mapper: Scalar | ListLike | None = ..., *, + axis: AxisIndex | None = ..., + copy: _bool = ..., + inplace: Literal[False] = ..., + ) -> Self: ... + # Rename axis with `index` and `inplace=True` + @overload + def rename_axis( + self, + *, + index: Scalar | ListLike | Callable | dict | None = ..., + copy: _bool = ..., inplace: Literal[True], ) -> None: ... + # Rename axis with `index` and `inplace=True` @overload def rename_axis( self, - mapper: Scalar | ListLike = ..., + *, index: Scalar | ListLike | Callable | dict | None = ..., - columns: Scalar | ListLike | Callable | dict | None = ..., - axis: AxisIndex | None = ..., copy: _bool = ..., inplace: Literal[False] = ..., ) -> Self: ... diff --git a/tests/test_frame.py b/tests/test_frame.py index 1d7e04682..a17fb948e 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1955,6 +1955,27 @@ def test_types_rename() -> None: df.rename(columns=lambda s: s.upper()) +def test_types_rename_axis() -> None: + df = pd.DataFrame({"col_name": [1, 2, 3]}) + df.index.name = "a" + df.columns.name = "b" + + # Rename axes with `mapper` and `axis` + df.rename_axis("A") + df.rename_axis(["A"]) + df.rename_axis(None) + df.rename_axis("B", axis=1) + df.rename_axis(["B"], axis=1) + df.rename_axis(None, axis=1) + + # Rename axes with `index` and `columns` + df.rename_axis(index="A", columns="B") + df.rename_axis(index=["A"], columns=["B"]) + df.rename_axis(index={"a": "A"}, columns={"b": "B"}) + df.rename_axis(index=lambda name: name.upper(), columns=lambda name: name.upper()) + df.rename_axis(index=None, columns=None) + + def test_types_eq() -> None: df1 = pd.DataFrame([[1, 2], [8, 9]], columns=["A", "B"]) res1: pd.DataFrame = df1 == 1 diff --git a/tests/test_series.py b/tests/test_series.py index 98284cc02..7e86653bb 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -1121,7 +1121,20 @@ def test_types_eq() -> None: def test_types_rename_axis() -> None: - s: pd.Series = pd.Series([1, 2, 3]).rename_axis("A") + s = pd.Series([1, 2, 3]) + s.index.name = "a" + + # Rename index with `mapper` + s.rename_axis("A") + s.rename_axis(["A"]) + s.rename_axis(None) + + # Rename index with `index` + s.rename_axis(index="A") + s.rename_axis(index=["A"]) + s.rename_axis(index={"a": "A"}) + s.rename_axis(index=lambda name: name.upper()) + s.rename_axis(index=None) def test_types_values() -> None: From 5392d9b1cf0c60a8571ddb7664535a41be4ac9e7 Mon Sep 17 00:00:00 2001 From: David Poznik Date: Thu, 21 Nov 2024 16:13:47 -0800 Subject: [PATCH 3/8] Fix comment --- pandas-stubs/core/series.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index cc8ceecb3..c60548e90 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -2105,7 +2105,7 @@ class Series(IndexOpsMixin[S1], NDFrame): copy: _bool = ..., inplace: Literal[True], ) -> None: ... - # Rename axis with `index` and `inplace=True` + # Rename axis with `index` and `inplace=False` @overload def rename_axis( self, From af01cc3bbb5ead3cc35eed3615c3df567f08d284 Mon Sep 17 00:00:00 2001 From: David Poznik Date: Thu, 21 Nov 2024 16:11:24 -0800 Subject: [PATCH 4/8] Use `check(assert_type(...))` framework in tests --- tests/test_frame.py | 31 ++++++++++++++++++++----------- tests/test_series.py | 22 ++++++++++++++-------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/tests/test_frame.py b/tests/test_frame.py index a17fb948e..575f1bb61 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1961,19 +1961,28 @@ def test_types_rename_axis() -> None: df.columns.name = "b" # Rename axes with `mapper` and `axis` - df.rename_axis("A") - df.rename_axis(["A"]) - df.rename_axis(None) - df.rename_axis("B", axis=1) - df.rename_axis(["B"], axis=1) - df.rename_axis(None, axis=1) + for _df in [ + df.rename_axis("A"), + df.rename_axis(["A"]), + df.rename_axis(None), + df.rename_axis("B", axis=1), + df.rename_axis(["B"], axis=1), + df.rename_axis(None, axis=1), + ]: + check(assert_type(_df, pd.DataFrame), pd.DataFrame) # Rename axes with `index` and `columns` - df.rename_axis(index="A", columns="B") - df.rename_axis(index=["A"], columns=["B"]) - df.rename_axis(index={"a": "A"}, columns={"b": "B"}) - df.rename_axis(index=lambda name: name.upper(), columns=lambda name: name.upper()) - df.rename_axis(index=None, columns=None) + for _df in [ + df.rename_axis(index="A", columns="B"), + df.rename_axis(index=["A"], columns=["B"]), + df.rename_axis(index={"a": "A"}, columns={"b": "B"}), + df.rename_axis( + index=lambda name: name.upper(), + columns=lambda name: name.upper(), + ), + df.rename_axis(index=None, columns=None), + ]: + check(assert_type(_df, pd.DataFrame), pd.DataFrame) def test_types_eq() -> None: diff --git a/tests/test_series.py b/tests/test_series.py index 7e86653bb..03c2597c7 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -1125,16 +1125,22 @@ def test_types_rename_axis() -> None: s.index.name = "a" # Rename index with `mapper` - s.rename_axis("A") - s.rename_axis(["A"]) - s.rename_axis(None) + for _s in [ + s.rename_axis("A"), + s.rename_axis(["A"]), + s.rename_axis(None), + ]: + check(assert_type(_s, pd.Series[int]), pd.Series[int]) # Rename index with `index` - s.rename_axis(index="A") - s.rename_axis(index=["A"]) - s.rename_axis(index={"a": "A"}) - s.rename_axis(index=lambda name: name.upper()) - s.rename_axis(index=None) + for _s in [ + s.rename_axis(index="A"), + s.rename_axis(index=["A"]), + s.rename_axis(index={"a": "A"}), + s.rename_axis(index=lambda name: name.upper()), + s.rename_axis(index=None), + ]: + check(assert_type(_s, pd.Series[int]), pd.Series[int]) def test_types_values() -> None: From 76250174c2a7ebb86aef39713f9039d6e5f4f146 Mon Sep 17 00:00:00 2001 From: David Poznik Date: Thu, 21 Nov 2024 16:18:17 -0800 Subject: [PATCH 5/8] Combine loops --- tests/test_frame.py | 8 ++------ tests/test_series.py | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/tests/test_frame.py b/tests/test_frame.py index 575f1bb61..3b5fb03a1 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1960,19 +1960,15 @@ def test_types_rename_axis() -> None: df.index.name = "a" df.columns.name = "b" - # Rename axes with `mapper` and `axis` for _df in [ + # Rename axes with `mapper` and `axis` df.rename_axis("A"), df.rename_axis(["A"]), df.rename_axis(None), df.rename_axis("B", axis=1), df.rename_axis(["B"], axis=1), df.rename_axis(None, axis=1), - ]: - check(assert_type(_df, pd.DataFrame), pd.DataFrame) - - # Rename axes with `index` and `columns` - for _df in [ + # Rename axes with `index` and `columns` df.rename_axis(index="A", columns="B"), df.rename_axis(index=["A"], columns=["B"]), df.rename_axis(index={"a": "A"}, columns={"b": "B"}), diff --git a/tests/test_series.py b/tests/test_series.py index 03c2597c7..3656e1a2a 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -1124,16 +1124,12 @@ def test_types_rename_axis() -> None: s = pd.Series([1, 2, 3]) s.index.name = "a" - # Rename index with `mapper` for _s in [ + # Rename index with `mapper` s.rename_axis("A"), s.rename_axis(["A"]), s.rename_axis(None), - ]: - check(assert_type(_s, pd.Series[int]), pd.Series[int]) - - # Rename index with `index` - for _s in [ + # Rename index with `index` s.rename_axis(index="A"), s.rename_axis(index=["A"]), s.rename_axis(index={"a": "A"}), From 0f38baabcd73a671bff930c3de5bfb1b65532c69 Mon Sep 17 00:00:00 2001 From: David Poznik Date: Fri, 22 Nov 2024 09:15:18 -0800 Subject: [PATCH 6/8] Restrict `hdf5` instruction to macOS --- docs/setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/setup.md b/docs/setup.md index 27cf9cf91..88927e02b 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -1,7 +1,7 @@ ## Set Up Environment - Make sure you have `python >= 3.10` installed. -- Make sure you have `hdf5` installed. +- If using macOS, you may need to install `hdf5` (e.g., via `brew install hdf5`). - Install poetry: `pip install 'poetry>=1.8'` - Install the project dependencies: `poetry update` - Enter the virtual environment: `poetry shell` From 7ced65d2d6271c390feb0b937edebf7d98bf281d Mon Sep 17 00:00:00 2001 From: David Poznik Date: Fri, 22 Nov 2024 09:33:57 -0800 Subject: [PATCH 7/8] Inline `check(assert_type(...))` calls --- tests/test_frame.py | 52 +++++++++++++++++++++++++++++--------------- tests/test_series.py | 27 ++++++++++++----------- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/tests/test_frame.py b/tests/test_frame.py index 3b5fb03a1..69f257b8b 100644 --- a/tests/test_frame.py +++ b/tests/test_frame.py @@ -1960,25 +1960,41 @@ def test_types_rename_axis() -> None: df.index.name = "a" df.columns.name = "b" - for _df in [ - # Rename axes with `mapper` and `axis` - df.rename_axis("A"), - df.rename_axis(["A"]), - df.rename_axis(None), - df.rename_axis("B", axis=1), - df.rename_axis(["B"], axis=1), - df.rename_axis(None, axis=1), - # Rename axes with `index` and `columns` - df.rename_axis(index="A", columns="B"), - df.rename_axis(index=["A"], columns=["B"]), - df.rename_axis(index={"a": "A"}, columns={"b": "B"}), - df.rename_axis( - index=lambda name: name.upper(), - columns=lambda name: name.upper(), + # Rename axes with `mapper` and `axis` + check(assert_type(df.rename_axis("A"), pd.DataFrame), pd.DataFrame) + check(assert_type(df.rename_axis(["A"]), pd.DataFrame), pd.DataFrame) + check(assert_type(df.rename_axis(None), pd.DataFrame), pd.DataFrame) + check(assert_type(df.rename_axis("B", axis=1), pd.DataFrame), pd.DataFrame) + check(assert_type(df.rename_axis(["B"], axis=1), pd.DataFrame), pd.DataFrame) + check(assert_type(df.rename_axis(None, axis=1), pd.DataFrame), pd.DataFrame) + + # Rename axes with `index` and `columns` + check( + assert_type(df.rename_axis(index="A", columns="B"), pd.DataFrame), + pd.DataFrame, + ) + check( + assert_type(df.rename_axis(index=["A"], columns=["B"]), pd.DataFrame), + pd.DataFrame, + ) + check( + assert_type(df.rename_axis(index={"a": "A"}, columns={"b": "B"}), pd.DataFrame), + pd.DataFrame, + ) + check( + assert_type( + df.rename_axis( + index=lambda name: name.upper(), + columns=lambda name: name.upper(), + ), + pd.DataFrame, ), - df.rename_axis(index=None, columns=None), - ]: - check(assert_type(_df, pd.DataFrame), pd.DataFrame) + pd.DataFrame, + ) + check( + assert_type(df.rename_axis(index=None, columns=None), pd.DataFrame), + pd.DataFrame, + ) def test_types_eq() -> None: diff --git a/tests/test_series.py b/tests/test_series.py index 3656e1a2a..9d583a1ef 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -1124,19 +1124,20 @@ def test_types_rename_axis() -> None: s = pd.Series([1, 2, 3]) s.index.name = "a" - for _s in [ - # Rename index with `mapper` - s.rename_axis("A"), - s.rename_axis(["A"]), - s.rename_axis(None), - # Rename index with `index` - s.rename_axis(index="A"), - s.rename_axis(index=["A"]), - s.rename_axis(index={"a": "A"}), - s.rename_axis(index=lambda name: name.upper()), - s.rename_axis(index=None), - ]: - check(assert_type(_s, pd.Series[int]), pd.Series[int]) + # Rename index with `mapper` + check(assert_type(s.rename_axis("A"), "pd.Series[int]"), pd.Series) + check(assert_type(s.rename_axis(["A"]), "pd.Series[int]"), pd.Series) + check(assert_type(s.rename_axis(None), "pd.Series[int]"), pd.Series) + + # Rename index with `index` + check(assert_type(s.rename_axis(index="A"), "pd.Series[int]"), pd.Series) + check(assert_type(s.rename_axis(index=["A"]), "pd.Series[int]"), pd.Series) + check(assert_type(s.rename_axis(index={"a": "A"}), "pd.Series[int]"), pd.Series) + check( + assert_type(s.rename_axis(index=lambda name: name.upper()), "pd.Series[int]"), + pd.Series, + ) + check(assert_type(s.rename_axis(index=None), "pd.Series[int]"), pd.Series) def test_types_values() -> None: From e1ca706a05f9566cb6810b644c1457a951e6d39c Mon Sep 17 00:00:00 2001 From: David Poznik Date: Fri, 22 Nov 2024 09:47:40 -0800 Subject: [PATCH 8/8] Check invalid usage of `columns` --- tests/test_series.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_series.py b/tests/test_series.py index 9d583a1ef..d48f0befd 100644 --- a/tests/test_series.py +++ b/tests/test_series.py @@ -1139,6 +1139,9 @@ def test_types_rename_axis() -> None: ) check(assert_type(s.rename_axis(index=None), "pd.Series[int]"), pd.Series) + if TYPE_CHECKING_INVALID_USAGE: + s.rename_axis(columns="A") # type: ignore[call-overload] # pyright: ignore[reportCallIssue] + def test_types_values() -> None: n1: np.ndarray | ExtensionArray = pd.Series([1, 2, 3]).values