@@ -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