From 389e5f50f8879b7d79525a6e1f5351f4d66beaa1 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 25 Jan 2021 12:58:39 +0100 Subject: [PATCH 1/5] bug re-render styler _todo --- pandas/io/formats/style.py | 6 +++--- pandas/tests/io/formats/test_style.py | 13 +++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 73b62a99f4a7e..0cb9aa3bea6ab 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -830,6 +830,7 @@ def _compute(self): r = self for func, args, kwargs in self._todo: r = func(self)(*args, **kwargs) + self._todo = [] return r def _apply( @@ -1454,9 +1455,8 @@ def set_properties(self, subset=None, **kwargs) -> Styler: >>> df.style.set_properties(color="white", align="right") >>> df.style.set_properties(**{'background-color': 'yellow'}) """ - values = ";".join(f"{p}: {v}" for p, v in kwargs.items()) - f = lambda x: values - return self.applymap(f, subset=subset) + values = "".join(f"{p}: {v};" for p, v in kwargs.items()) + return self.applymap(lambda x: values, subset=subset) @staticmethod def _bar( diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index 51810786395b5..9e64bc7eb55ad 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -102,12 +102,21 @@ def test_deepcopy(self): assert self.styler._todo != s2._todo def test_clear(self): - s = self.df.style.highlight_max()._compute() - assert len(s.ctx) > 0 + tt = DataFrame({"A": [None, "tt"]}) + css = DataFrame({"A": [None, "cls-a"]}) + s = self.df.style.highlight_max().set_tooltips(tt).set_td_classes(css) assert len(s._todo) > 0 + assert s.tooltips + assert len(s.cell_context) > 0 + s = s._compute() + assert len(s.ctx) > 0 + assert len(s._todo) == 0 + s._todo = [1] s.clear() assert len(s.ctx) == 0 assert len(s._todo) == 0 + assert not s.tooltips + assert len(s.cell_context) == 0 def test_render(self): df = DataFrame({"A": [0, 1]}) From 04a30e53a92270b3e642d9fa7c694874aa1043da Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 25 Jan 2021 17:21:08 +0100 Subject: [PATCH 2/5] text comments --- pandas/tests/io/formats/test_style.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index 9e64bc7eb55ad..7079182c1f6e8 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -105,14 +105,17 @@ def test_clear(self): tt = DataFrame({"A": [None, "tt"]}) css = DataFrame({"A": [None, "cls-a"]}) s = self.df.style.highlight_max().set_tooltips(tt).set_td_classes(css) + # _todo, tooltips and cell_context items all affected.. assert len(s._todo) > 0 assert s.tooltips assert len(s.cell_context) > 0 s = s._compute() + # ctx and _todo items affected assert len(s.ctx) > 0 - assert len(s._todo) == 0 + assert len(s._todo) == 0 # _todo is emptied after compute. s._todo = [1] s.clear() + # ctx, _todo, tooltips and cell_context items all revert to null state. assert len(s.ctx) == 0 assert len(s._todo) == 0 assert not s.tooltips From 48818fbe07f7310444e2a417dd10848b8572b45b Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 25 Jan 2021 17:24:45 +0100 Subject: [PATCH 3/5] whats new --- doc/source/whatsnew/v1.3.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 67f27a75c7071..d520c20b112e5 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -381,7 +381,7 @@ ExtensionArray Other ^^^^^ - Bug in :class:`Index` constructor sometimes silently ignorning a specified ``dtype`` (:issue:`38879`) -- +- Bug in :class:`Styler` which caused CSS to duplicate on multiple renders. (:issue:`39395`) - .. --------------------------------------------------------------------------- From 06bcfe05ffa53017e11aedd063f97740e0f3236a Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 25 Jan 2021 18:25:23 +0100 Subject: [PATCH 4/5] test --- pandas/tests/io/formats/test_style.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index 7079182c1f6e8..99939ea0cbbfc 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -102,6 +102,7 @@ def test_deepcopy(self): assert self.styler._todo != s2._todo def test_clear(self): + # updated in GH 39396 tt = DataFrame({"A": [None, "tt"]}) css = DataFrame({"A": [None, "cls-a"]}) s = self.df.style.highlight_max().set_tooltips(tt).set_td_classes(css) @@ -128,6 +129,15 @@ def test_render(self): s.render() # it worked? + def test_multiple_render(self): + # GH 39396 + s = Styler(self.df, uuid_len=0).applymap(lambda x: "color: red;", subset=["A"]) + s.render() # do 2 renders to ensure css styles not duplicated + assert ( + '" in s.render() + ) + def test_render_empty_dfs(self): empty_df = DataFrame() es = Styler(empty_df) From aa8d4b4eaca1bef65eb3e47a6decb668fa4e5e39 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Tue, 26 Jan 2021 08:18:17 +0100 Subject: [PATCH 5/5] spaces --- pandas/tests/io/formats/test_style.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index 99939ea0cbbfc..6556075272308 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -106,14 +106,16 @@ def test_clear(self): tt = DataFrame({"A": [None, "tt"]}) css = DataFrame({"A": [None, "cls-a"]}) s = self.df.style.highlight_max().set_tooltips(tt).set_td_classes(css) - # _todo, tooltips and cell_context items all affected.. + # _todo, tooltips and cell_context items added to.. assert len(s._todo) > 0 assert s.tooltips assert len(s.cell_context) > 0 + s = s._compute() - # ctx and _todo items affected + # ctx and _todo items affected when a render takes place assert len(s.ctx) > 0 assert len(s._todo) == 0 # _todo is emptied after compute. + s._todo = [1] s.clear() # ctx, _todo, tooltips and cell_context items all revert to null state.