@@ -38,6 +38,35 @@ def mi_styler(mi_df):
38
38
return Styler (mi_df , uuid_len = 0 )
39
39
40
40
41
+ @pytest .fixture
42
+ def mi_styler_comp (mi_styler ):
43
+ # comprehensively add features to mi_styler
44
+ mi_styler .uuid_len = 5
45
+ mi_styler .uuid = "abcde_"
46
+ mi_styler .set_caption ("capt" )
47
+ mi_styler .set_table_styles ([{"selector" : "a" , "props" : "a:v;" }])
48
+ mi_styler .hide_columns ()
49
+ mi_styler .hide_columns ([("c0" , "c1_a" )])
50
+ mi_styler .hide_index ()
51
+ mi_styler .hide_index ([("i0" , "i1_a" )])
52
+ mi_styler .set_table_attributes ('class="box"' )
53
+ mi_styler .format (na_rep = "MISSING" , precision = 3 )
54
+ mi_styler .highlight_max (axis = None )
55
+ mi_styler .set_td_classes (
56
+ DataFrame (
57
+ [["a" , "b" ], ["a" , "c" ]], index = mi_styler .index , columns = mi_styler .columns
58
+ )
59
+ )
60
+ mi_styler .set_tooltips (
61
+ DataFrame (
62
+ [["a2" , "b2" ], ["a2" , "c2" ]],
63
+ index = mi_styler .index ,
64
+ columns = mi_styler .columns ,
65
+ )
66
+ )
67
+ return mi_styler
68
+
69
+
41
70
@pytest .mark .parametrize (
42
71
"sparse_columns, exp_cols" ,
43
72
[
@@ -156,6 +185,49 @@ def test_render_trimming_mi():
156
185
assert {"attributes" : 'colspan="2"' }.items () <= ctx ["head" ][0 ][2 ].items ()
157
186
158
187
188
+ @pytest .mark .parametrize ("comprehensive" , [True , False ])
189
+ @pytest .mark .parametrize ("render" , [True , False ])
190
+ @pytest .mark .parametrize ("deepcopy" , [True , False ])
191
+ def test_copy (comprehensive , render , deepcopy , mi_styler , mi_styler_comp ):
192
+ styler = mi_styler_comp if comprehensive else mi_styler
193
+ styler .uuid_len = 5
194
+
195
+ s2 = copy .deepcopy (styler ) if deepcopy else copy .copy (styler ) # make copy and check
196
+ assert s2 is not styler
197
+
198
+ if render :
199
+ styler .to_html ()
200
+
201
+ excl = ["na_rep" , "precision" , "uuid" , "cellstyle_map" ] # deprecated or special var
202
+ if not deepcopy : # check memory locations are equal for all included attributes
203
+ for attr in [a for a in styler .__dict__ if (not callable (a ) and a not in excl )]:
204
+ assert id (getattr (s2 , attr )) == id (getattr (styler , attr ))
205
+ else : # check memory locations are different for nested or mutable vars
206
+ shallow = [
207
+ "data" ,
208
+ "columns" ,
209
+ "index" ,
210
+ "uuid_len" ,
211
+ "caption" ,
212
+ "cell_ids" ,
213
+ "hide_index_" ,
214
+ "hide_columns_" ,
215
+ "table_attributes" ,
216
+ ]
217
+ for attr in shallow :
218
+ assert id (getattr (s2 , attr )) == id (getattr (styler , attr ))
219
+
220
+ for attr in [
221
+ a
222
+ for a in styler .__dict__
223
+ if (not callable (a ) and a not in excl and a not in shallow )
224
+ ]:
225
+ if getattr (s2 , attr ) is None :
226
+ assert id (getattr (s2 , attr )) == id (getattr (styler , attr ))
227
+ else :
228
+ assert id (getattr (s2 , attr )) != id (getattr (styler , attr ))
229
+
230
+
159
231
class TestStyler :
160
232
def setup_method (self , method ):
161
233
np .random .seed (24 )
@@ -211,102 +283,6 @@ def test_update_ctx_flatten_multi_and_trailing_semi(self):
211
283
}
212
284
assert self .styler .ctx == expected
213
285
214
- @pytest .mark .parametrize ("do_changes" , [True , False ])
215
- @pytest .mark .parametrize ("do_render" , [True , False ])
216
- def test_copy (self , do_changes , do_render ):
217
- # Updated in GH39708
218
- # Change some defaults (to check later if the new values are copied)
219
- if do_changes :
220
- self .styler .set_table_styles (
221
- [{"selector" : "th" , "props" : [("foo" , "bar" )]}]
222
- )
223
- self .styler .set_table_attributes ('class="foo" data-bar' )
224
- self .styler .hide_index_ = not self .styler .hide_index_
225
- self .styler .hide_columns ("A" )
226
- classes = DataFrame (
227
- [["favorite-val red" , "" ], [None , "blue my-val" ]],
228
- index = self .df .index ,
229
- columns = self .df .columns ,
230
- )
231
- self .styler .set_td_classes (classes )
232
- ttips = DataFrame (
233
- data = [["Favorite" , "" ], [np .nan , "my" ]],
234
- columns = self .df .columns ,
235
- index = self .df .index ,
236
- )
237
- self .styler .set_tooltips (ttips )
238
- self .styler .cell_ids = not self .styler .cell_ids
239
-
240
- if do_render :
241
- self .styler .render ()
242
-
243
- s_copy = copy .copy (self .styler )
244
- s_deepcopy = copy .deepcopy (self .styler )
245
-
246
- assert self .styler is not s_copy
247
- assert self .styler is not s_deepcopy
248
-
249
- # Check for identity
250
- assert self .styler .ctx is s_copy .ctx
251
- assert self .styler ._todo is s_copy ._todo
252
- assert self .styler .table_styles is s_copy .table_styles
253
- assert self .styler .hidden_columns is s_copy .hidden_columns
254
- assert self .styler .cell_context is s_copy .cell_context
255
- assert self .styler .tooltips is s_copy .tooltips
256
- if do_changes : # self.styler.tooltips is not None
257
- assert self .styler .tooltips .tt_data is s_copy .tooltips .tt_data
258
- assert (
259
- self .styler .tooltips .class_properties
260
- is s_copy .tooltips .class_properties
261
- )
262
- assert self .styler .tooltips .table_styles is s_copy .tooltips .table_styles
263
-
264
- # Check for non-identity
265
- assert self .styler .ctx is not s_deepcopy .ctx
266
- assert self .styler ._todo is not s_deepcopy ._todo
267
- assert self .styler .hidden_columns is not s_deepcopy .hidden_columns
268
- assert self .styler .cell_context is not s_deepcopy .cell_context
269
- if do_changes : # self.styler.table_style is not None
270
- assert self .styler .table_styles is not s_deepcopy .table_styles
271
- if do_changes : # self.styler.tooltips is not None
272
- assert self .styler .tooltips is not s_deepcopy .tooltips
273
- assert self .styler .tooltips .tt_data is not s_deepcopy .tooltips .tt_data
274
- assert (
275
- self .styler .tooltips .class_properties
276
- is not s_deepcopy .tooltips .class_properties
277
- )
278
- assert (
279
- self .styler .tooltips .table_styles
280
- is not s_deepcopy .tooltips .table_styles
281
- )
282
-
283
- self .styler ._update_ctx (self .attrs )
284
- self .styler .highlight_max ()
285
- assert self .styler .ctx == s_copy .ctx
286
- assert self .styler .ctx != s_deepcopy .ctx
287
- assert self .styler ._todo == s_copy ._todo
288
- assert self .styler ._todo != s_deepcopy ._todo
289
- assert s_deepcopy ._todo == []
290
-
291
- equal_attributes = [
292
- "table_styles" ,
293
- "table_attributes" ,
294
- "cell_ids" ,
295
- "hide_index_" ,
296
- "hidden_columns" ,
297
- "cell_context" ,
298
- ]
299
- for s2 in [s_copy , s_deepcopy ]:
300
- for att in equal_attributes :
301
- assert self .styler .__dict__ [att ] == s2 .__dict__ [att ]
302
- if do_changes : # self.styler.tooltips is not None
303
- tm .assert_frame_equal (self .styler .tooltips .tt_data , s2 .tooltips .tt_data )
304
- assert (
305
- self .styler .tooltips .class_properties
306
- == s2 .tooltips .class_properties
307
- )
308
- assert self .styler .tooltips .table_styles == s2 .tooltips .table_styles
309
-
310
286
def test_clear (self ):
311
287
# updated in GH 39396
312
288
tt = DataFrame ({"A" : [None , "tt" ]})
0 commit comments