@@ -43,12 +43,26 @@ def fullmatch(regex, string, flags=0):
4343# Utility functions
4444# -----------------
4545def to_scalar_or_list (v ):
46+ # Handle the case where 'v' is a non-native scalar-like type,
47+ # such as numpy.float32. Without this case, the object might be
48+ # considered numpy-convertable and therefore promoted to a
49+ # 0-dimensional array, but we instead want it converted to a
50+ # Python native scalar type ('float' in the example above).
51+ # We explicitly check if is has the 'item' method, which conventionally
52+ # converts these types to native scalars. This guards against 'v' already being
53+ # a Python native scalar type since `numpy.isscalar` would return
54+ # True but `numpy.asscalar` will (oddly) raise an error is called with a
55+ # a native Python scalar object.
56+ if np and np .isscalar (v ) and hasattr (v , 'item' ):
57+ return np .asscalar (v )
4658 if isinstance (v , (list , tuple )):
4759 return [to_scalar_or_list (e ) for e in v ]
4860 elif np and isinstance (v , np .ndarray ):
4961 return [to_scalar_or_list (e ) for e in v ]
5062 elif pd and isinstance (v , (pd .Series , pd .Index )):
5163 return [to_scalar_or_list (e ) for e in v ]
64+ elif is_numpy_convertable (v ):
65+ return to_scalar_or_list (np .array (v ))
5266 else :
5367 return v
5468
@@ -101,16 +115,19 @@ def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False):
101115 else :
102116 # DatetimeIndex
103117 v = v .to_pydatetime ()
104-
105118 if not isinstance (v , np .ndarray ):
106- # v is not homogenous array
107- v_list = [to_scalar_or_list (e ) for e in v ]
119+ # v has its own logic on how to convert itself into a numpy array
120+ if is_numpy_convertable (v ):
121+ return copy_to_readonly_numpy_array (np .array (v ), kind = kind , force_numeric = force_numeric )
122+ else :
123+ # v is not homogenous array
124+ v_list = [to_scalar_or_list (e ) for e in v ]
108125
109- # Lookup dtype for requested kind, if any
110- dtype = kind_default_dtypes .get (first_kind , None )
126+ # Lookup dtype for requested kind, if any
127+ dtype = kind_default_dtypes .get (first_kind , None )
111128
112- # construct new array from list
113- new_v = np .array (v_list , order = 'C' , dtype = dtype )
129+ # construct new array from list
130+ new_v = np .array (v_list , order = 'C' , dtype = dtype )
114131 elif v .dtype .kind in numeric_kinds :
115132 # v is a homogenous numeric array
116133 if kind and v .dtype .kind not in kind :
@@ -148,12 +165,29 @@ def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False):
148165 return new_v
149166
150167
168+ def is_numpy_convertable (v ):
169+ """
170+ Return whether a value is meaningfully convertable to a numpy array
171+ via 'numpy.array'
172+ """
173+ return hasattr (v , '__array__' ) or hasattr (v , '__array_interface__' )
174+
175+
151176def is_homogeneous_array (v ):
152177 """
153178 Return whether a value is considered to be a homogeneous array
154- """
155- return ((np and isinstance (v , np .ndarray )) or
156- (pd and isinstance (v , (pd .Series , pd .Index ))))
179+ """
180+ if ((np and isinstance (v , np .ndarray ) or
181+ (pd and isinstance (v , (pd .Series , pd .Index ))))):
182+ return True
183+ if is_numpy_convertable (v ):
184+ v_numpy = np .array (v )
185+ # v is essentially a scalar and so shouldn't count as an array
186+ if v_numpy .shape == ():
187+ return False
188+ else :
189+ return True
190+ return False
157191
158192
159193def is_simple_array (v ):
@@ -1097,13 +1131,12 @@ def validate_coerce(self, v, should_raise=True):
10971131 # Pass None through
10981132 pass
10991133 elif self .array_ok and is_homogeneous_array (v ):
1100-
1101- v_array = copy_to_readonly_numpy_array (v )
1134+ v = copy_to_readonly_numpy_array (v )
11021135 if (self .numbers_allowed () and
1103- v_array .dtype .kind in ['u' , 'i' , 'f' ]):
1136+ v .dtype .kind in ['u' , 'i' , 'f' ]):
11041137 # Numbers are allowed and we have an array of numbers.
11051138 # All good
1106- v = v_array
1139+ pass
11071140 else :
11081141 validated_v = [
11091142 self .validate_coerce (e , should_raise = False )
0 commit comments