@@ -1672,8 +1672,8 @@ def __new__(cls, data, dtype=None, copy=False, name=None, fastpath=False):
16721672 subarr = np .array (data , dtype = np .int64 , copy = copy )
16731673 if len (data ) > 0 :
16741674 if (subarr != data ).any ():
1675- raise TypeError ('Unsafe NumPy casting, you must '
1676- 'explicitly cast' )
1675+ raise TypeError ('Unsafe NumPy casting to integer , you must'
1676+ ' explicitly cast' )
16771677
16781678 subarr = subarr .view (cls )
16791679 subarr .name = name
@@ -1857,11 +1857,12 @@ class MultiIndex(Index):
18571857
18581858 def __new__ (cls , levels = None , labels = None , sortorder = None , names = None ,
18591859 copy = False ):
1860+ if levels is None or labels is None :
1861+ raise TypeError ("Must pass both levels and labels" )
18601862 if len (levels ) != len (labels ):
1861- raise ValueError (
1862- 'Length of levels and labels must be the same' )
1863+ raise ValueError ('Length of levels and labels must be the same.' )
18631864 if len (levels ) == 0 :
1864- raise TypeError ('Must pass non-zero number of levels/labels' )
1865+ raise ValueError ('Must pass non-zero number of levels/labels' )
18651866 if len (levels ) == 1 :
18661867 if names :
18671868 name = names [0 ]
@@ -1872,10 +1873,12 @@ def __new__(cls, levels=None, labels=None, sortorder=None, names=None,
18721873
18731874 # v3, 0.8.0
18741875 subarr = np .empty (0 , dtype = object ).view (cls )
1875- subarr ._set_levels (levels , copy = copy )
1876- subarr ._set_labels (labels , copy = copy )
1876+ # we've already validated levels and labels, so shortcut here
1877+ subarr ._set_levels (levels , copy = copy , validate = False )
1878+ subarr ._set_labels (labels , copy = copy , validate = False )
18771879
18781880 if names is not None :
1881+ # handles name validation
18791882 subarr ._set_names (names )
18801883
18811884 if sortorder is not None :
@@ -1888,12 +1891,14 @@ def __new__(cls, levels=None, labels=None, sortorder=None, names=None,
18881891 def _get_levels (self ):
18891892 return self ._levels
18901893
1891- def _set_levels (self , levels , copy = False ):
1894+ def _set_levels (self , levels , copy = False , validate = True ):
18921895 # This is NOT part of the levels property because it should be
18931896 # externally not allowed to set levels. User beware if you change
18941897 # _levels directly
1895- if len (levels ) == 0 :
1896- raise ValueError ("Must set non-zero number of levels." )
1898+ if validate and len (levels ) == 0 :
1899+ raise ValueError ('Must set non-zero number of levels.' )
1900+ if validate and len (levels ) != len (self ._labels ):
1901+ raise ValueError ('Length of levels must match length of labels.' )
18971902 levels = FrozenList (_ensure_index (lev , copy = copy )._shallow_copy ()
18981903 for lev in levels )
18991904 names = self .names
@@ -1917,13 +1922,16 @@ def set_levels(self, levels, inplace=False):
19171922 -------
19181923 new index (of same type and class...etc)
19191924 """
1925+ if not com .is_list_like (levels ) or not com .is_list_like (levels [0 ]):
1926+ raise TypeError ("Levels must be list of lists-like" )
19201927 if inplace :
19211928 idx = self
19221929 else :
19231930 idx = self ._shallow_copy ()
19241931 idx ._reset_identity ()
19251932 idx ._set_levels (levels )
1926- return idx
1933+ if not inplace :
1934+ return idx
19271935
19281936 # remove me in 0.14 and change to read only property
19291937 __set_levels = deprecate ("setting `levels` directly" ,
@@ -1934,9 +1942,9 @@ def set_levels(self, levels, inplace=False):
19341942 def _get_labels (self ):
19351943 return self ._labels
19361944
1937- def _set_labels (self , labels , copy = False ):
1938- if len (labels ) != self .nlevels :
1939- raise ValueError ("Length of levels and labels must be the same. " )
1945+ def _set_labels (self , labels , copy = False , validate = True ):
1946+ if validate and len (labels ) != self .nlevels :
1947+ raise ValueError ("Length of labels must match length of levels " )
19401948 self ._labels = FrozenList (_ensure_frozen (labs , copy = copy )._shallow_copy ()
19411949 for labs in labels )
19421950
@@ -1956,13 +1964,16 @@ def set_labels(self, labels, inplace=False):
19561964 -------
19571965 new index (of same type and class...etc)
19581966 """
1967+ if not com .is_list_like (labels ) or not com .is_list_like (labels [0 ]):
1968+ raise TypeError ("Labels must be list of lists-like" )
19591969 if inplace :
19601970 idx = self
19611971 else :
19621972 idx = self ._shallow_copy ()
19631973 idx ._reset_identity ()
19641974 idx ._set_labels (labels )
1965- return idx
1975+ if not inplace :
1976+ return idx
19661977
19671978 # remove me in 0.14 and change to readonly property
19681979 __set_labels = deprecate ("setting labels directly" ,
@@ -2021,7 +2032,8 @@ def __array_finalize__(self, obj):
20212032 # instance.
20222033 return
20232034
2024- self ._set_levels (getattr (obj , 'levels' , []))
2035+ # skip the validation on first, rest will catch the errors
2036+ self ._set_levels (getattr (obj , 'levels' , []), validate = False )
20252037 self ._set_labels (getattr (obj , 'labels' , []))
20262038 self ._set_names (getattr (obj , 'names' , []))
20272039 self .sortorder = getattr (obj , 'sortorder' , None )
@@ -2083,16 +2095,15 @@ def _convert_slice_indexer(self, key, typ=None):
20832095 def _get_names (self ):
20842096 return FrozenList (level .name for level in self .levels )
20852097
2086- def _set_names (self , values ):
2098+ def _set_names (self , values , validate = True ):
20872099 """
20882100 sets names on levels. WARNING: mutates!
20892101
20902102 Note that you generally want to set this *after* changing levels, so that it only
20912103 acts on copies"""
20922104 values = list (values )
2093- if len (values ) != self .nlevels :
2094- raise ValueError ('Length of names (%d) must be same as level '
2095- '(%d)' % (len (values ), self .nlevels ))
2105+ if validate and len (values ) != self .nlevels :
2106+ raise ValueError ('Length of names must match length of levels' )
20962107 # set the name
20972108 for name , level in zip (values , self .levels ):
20982109 level .rename (name , inplace = True )
@@ -2446,7 +2457,7 @@ def __setstate__(self, state):
24462457 np .ndarray .__setstate__ (self , nd_state )
24472458 levels , labels , sortorder , names = own_state
24482459
2449- self ._set_levels ([Index (x ) for x in levels ])
2460+ self ._set_levels ([Index (x ) for x in levels ], validate = False )
24502461 self ._set_labels (labels )
24512462 self ._set_names (names )
24522463 self .sortorder = sortorder
@@ -2473,7 +2484,7 @@ def __getitem__(self, key):
24732484 new_labels = [lab [key ] for lab in self .labels ]
24742485
24752486 # an optimization
2476- result ._set_levels (self .levels )
2487+ result ._set_levels (self .levels , validate = False )
24772488 result ._set_labels (new_labels )
24782489 result .sortorder = sortorder
24792490 result ._set_names (self .names )
@@ -3351,17 +3362,12 @@ def _ensure_index(index_like, copy=False):
33513362 return Index (index_like )
33523363
33533364
3354- def _ensure_frozen (nd_array_like , copy = False ):
3355- if not isinstance (nd_array_like , FrozenNDArray ):
3356- arr = np .asarray (nd_array_like , dtype = np .int_ )
3357- # have to do this separately so that non-index input gets copied
3358- if copy :
3359- arr = arr .copy ()
3360- nd_array_like = arr .view (FrozenNDArray )
3361- else :
3362- if copy :
3363- nd_array_like = nd_array_like .copy ()
3364- return nd_array_like
3365+ def _ensure_frozen (array_like , copy = False ):
3366+ array_like = np .asanyarray (array_like , dtype = np .int_ )
3367+ array_like = array_like .view (FrozenNDArray )
3368+ if copy :
3369+ array_like = array_like .copy ()
3370+ return array_like
33653371
33663372
33673373def _validate_join_method (method ):
0 commit comments