From 7a47b42313d7c280a0bfbfac35d6b05c8b91125a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Tue, 20 May 2025 21:08:00 -0400 Subject: [PATCH 1/7] GH1226 Add Styler.map to the stubs --- pandas-stubs/io/formats/style.pyi | 3 +++ tests/test_styler.py | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pandas-stubs/io/formats/style.pyi b/pandas-stubs/io/formats/style.pyi index aea4da64..1c46ea77 100644 --- a/pandas-stubs/io/formats/style.pyi +++ b/pandas-stubs/io/formats/style.pyi @@ -71,6 +71,9 @@ class Styler(StylerRenderer): formatter: ExtFormatter | None = ..., ) -> None: ... def concat(self, other: Styler) -> Styler: ... + def map( + self, func: Callable, subset: Subset | None = ..., **kwargs: Any + ) -> Styler: ... def set_tooltips( self, ttips: DataFrame, diff --git a/tests/test_styler.py b/tests/test_styler.py index 3293a173..ecf767d4 100644 --- a/tests/test_styler.py +++ b/tests/test_styler.py @@ -30,7 +30,6 @@ DF = DataFrame({"a": [1, 2, 3], "b": [3.14, 2.72, 1.61]}) - PWD = pathlib.Path(os.path.split(os.path.abspath(__file__))[0]) if TYPE_CHECKING: @@ -233,3 +232,12 @@ def test_styler_columns_and_index() -> None: styler = DF.style check(assert_type(styler.columns, Index), Index) check(assert_type(styler.index, Index), Index) + + +def test_styler_map() -> None: + """Test type returned with Styler.map GH1226.""" + df = DataFrame(data={"col1": [1, -2], "col2": [-3, 4]}) + check( + assert_type(df.style.map(lambda v: "color: red;" if v < 0 else None), Styler), + Styler, + ) From a3357a3bdd71953cdfecd90f5134ca5bb9ce2d20 Mon Sep 17 00:00:00 2001 From: Loic Diridollou Date: Wed, 21 May 2025 17:31:23 -0400 Subject: [PATCH 2/7] Update pandas-stubs/io/formats/style.pyi Co-authored-by: Irv Lustig --- pandas-stubs/io/formats/style.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas-stubs/io/formats/style.pyi b/pandas-stubs/io/formats/style.pyi index 1c46ea77..b6df5b2a 100644 --- a/pandas-stubs/io/formats/style.pyi +++ b/pandas-stubs/io/formats/style.pyi @@ -72,7 +72,7 @@ class Styler(StylerRenderer): ) -> None: ... def concat(self, other: Styler) -> Styler: ... def map( - self, func: Callable, subset: Subset | None = ..., **kwargs: Any + self, func: Callable[[Scalar], str], subset: Subset | None = ..., **kwargs: dict[str, Any] ) -> Styler: ... def set_tooltips( self, From 85eac7a5404f5da615ae6b0b20d2a9af4b88fd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Wed, 21 May 2025 17:51:47 -0400 Subject: [PATCH 3/7] GH1226 PR Feedback --- pandas-stubs/io/formats/style.pyi | 5 ++++- tests/test_styler.py | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/io/formats/style.pyi b/pandas-stubs/io/formats/style.pyi index b6df5b2a..19eef44e 100644 --- a/pandas-stubs/io/formats/style.pyi +++ b/pandas-stubs/io/formats/style.pyi @@ -72,7 +72,10 @@ class Styler(StylerRenderer): ) -> None: ... def concat(self, other: Styler) -> Styler: ... def map( - self, func: Callable[[Scalar], str], subset: Subset | None = ..., **kwargs: dict[str, Any] + self, + func: Callable[[Scalar], str | None], + subset: Subset | None = ..., + **kwargs: dict[str, Any], ) -> Styler: ... def set_tooltips( self, diff --git a/tests/test_styler.py b/tests/test_styler.py index ecf767d4..f962c73f 100644 --- a/tests/test_styler.py +++ b/tests/test_styler.py @@ -238,6 +238,11 @@ def test_styler_map() -> None: """Test type returned with Styler.map GH1226.""" df = DataFrame(data={"col1": [1, -2], "col2": [-3, 4]}) check( - assert_type(df.style.map(lambda v: "color: red;" if v < 0 else None), Styler), + assert_type( + df.style.map( + lambda v: "color: red;" if isinstance(v, float) and v < 0 else None + ), + Styler, + ), Styler, ) From 75b9ad92883ea308ae6bb0bf8b3a013a6549c771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Wed, 21 May 2025 19:20:55 -0400 Subject: [PATCH 4/7] GH1226 PR Feedback --- pandas-stubs/io/formats/style.pyi | 9 ++++++++- tests/test_styler.py | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/io/formats/style.pyi b/pandas-stubs/io/formats/style.pyi index 19eef44e..502f7794 100644 --- a/pandas-stubs/io/formats/style.pyi +++ b/pandas-stubs/io/formats/style.pyi @@ -71,11 +71,18 @@ class Styler(StylerRenderer): formatter: ExtFormatter | None = ..., ) -> None: ... def concat(self, other: Styler) -> Styler: ... + @overload def map( self, func: Callable[[Scalar], str | None], subset: Subset | None = ..., - **kwargs: dict[str, Any], + ) -> Styler: ... + @overload + def map( + self, + func: Callable[..., str | None], + subset: Subset | None = ..., + **kwargs: Any, ) -> Styler: ... def set_tooltips( self, diff --git a/tests/test_styler.py b/tests/test_styler.py index f962c73f..9ad75956 100644 --- a/tests/test_styler.py +++ b/tests/test_styler.py @@ -2,7 +2,10 @@ import os import pathlib -from typing import TYPE_CHECKING +from typing import ( + TYPE_CHECKING, + Any, +) from jinja2.environment import ( Environment, @@ -246,3 +249,16 @@ def test_styler_map() -> None: ), Styler, ) + + def color_negative(v: Scalar, color: str) -> str | None: + return f"color: {color};" if isinstance(v, float) and v < 0 else None + + df = DataFrame(np.random.randn(5, 2), columns=["A", "B"]) + + check( + assert_type( + df.style.map(color_negative, color="red"), + Styler, + ), + Styler, + ) From b7a991b5c5476c2a8a35c70bc889024bfb4f9988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Wed, 21 May 2025 19:21:20 -0400 Subject: [PATCH 5/7] GH1226 PR Feedback --- tests/test_styler.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/test_styler.py b/tests/test_styler.py index 9ad75956..3678587d 100644 --- a/tests/test_styler.py +++ b/tests/test_styler.py @@ -2,10 +2,7 @@ import os import pathlib -from typing import ( - TYPE_CHECKING, - Any, -) +from typing import TYPE_CHECKING from jinja2.environment import ( Environment, From 6dd566a49a825d0e6bc3065e2534e0cadeda51cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Thu, 22 May 2025 22:36:47 -0400 Subject: [PATCH 6/7] GH1226 PR Feedback --- pandas-stubs/io/formats/style.pyi | 9 ++++++++- tests/test_styler.py | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pandas-stubs/io/formats/style.pyi b/pandas-stubs/io/formats/style.pyi index 502f7794..86cf20dc 100644 --- a/pandas-stubs/io/formats/style.pyi +++ b/pandas-stubs/io/formats/style.pyi @@ -53,6 +53,13 @@ class _DataFrameFunc(Protocol): self, series: DataFrame, /, *args: Any, **kwargs: Any ) -> npt.NDArray | DataFrame: ... +class _MapCallable(Protocol): + """Dedicated signature for functions passed in Styler.map.""" + + def __call__( + self, first_arg: Scalar, /, *args: Any, **kwargs: Any + ) -> str | None: ... + class Styler(StylerRenderer): def __init__( self, @@ -80,7 +87,7 @@ class Styler(StylerRenderer): @overload def map( self, - func: Callable[..., str | None], + func: _MapCallable, subset: Subset | None = ..., **kwargs: Any, ) -> Styler: ... diff --git a/tests/test_styler.py b/tests/test_styler.py index 3678587d..0efff33c 100644 --- a/tests/test_styler.py +++ b/tests/test_styler.py @@ -247,7 +247,7 @@ def test_styler_map() -> None: Styler, ) - def color_negative(v: Scalar, color: str) -> str | None: + def color_negative(v: Scalar, /, color: str) -> str | None: return f"color: {color};" if isinstance(v, float) and v < 0 else None df = DataFrame(np.random.randn(5, 2), columns=["A", "B"]) From 8196941850627f9f48aacd3d878d8701ab7371a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Diridollou?= Date: Thu, 22 May 2025 22:38:48 -0400 Subject: [PATCH 7/7] GH1226 PR Feedback --- pandas-stubs/io/formats/style.pyi | 2 -- 1 file changed, 2 deletions(-) diff --git a/pandas-stubs/io/formats/style.pyi b/pandas-stubs/io/formats/style.pyi index 86cf20dc..cf0ec7f6 100644 --- a/pandas-stubs/io/formats/style.pyi +++ b/pandas-stubs/io/formats/style.pyi @@ -54,8 +54,6 @@ class _DataFrameFunc(Protocol): ) -> npt.NDArray | DataFrame: ... class _MapCallable(Protocol): - """Dedicated signature for functions passed in Styler.map.""" - def __call__( self, first_arg: Scalar, /, *args: Any, **kwargs: Any ) -> str | None: ...