Skip to content

Commit 56ddecf

Browse files
committed
BUG: Styler copy methods not updated for recent additions (pandas-dev#39708)
1 parent a7402c1 commit 56ddecf

File tree

3 files changed

+123
-5
lines changed

3 files changed

+123
-5
lines changed

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ Other
482482
- Bug in :class:`Styler` where rendered HTML was missing a column class identifier for certain header cells (:issue:`39716`)
483483
- Bug in :meth:`Styler.background_gradient` where text-color was not determined correctly (:issue:`39888`)
484484
- Bug in :meth:`DataFrame.equals`, :meth:`Series.equals`, :meth:`Index.equals` with object-dtype containing ``np.datetime64("NaT")`` or ``np.timedelta64("NaT")`` (:issue:`39650`)
485+
- Bug in :class:`Styler` copy methods which were not updated for recently introduced attributes (:issue:`39708`)
485486

486487

487488
.. ---------------------------------------------------------------------------

pandas/io/formats/style.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -783,15 +783,29 @@ def _copy(self, deepcopy: bool = False) -> Styler:
783783
precision=self.precision,
784784
caption=self.caption,
785785
uuid=self.uuid,
786-
table_styles=self.table_styles,
786+
table_attributes=self.table_attributes,
787+
cell_ids=self.cell_ids,
787788
na_rep=self.na_rep,
789+
uuid_len=self.uuid_len,
788790
)
791+
792+
styler.hidden_index = self.hidden_index
793+
789794
if deepcopy:
790795
styler.ctx = copy.deepcopy(self.ctx)
791796
styler._todo = copy.deepcopy(self._todo)
797+
styler.table_styles = copy.deepcopy(self.table_styles)
798+
styler.hidden_columns = copy.deepcopy(self.hidden_columns)
799+
styler.cell_context = copy.deepcopy(self.cell_context)
800+
styler.tooltips = copy.deepcopy(self.tooltips)
792801
else:
793802
styler.ctx = self.ctx
794803
styler._todo = self._todo
804+
styler.table_styles = self.table_styles
805+
styler.hidden_columns = self.hidden_columns
806+
styler.cell_context = self.cell_context
807+
styler.tooltips = self.tooltips
808+
795809
return styler
796810

797811
def __copy__(self) -> Styler:

pandas/tests/io/formats/test_style.py

+107-4
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,131 @@ def test_update_ctx_flatten_multi_and_trailing_semi(self):
8787
}
8888
assert self.styler.ctx == expected
8989

90-
def test_copy(self):
90+
@pytest.mark.parametrize("do_changes", [True, False])
91+
@pytest.mark.parametrize("do_render", [True, False])
92+
def test_copy(self, do_changes, do_render):
93+
# Updated in GH39708
94+
# Change some defaults (to check later if they are copied)
95+
if do_changes:
96+
style = [{"selector": "th", "props": [("foo", "bar")]}]
97+
self.styler.set_table_styles(style)
98+
attributes = 'class="foo" data-bar'
99+
self.styler.set_table_attributes(attributes)
100+
self.styler.uuid_len += 1
101+
self.styler.hidden_index = not self.styler.hidden_index
102+
self.styler.hide_columns("A")
103+
classes = pd.DataFrame(
104+
[["favorite-val red", ""], [None, "blue my-val"]],
105+
index=self.df.index,
106+
columns=self.df.columns,
107+
)
108+
self.styler.set_td_classes(classes)
109+
ttips = pd.DataFrame(
110+
data=[["Favorite", ""], [np.nan, "my"]],
111+
columns=self.df.columns,
112+
index=self.df.index,
113+
)
114+
self.styler.set_tooltips(ttips)
115+
self.styler.cell_ids = not self.styler.cell_ids
116+
self.styler.format("{:.2%}")
117+
118+
if do_render:
119+
self.styler.render()
120+
91121
s2 = copy.copy(self.styler)
122+
123+
# Check for identity
92124
assert self.styler is not s2
93125
assert self.styler.ctx is s2.ctx # shallow
94126
assert self.styler._todo is s2._todo
95-
127+
assert self.styler.table_styles is s2.table_styles
128+
assert self.styler.hidden_columns is s2.hidden_columns
129+
assert self.styler.cell_context is s2.cell_context
130+
assert self.styler.tooltips is s2.tooltips
131+
if do_changes: # self.styler.tooltips is not None
132+
assert self.styler.tooltips.tt_data is s2.tooltips.tt_data
133+
134+
# Check for equality (and changes in referenced objects)
96135
self.styler._update_ctx(self.attrs)
97136
self.styler.highlight_max()
98137
assert self.styler.ctx == s2.ctx
99138
assert self.styler._todo == s2._todo
139+
assert self.styler.table_styles == s2.table_styles
140+
assert self.styler.table_attributes == s2.table_attributes
141+
assert self.styler.cell_ids == s2.cell_ids
142+
assert self.styler.uuid_len == s2.uuid_len
143+
assert self.styler.hidden_index == s2.hidden_index
144+
assert self.styler.hidden_columns == s2.hidden_columns
145+
assert self.styler.cell_context == s2.cell_context
146+
if do_changes: # self.styler.table_style is not None
147+
self.styler.table_styles[0]["selector"] = "ti"
148+
assert self.styler.table_styles == s2.table_styles
149+
if do_changes: # self.styler.tooltips is not None
150+
tm.assert_frame_equal(self.styler.tooltips.tt_data, s2.tooltips.tt_data)
151+
152+
@pytest.mark.parametrize("do_changes", [True, False])
153+
@pytest.mark.parametrize("do_render", [True, False])
154+
def test_deepcopy(self, do_changes, do_render):
155+
# Updated in GH39708
156+
# Change some defaults (to check later if they are copied)
157+
if do_changes:
158+
style = [{"selector": "th", "props": [("foo", "bar")]}]
159+
self.styler.set_table_styles(style)
160+
attributes = 'class="foo" data-bar'
161+
self.styler.set_table_attributes(attributes)
162+
self.styler.uuid_len += 1
163+
self.styler.hidden_index = not self.styler.hidden_index
164+
self.styler.hide_columns("A")
165+
classes = pd.DataFrame(
166+
[["favorite-val red", ""], [None, "blue my-val"]],
167+
index=self.df.index,
168+
columns=self.df.columns,
169+
)
170+
self.styler.set_td_classes(classes)
171+
ttips = pd.DataFrame(
172+
data=[["Favorite", ""], [np.nan, "my"]],
173+
columns=self.df.columns,
174+
index=self.df.index,
175+
)
176+
self.styler.set_tooltips(ttips)
177+
self.styler.cell_ids = not self.styler.cell_ids
178+
self.styler.format("{:.2%}")
179+
180+
if do_render:
181+
self.styler.render()
100182

101-
def test_deepcopy(self):
102183
s2 = copy.deepcopy(self.styler)
184+
185+
# Check for non-identity
103186
assert self.styler is not s2
104187
assert self.styler.ctx is not s2.ctx
105188
assert self.styler._todo is not s2._todo
106-
189+
assert self.styler.hidden_columns is not s2.hidden_columns
190+
assert self.styler.cell_context is not s2.cell_context
191+
if do_changes: # self.styler.table_style is not None
192+
assert self.styler.table_styles is not s2.table_styles
193+
if do_changes: # self.styler.tooltips is not None
194+
assert self.styler.tooltips is not s2.tooltips
195+
assert self.styler.tooltips.tt_data is not s2.tooltips.tt_data
196+
197+
# Check for equality (and changes in original objects)
107198
self.styler._update_ctx(self.attrs)
108199
self.styler.highlight_max()
109200
assert self.styler.ctx != s2.ctx
110201
assert s2._todo == []
111202
assert self.styler._todo != s2._todo
203+
assert self.styler.table_styles == s2.table_styles
204+
assert self.styler.table_attributes == s2.table_attributes
205+
assert self.styler.cell_ids == s2.cell_ids
206+
assert self.styler.uuid_len == s2.uuid_len
207+
assert self.styler.hidden_index == s2.hidden_index
208+
assert self.styler.hidden_columns == s2.hidden_columns
209+
assert self.styler.cell_context == s2.cell_context
210+
if do_changes: # self.styler.table_style is not None
211+
self.styler.table_styles[0]["selector"] = "ti"
212+
assert self.styler.table_styles != s2.table_styles
213+
if do_changes: # self.styler.tooltips is not None
214+
tm.assert_frame_equal(self.styler.tooltips.tt_data, s2.tooltips.tt_data)
112215

113216
def test_clear(self):
114217
# updated in GH 39396

0 commit comments

Comments
 (0)