58
58
is_timedelta64_dtype ,
59
59
is_unsigned_integer_dtype ,
60
60
pandas_dtype ,
61
+ validate_all_hashable ,
61
62
)
62
63
from pandas .core .dtypes .concat import concat_compat
63
64
from pandas .core .dtypes .generic import (
@@ -812,13 +813,11 @@ def copy(self, name=None, deep=False, dtype=None, names=None):
812
813
In most cases, there should be no functional difference from using
813
814
``deep``, but if ``deep`` is passed it will attempt to deepcopy.
814
815
"""
816
+ name = self ._validate_names (name = name , names = names , deep = deep )[0 ]
815
817
if deep :
816
- new_index = self ._shallow_copy (self ._data .copy ())
818
+ new_index = self ._shallow_copy (self ._data .copy (), name = name )
817
819
else :
818
- new_index = self ._shallow_copy ()
819
-
820
- names = self ._validate_names (name = name , names = names , deep = deep )
821
- new_index = new_index .set_names (names )
820
+ new_index = self ._shallow_copy (name = name )
822
821
823
822
if dtype :
824
823
new_index = new_index .astype (dtype )
@@ -1186,7 +1185,7 @@ def name(self, value):
1186
1185
maybe_extract_name (value , None , type (self ))
1187
1186
self ._name = value
1188
1187
1189
- def _validate_names (self , name = None , names = None , deep : bool = False ):
1188
+ def _validate_names (self , name = None , names = None , deep : bool = False ) -> List [ Label ] :
1190
1189
"""
1191
1190
Handles the quirks of having a singular 'name' parameter for general
1192
1191
Index and plural 'names' parameter for MultiIndex.
@@ -1196,15 +1195,25 @@ def _validate_names(self, name=None, names=None, deep: bool = False):
1196
1195
if names is not None and name is not None :
1197
1196
raise TypeError ("Can only provide one of `names` and `name`" )
1198
1197
elif names is None and name is None :
1199
- return deepcopy (self .names ) if deep else self .names
1198
+ new_names = deepcopy (self .names ) if deep else self .names
1200
1199
elif names is not None :
1201
1200
if not is_list_like (names ):
1202
1201
raise TypeError ("Must pass list-like as `names`." )
1203
- return names
1202
+ new_names = names
1203
+ elif not is_list_like (name ):
1204
+ new_names = [name ]
1204
1205
else :
1205
- if not is_list_like (name ):
1206
- return [name ]
1207
- return name
1206
+ new_names = name
1207
+
1208
+ if len (new_names ) != len (self .names ):
1209
+ raise ValueError (
1210
+ f"Length of new names must be { len (self .names )} , got { len (new_names )} "
1211
+ )
1212
+
1213
+ # All items in 'new_names' need to be hashable
1214
+ validate_all_hashable (* new_names , error_name = f"{ type (self ).__name__ } .name" )
1215
+
1216
+ return new_names
1208
1217
1209
1218
def _get_names (self ):
1210
1219
return FrozenList ((self .name ,))
@@ -1232,9 +1241,8 @@ def _set_names(self, values, level=None):
1232
1241
1233
1242
# GH 20527
1234
1243
# All items in 'name' need to be hashable:
1235
- for name in values :
1236
- if not is_hashable (name ):
1237
- raise TypeError (f"{ type (self ).__name__ } .name must be a hashable type" )
1244
+ validate_all_hashable (* values , error_name = f"{ type (self ).__name__ } .name" )
1245
+
1238
1246
self ._name = values [0 ]
1239
1247
1240
1248
names = property (fset = _set_names , fget = _get_names )
0 commit comments