@@ -335,12 +335,18 @@ def test_setitem(self, float_frame, using_copy_on_write):
335335    def  test_setitem2 (self ):
336336        # dtype changing GH4204 
337337        df  =  DataFrame ([[0 , 0 ]])
338-         df .iloc [0 ] =  np .nan 
338+         with  tm .assert_produces_warning (
339+             FutureWarning , match = "Setting an item of incompatible dtype" 
340+         ):
341+             df .iloc [0 ] =  np .nan 
339342        expected  =  DataFrame ([[np .nan , np .nan ]])
340343        tm .assert_frame_equal (df , expected )
341344
342345        df  =  DataFrame ([[0 , 0 ]])
343-         df .loc [0 ] =  np .nan 
346+         with  tm .assert_produces_warning (
347+             FutureWarning , match = "Setting an item of incompatible dtype" 
348+         ):
349+             df .loc [0 ] =  np .nan 
344350        tm .assert_frame_equal (df , expected )
345351
346352    def  test_setitem_boolean (self , float_frame ):
@@ -1332,12 +1338,22 @@ def test_loc_expand_empty_frame_keep_midx_names(self):
13321338        )
13331339        tm .assert_frame_equal (df , expected )
13341340
1335-     @pytest .mark .parametrize ("val" , ["x" , 1 ]) 
1336-     @pytest .mark .parametrize ("idxr" , ["a" , ["a" ]]) 
1337-     def  test_loc_setitem_rhs_frame (self , idxr , val ):
1341+     @pytest .mark .parametrize ( 
1342+         "val, idxr, warn" , 
1343+         [ 
1344+             ("x" , "a" , None ),  # TODO: this should warn as well  
1345+             ("x" , ["a" ], None ),  # TODO: this should warn as well  
1346+             (1 , "a" , None ),  # TODO: this should warn as well  
1347+             (1 , ["a" ], FutureWarning ), 
1348+         ], 
1349+     ) 
1350+     def  test_loc_setitem_rhs_frame (self , idxr , val , warn ):
13381351        # GH#47578 
13391352        df  =  DataFrame ({"a" : [1 , 2 ]})
1340-         with  tm .assert_produces_warning (None ):
1353+ 
1354+         with  tm .assert_produces_warning (
1355+             warn , match = "Setting an item of incompatible dtype" 
1356+         ):
13411357            df .loc [:, idxr ] =  DataFrame ({"a" : [val , 11 ]}, index = [1 , 2 ])
13421358        expected  =  DataFrame ({"a" : [np .nan , val ]})
13431359        tm .assert_frame_equal (df , expected )
@@ -1537,8 +1553,11 @@ def test_setitem(self, uint64_frame):
15371553        # With NaN: because uint64 has no NaN element, 
15381554        # the column should be cast to object. 
15391555        df2  =  df .copy ()
1540-         df2 .iloc [1 , 1 ] =  pd .NaT 
1541-         df2 .iloc [1 , 2 ] =  pd .NaT 
1556+         with  tm .assert_produces_warning (
1557+             FutureWarning , match = "Setting an item of incompatible dtype" 
1558+         ):
1559+             df2 .iloc [1 , 1 ] =  pd .NaT 
1560+             df2 .iloc [1 , 2 ] =  pd .NaT 
15421561        result  =  df2 ["B" ]
15431562        tm .assert_series_equal (notna (result ), Series ([True , False , True ], name = "B" ))
15441563        tm .assert_series_equal (
@@ -1851,3 +1870,54 @@ def test_setitem_dict_and_set_disallowed_multiindex(self, key):
18511870        )
18521871        with  pytest .raises (TypeError , match = "as an indexer is not supported" ):
18531872            df .loc [key ] =  1 
1873+ 
1874+ 
1875+ class  TestSetitemValidation :
1876+     # This is adapted from pandas/tests/arrays/masked/test_indexing.py 
1877+     # but checks for warnings instead of errors. 
1878+     def  _check_setitem_invalid (self , df , invalid , indexer ):
1879+         msg  =  "Setting an item of incompatible dtype is deprecated" 
1880+         msg  =  re .escape (msg )
1881+ 
1882+         orig_df  =  df .copy ()
1883+ 
1884+         # iloc 
1885+         with  tm .assert_produces_warning (FutureWarning , match = msg ):
1886+             df .iloc [indexer , 0 ] =  invalid 
1887+             df  =  orig_df .copy ()
1888+ 
1889+         # loc 
1890+         with  tm .assert_produces_warning (FutureWarning , match = msg ):
1891+             df .loc [indexer , "a" ] =  invalid 
1892+             df  =  orig_df .copy ()
1893+ 
1894+     _invalid_scalars  =  [
1895+         1  +  2j ,
1896+         "True" ,
1897+         "1" ,
1898+         "1.0" ,
1899+         pd .NaT ,
1900+         np .datetime64 ("NaT" ),
1901+         np .timedelta64 ("NaT" ),
1902+     ]
1903+     _indexers  =  [0 , [0 ], slice (0 , 1 ), [True , False , False ]]
1904+ 
1905+     @pytest .mark .parametrize ( 
1906+         "invalid" , _invalid_scalars  +  [1 , 1.0 , np .int64 (1 ), np .float64 (1 )] 
1907+     ) 
1908+     @pytest .mark .parametrize ("indexer" , _indexers ) 
1909+     def  test_setitem_validation_scalar_bool (self , invalid , indexer ):
1910+         df  =  DataFrame ({"a" : [True , False , False ]}, dtype = "bool" )
1911+         self ._check_setitem_invalid (df , invalid , indexer )
1912+ 
1913+     @pytest .mark .parametrize ("invalid" , _invalid_scalars  +  [True , 1.5 , np .float64 (1.5 )]) 
1914+     @pytest .mark .parametrize ("indexer" , _indexers ) 
1915+     def  test_setitem_validation_scalar_int (self , invalid , any_int_numpy_dtype , indexer ):
1916+         df  =  DataFrame ({"a" : [1 , 2 , 3 ]}, dtype = any_int_numpy_dtype )
1917+         self ._check_setitem_invalid (df , invalid , indexer )
1918+ 
1919+     @pytest .mark .parametrize ("invalid" , _invalid_scalars  +  [True ]) 
1920+     @pytest .mark .parametrize ("indexer" , _indexers ) 
1921+     def  test_setitem_validation_scalar_float (self , invalid , float_numpy_dtype , indexer ):
1922+         df  =  DataFrame ({"a" : [1 , 2 , None ]}, dtype = float_numpy_dtype )
1923+         self ._check_setitem_invalid (df , invalid , indexer )
0 commit comments