@@ -38,6 +38,35 @@ def mi_styler(mi_df):
3838    return  Styler (mi_df , uuid_len = 0 )
3939
4040
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+ 
4170@pytest .mark .parametrize ( 
4271    "sparse_columns, exp_cols" , 
4372    [ 
@@ -156,6 +185,49 @@ def test_render_trimming_mi():
156185    assert  {"attributes" : 'colspan="2"' }.items () <=  ctx ["head" ][0 ][2 ].items ()
157186
158187
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+ 
159231class  TestStyler :
160232    def  setup_method (self , method ):
161233        np .random .seed (24 )
@@ -211,102 +283,6 @@ def test_update_ctx_flatten_multi_and_trailing_semi(self):
211283        }
212284        assert  self .styler .ctx  ==  expected 
213285
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- 
310286    def  test_clear (self ):
311287        # updated in GH 39396 
312288        tt  =  DataFrame ({"A" : [None , "tt" ]})
0 commit comments