[pypy-commit] pypy can_cast: Add stub implementation for can_cast(<value>, dtype)

rlamy noreply at buildbot.pypy.org
Sun Apr 26 04:03:31 CEST 2015


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: can_cast
Changeset: r76937:6aaed87e0b78
Date: 2015-04-26 03:03 +0100
http://bitbucket.org/pypy/pypy/changeset/6aaed87e0b78/

Log:	Add stub implementation for can_cast(<value>, dtype)

diff --git a/pypy/module/micronumpy/arrayops.py b/pypy/module/micronumpy/arrayops.py
--- a/pypy/module/micronumpy/arrayops.py
+++ b/pypy/module/micronumpy/arrayops.py
@@ -306,7 +306,18 @@
 def can_cast(space, w_from, w_totype, casting='safe'):
     try:
         target = as_dtype(space, w_totype, allow_None=False)
-        origin = as_dtype(space, w_from, allow_None=False)  # XXX
+    except TypeError:
+        raise oefmt(space.w_TypeError,
+            "did not understand one of the types; 'None' not accepted")
+    if isinstance(w_from, W_NDimArray):
+        return space.wrap(can_cast_array(space, w_from, target, casting))
+    elif is_scalar_w(space, w_from):
+        w_scalar = as_scalar(space, w_from)
+        w_arr = W_NDimArray.from_scalar(space, w_scalar)
+        return space.wrap(can_cast_array(space, w_arr, target, casting))
+
+    try:
+        origin = as_dtype(space, w_from, allow_None=False)
     except TypeError:
         raise oefmt(space.w_TypeError,
             "did not understand one of the types; 'None' not accepted")
@@ -334,6 +345,30 @@
     else:
         return origin.can_cast_to(target)
 
+def can_cast_array(space, w_from, target, casting):
+    origin = w_from.get_dtype()
+    if w_from.is_scalar():
+        return can_cast_scalar(
+            space, origin, w_from.get_scalar_value(), target, casting)
+    else:
+        return can_cast_type(space, origin, target, casting)
+
+def can_cast_scalar(space, from_type, value, target, casting):
+    if from_type == target or casting == 'unsafe':
+        return True
+    if not from_type.is_number() or casting in ('no', 'equiv'):
+        return can_cast_type(space, from_type, target, casting)
+    if not from_type.is_native():
+        value = value.descr_byteswap(space)
+    return can_cast_type(space, from_type, target, casting)  # XXX: stub impl
+
+def is_scalar_w(space, w_arg):
+    return (isinstance(w_arg, W_GenericBox) or
+            space.isinstance_w(w_arg, space.w_int) or
+            space.isinstance_w(w_arg, space.w_float) or
+            space.isinstance_w(w_arg, space.w_complex) or
+            space.isinstance_w(w_arg, space.w_long) or
+            space.isinstance_w(w_arg, space.w_bool))
 
 def as_dtype(space, w_arg, allow_None=True):
     # roughly equivalent to CNumPy's PyArray_DescrConverter2
@@ -341,13 +376,12 @@
         raise TypeError("Cannot create dtype from None here")
     if isinstance(w_arg, W_NDimArray):
         return w_arg.get_dtype()
-    elif isinstance(w_arg, W_GenericBox) or (
-            space.isinstance_w(w_arg, space.w_int) or
-            space.isinstance_w(w_arg, space.w_float) or
-            space.isinstance_w(w_arg, space.w_complex) or
-            space.isinstance_w(w_arg, space.w_long) or
-            space.isinstance_w(w_arg, space.w_bool)):
+    elif is_scalar_w(space, w_arg):
         return ufuncs.find_dtype_for_scalar(space, w_arg)
     else:
         return space.interp_w(descriptor.W_Dtype,
             space.call_function(space.gettypefor(descriptor.W_Dtype), w_arg))
+
+def as_scalar(space, w_obj):
+    dtype = ufuncs.find_dtype_for_scalar(space, w_obj)
+    return dtype.coerce(space, w_obj)
diff --git a/pypy/module/micronumpy/descriptor.py b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -150,6 +150,9 @@
     def is_complex(self):
         return self.kind == NPY.COMPLEXLTR
 
+    def is_number(self):
+        return self.is_int() or self.is_float() or self.is_complex()
+
     def is_str(self):
         return self.num == NPY.STRING
 
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -4047,3 +4047,9 @@
 
         raises(TypeError, np.can_cast, 'i4', None)
         raises(TypeError, np.can_cast, None, 'i4')
+
+    def test_can_cast_scalar(self):
+        import numpy as np
+        assert np.can_cast(127, np.int8)
+        assert not np.can_cast(128, np.int8)
+        assert np.can_cast(128, np.int16)


More information about the pypy-commit mailing list