@@ -53,7 +53,7 @@ def to_scalar_or_list(v):
5353 return v
5454
5555
56- def copy_to_readonly_numpy_array (v , kind = None , force_numeric = False ):
56+ def copy_to_readonly_numpy_array_or_list (v , kind = None , force_numeric = False ):
5757 """
5858 Convert an array-like value into a read-only numpy array
5959
@@ -89,7 +89,13 @@ def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False):
8989
9090 # u: unsigned int, i: signed int, f: float
9191 numeric_kinds = {"u" , "i" , "f" }
92- kind_default_dtypes = {"u" : "uint32" , "i" : "int32" , "f" : "float64" , "O" : "object" }
92+ kind_default_dtypes = {
93+ "u" : "uint32" ,
94+ "i" : "int32" ,
95+ "f" : "float64" ,
96+ "O" : "object" ,
97+ "U" : "U" ,
98+ }
9399
94100 # Handle pandas Series and Index objects
95101 if pd and isinstance (v , (pd .Series , pd .Index )):
@@ -113,18 +119,12 @@ def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False):
113119 if not isinstance (v , np .ndarray ):
114120 # v has its own logic on how to convert itself into a numpy array
115121 if is_numpy_convertable (v ):
116- return copy_to_readonly_numpy_array (
122+ return copy_to_readonly_numpy_array_or_list (
117123 np .array (v ), kind = kind , force_numeric = force_numeric
118124 )
119125 else :
120126 # v is not homogenous array
121- v_list = [to_scalar_or_list (e ) for e in v ]
122-
123- # Lookup dtype for requested kind, if any
124- dtype = kind_default_dtypes .get (first_kind , None )
125-
126- # construct new array from list
127- new_v = np .array (v_list , order = "C" , dtype = dtype )
127+ return [to_scalar_or_list (e ) for e in v ]
128128 elif v .dtype .kind in numeric_kinds :
129129 # v is a homogenous numeric array
130130 if kind and v .dtype .kind not in kind :
@@ -135,6 +135,12 @@ def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False):
135135 else :
136136 # Either no kind was requested or requested kind is satisfied
137137 new_v = np .ascontiguousarray (v .copy ())
138+ elif v .dtype .kind == "O" :
139+ if kind :
140+ dtype = kind_default_dtypes .get (first_kind , None )
141+ return np .array (v , dtype = dtype )
142+ else :
143+ return v .tolist ()
138144 else :
139145 # v is a non-numeric homogenous array
140146 new_v = v .copy ()
@@ -149,12 +155,12 @@ def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False):
149155 if "U" not in kind :
150156 # Force non-numeric arrays to have object type
151157 # --------------------------------------------
152- # Here we make sure that non-numeric arrays have the object
153- # datatype. This works around cases like np.array([1, 2, '3']) where
158+ # Here we make sure that non-numeric arrays become lists
159+ # This works around cases like np.array([1, 2, '3']) where
154160 # numpy converts the integers to strings and returns array of dtype
155161 # '<U21'
156162 if new_v .dtype .kind not in ["u" , "i" , "f" , "O" , "M" ]:
157- new_v = np . array ( v , dtype = "object" )
163+ return v . tolist ( )
158164
159165 # Set new array to be read-only
160166 # -----------------------------
@@ -191,7 +197,7 @@ def is_homogeneous_array(v):
191197 if v_numpy .shape == ():
192198 return False
193199 else :
194- return True
200+ return True # v_numpy.dtype.kind in ["u", "i", "f", "M", "U"]
195201 return False
196202
197203
@@ -393,7 +399,7 @@ def validate_coerce(self, v):
393399 # Pass None through
394400 pass
395401 elif is_homogeneous_array (v ):
396- v = copy_to_readonly_numpy_array (v )
402+ v = copy_to_readonly_numpy_array_or_list (v )
397403 elif is_simple_array (v ):
398404 v = to_scalar_or_list (v )
399405 else :
@@ -598,7 +604,7 @@ def validate_coerce(self, v):
598604 self .raise_invalid_elements (invalid_els [:10 ])
599605
600606 if is_homogeneous_array (v ):
601- v = copy_to_readonly_numpy_array (v )
607+ v = copy_to_readonly_numpy_array_or_list (v )
602608 else :
603609 v = to_scalar_or_list (v )
604610 else :
@@ -754,7 +760,7 @@ def validate_coerce(self, v):
754760 elif self .array_ok and is_homogeneous_array (v ):
755761 np = get_module ("numpy" )
756762 try :
757- v_array = copy_to_readonly_numpy_array (v , force_numeric = True )
763+ v_array = copy_to_readonly_numpy_array_or_list (v , force_numeric = True )
758764 except (ValueError , TypeError , OverflowError ):
759765 self .raise_invalid_val (v )
760766
@@ -881,7 +887,7 @@ def validate_coerce(self, v):
881887 pass
882888 elif self .array_ok and is_homogeneous_array (v ):
883889 np = get_module ("numpy" )
884- v_array = copy_to_readonly_numpy_array (
890+ v_array = copy_to_readonly_numpy_array_or_list (
885891 v , kind = ("i" , "u" ), force_numeric = True
886892 )
887893
@@ -1042,26 +1048,7 @@ def validate_coerce(self, v):
10421048 if invalid_els :
10431049 self .raise_invalid_elements (invalid_els )
10441050
1045- if is_homogeneous_array (v ):
1046- np = get_module ("numpy" )
1047-
1048- # If not strict, let numpy cast elements to strings
1049- v = copy_to_readonly_numpy_array (v , kind = "U" )
1050-
1051- # Check no_blank
1052- if self .no_blank :
1053- invalid_els = v [v == "" ][:10 ].tolist ()
1054- if invalid_els :
1055- self .raise_invalid_elements (invalid_els )
1056-
1057- # Check values
1058- if self .values :
1059- invalid_inds = np .logical_not (np .isin (v , self .values ))
1060- invalid_els = v [invalid_inds ][:10 ].tolist ()
1061- if invalid_els :
1062- self .raise_invalid_elements (invalid_els )
1063-
1064- elif is_simple_array (v ):
1051+ if is_simple_array (v ) or is_homogeneous_array (v ):
10651052 if not self .strict :
10661053 v = [StringValidator .to_str_or_unicode_or_none (e ) for e in v ]
10671054
@@ -1338,8 +1325,12 @@ def validate_coerce(self, v, should_raise=True):
13381325 # Pass None through
13391326 pass
13401327 elif self .array_ok and is_homogeneous_array (v ):
1341- v = copy_to_readonly_numpy_array (v )
1342- if self .numbers_allowed () and v .dtype .kind in ["u" , "i" , "f" ]:
1328+ v = copy_to_readonly_numpy_array_or_list (v )
1329+ if (
1330+ not isinstance (v , list )
1331+ and self .numbers_allowed ()
1332+ and v .dtype .kind in ["u" , "i" , "f" ]
1333+ ):
13431334 # Numbers are allowed and we have an array of numbers.
13441335 # All good
13451336 pass
@@ -1353,9 +1344,9 @@ def validate_coerce(self, v, should_raise=True):
13531344
13541345 # ### Check that elements have valid colors types ###
13551346 elif self .numbers_allowed () or invalid_els :
1356- v = copy_to_readonly_numpy_array (validated_v , kind = "O" )
1347+ v = copy_to_readonly_numpy_array_or_list (validated_v , kind = "O" )
13571348 else :
1358- v = copy_to_readonly_numpy_array (validated_v , kind = "U" )
1349+ v = copy_to_readonly_numpy_array_or_list (validated_v , kind = "U" )
13591350 elif self .array_ok and is_simple_array (v ):
13601351 validated_v = [self .validate_coerce (e , should_raise = False ) for e in v ]
13611352
@@ -1870,7 +1861,7 @@ def validate_coerce(self, v):
18701861 self .raise_invalid_elements (invalid_els )
18711862
18721863 if is_homogeneous_array (v ):
1873- v = copy_to_readonly_numpy_array (validated_v , kind = "U" )
1864+ v = copy_to_readonly_numpy_array_or_list (validated_v , kind = "U" )
18741865 else :
18751866 v = to_scalar_or_list (v )
18761867 else :
@@ -1918,7 +1909,7 @@ def validate_coerce(self, v):
19181909 # Pass None through
19191910 pass
19201911 elif self .array_ok and is_homogeneous_array (v ):
1921- v = copy_to_readonly_numpy_array (v , kind = "O" )
1912+ v = copy_to_readonly_numpy_array_or_list (v , kind = "O" )
19221913 elif self .array_ok and is_simple_array (v ):
19231914 v = to_scalar_or_list (v )
19241915 return v
0 commit comments