summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/tests/test_multiarray.py47
1 files changed, 44 insertions, 3 deletions
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 937ca9d72..42222e71d 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -2299,7 +2299,6 @@ class TestBinop(object):
def test_ufunc_override_rop_simple(self):
# Check parts of the binary op overriding behavior in an
# explicit test case that is easier to understand.
-
class SomeClass(object):
def __numpy_ufunc__(self, *a, **kw):
return "ufunc"
@@ -2307,6 +2306,8 @@ class TestBinop(object):
return 123
def __rmul__(self, other):
return 321
+ def __rsub__(self, other):
+ return "no subs for me"
def __gt__(self, other):
return "yep"
def __lt__(self, other):
@@ -2314,7 +2315,7 @@ class TestBinop(object):
class SomeClass2(SomeClass, ndarray):
def __numpy_ufunc__(self, ufunc, method, i, inputs, **kw):
- if ufunc is np.multiply:
+ if ufunc is np.multiply or ufunc is np.bitwise_and:
return "ufunc"
else:
inputs = list(inputs)
@@ -2324,28 +2325,47 @@ class TestBinop(object):
if 'out' in kw:
return r
else:
- x = SomeClass2(r.shape, dtype=r.dtype)
+ x = self.__class__(r.shape, dtype=r.dtype)
x[...] = r
return x
+ class SomeClass3(SomeClass2):
+ def __rsub__(self, other):
+ return "sub for me"
+
arr = np.array([0])
obj = SomeClass()
obj2 = SomeClass2((1,), dtype=np.int_)
obj2[0] = 9
+ obj3 = SomeClass3((1,), dtype=np.int_)
+ obj3[0] = 4
+ # obj is first, so should get to define outcome.
assert_equal(obj * arr, 123)
+ # obj is second, but has __numpy_ufunc__ and defines __rmul__.
assert_equal(arr * obj, 321)
+ # obj is second, but has __numpy_ufunc__ and defines __rsub__.
+ assert_equal(arr - obj, "no subs for me")
+ # obj is second, but has __numpy_ufunc__ and defines __lt__.
assert_equal(arr > obj, "nope")
+ # obj is second, but has __numpy_ufunc__ and defines __gt__.
assert_equal(arr < obj, "yep")
+ # Called as a ufunc, obj.__numpy_ufunc__ is used.
assert_equal(np.multiply(arr, obj), "ufunc")
+ # obj is second, but has __numpy_ufunc__ and defines __rmul__.
arr *= obj
assert_equal(arr, 321)
+ # obj2 is an ndarray subclass, so CPython takes care of the same rules.
assert_equal(obj2 * arr, 123)
assert_equal(arr * obj2, 321)
+ assert_equal(arr - obj2, "no subs for me")
assert_equal(arr > obj2, "nope")
assert_equal(arr < obj2, "yep")
+ # Called as a ufunc, obj2.__numpy_ufunc__ is called.
assert_equal(np.multiply(arr, obj2), "ufunc")
+ # Also when the method is not overridden.
+ assert_equal(arr & obj2, "ufunc")
arr *= obj2
assert_equal(arr, 321)
@@ -2354,6 +2374,27 @@ class TestBinop(object):
assert_equal(obj2.sum(), 42)
assert_(isinstance(obj2, SomeClass2))
+ # Obj3 is subclass that defines __rsub__. CPython calls it.
+ assert_equal(arr - obj3, "sub for me")
+ assert_equal(obj2 - obj3, "sub for me")
+ # obj3 is a subclass that defines __rmul__. CPython calls it.
+ assert_equal(arr * obj3, 321)
+ # But not here, since obj3.__rmul__ is obj2.__rmul__.
+ assert_equal(obj2 * obj3, 123)
+ # And of course, here obj3.__mul__ should be called.
+ assert_equal(obj3 * obj2, 123)
+ # obj3 defines __numpy_ufunc__ but obj3.__radd__ is obj2.__radd__.
+ # (and both are just ndarray.__radd__); see #4815.
+ res = obj2 + obj3
+ assert_equal(res, 46)
+ assert_(isinstance(res, SomeClass2))
+ # Since obj3 is a subclass, it should have precedence, like CPython
+ # would give, even though obj2 has __numpy_ufunc__ and __radd__.
+ # See gh-4815 and gh-5747.
+ res = obj3 + obj2
+ assert_equal(res, 46)
+ assert_(isinstance(res, SomeClass3))
+
def test_ufunc_override_normalize_signature(self):
# gh-5674
class SomeClass(object):