1
1
from __future__ import division , absolute_import , print_function
2
2
3
3
import numbers
4
+ import operator
4
5
5
6
import numpy as np
6
- from numpy .testing import TestCase , run_module_suite , assert_ , assert_equal
7
+ from numpy .testing import (
8
+ TestCase , run_module_suite , assert_ , assert_equal , assert_raises )
7
9
8
10
9
11
class ArrayLike (np .NDArrayOperatorsMixin ):
@@ -24,8 +26,6 @@ class ArrayLike(np.NDArrayOperatorsMixin):
24
26
def __init__ (self , value ):
25
27
self .value = np .asarray (value )
26
28
27
- # __array_priority__ = 1000 # for legacy reasons
28
-
29
29
_handled_types = (np .ndarray , numbers .Number )
30
30
31
31
def __array_ufunc__ (self , ufunc , method , * inputs , ** kwargs ):
@@ -44,22 +44,74 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
44
44
kwargs ['out' ] = tuple (x .value if isinstance (self , type (x )) else x
45
45
for x in out )
46
46
result = getattr (ufunc , method )(* inputs , ** kwargs )
47
- if isinstance (result , tuple ):
47
+
48
+ if type (result ) is tuple :
49
+ # multiple return values
48
50
return tuple (type (self )(x ) for x in result )
49
- else :
51
+ elif result is not None :
52
+ # one return value
50
53
return type (self )(result )
54
+ else :
55
+ # no return return value, e.g., ufunc.at
56
+ return None
51
57
52
58
def __repr__ (self ):
53
59
return '%s(%r)' % (type (self ).__name__ , self .value )
54
60
55
61
62
+ def _assert_equal_type_and_value (result , expected ):
63
+ assert_equal (type (result ), type (expected ))
64
+ assert_equal (result .value , expected .value )
65
+
66
+
56
67
class TestNDArrayOperatorsMixin (TestCase ):
57
68
58
- def test_array_like (self ):
69
+ def test_array_like_add (self ):
70
+
71
+ def check (result ):
72
+ _assert_equal_type_and_value (result , ArrayLike (0 ))
73
+
74
+ check (ArrayLike (0 ) + 0 )
75
+ check (0 + ArrayLike (0 ))
76
+
77
+ check (ArrayLike (0 ) + np .array (0 ))
78
+ check (np .array (0 ) + ArrayLike (0 ))
79
+
80
+ check (ArrayLike (np .array (0 )) + 0 )
81
+ check (0 + ArrayLike (np .array (0 )))
82
+
83
+ check (ArrayLike (np .array (0 )) + np .array (0 ))
84
+ check (np .array (0 ) + ArrayLike (np .array (0 )))
85
+
86
+ def test_divmod (self ):
87
+ # divmod is subtle: it's returns a tuple
59
88
60
- x = ArrayLike (1 )
61
- assert_ (isinstance (x + 1 , ArrayLike ))
62
- assert_equal ((x + 1 ).value , 2 )
89
+ def check (result ):
90
+ assert_ (type (result ) is tuple )
91
+ assert_equal (len (result ), 2 )
92
+ _assert_equal_type_and_value (result [0 ], ArrayLike (1 ))
93
+ _assert_equal_type_and_value (result [1 ], ArrayLike (0 ))
94
+
95
+ check (divmod (ArrayLike (2 ), 2 ))
96
+ check (divmod (2 , ArrayLike (2 )))
97
+
98
+ check (divmod (ArrayLike (2 ), np .array (2 )))
99
+ check (divmod (np .array (2 ), ArrayLike (2 )))
100
+
101
+ check (divmod (ArrayLike (np .array (2 )), 2 ))
102
+ check (divmod (2 , ArrayLike (np .array (2 ))))
103
+
104
+ check (divmod (ArrayLike (np .array (2 )), np .array (2 )))
105
+ check (divmod (np .array (2 ), ArrayLike (np .array (2 ))))
106
+
107
+ def test_inplace (self ):
108
+ array_like = ArrayLike (np .array ([0 ]))
109
+ array_like += 1
110
+ _assert_equal_type_and_value (array_like , ArrayLike (np .array ([1 ])))
111
+
112
+ array = np .array ([0 ])
113
+ array += ArrayLike (1 )
114
+ _assert_equal_type_and_value (array , ArrayLike (np .array ([1 ])))
63
115
64
116
def test_opt_out (self ):
65
117
@@ -73,29 +125,33 @@ def __add__(self, other):
73
125
def __radd__ (self , other ):
74
126
return self
75
127
76
- x = ArrayLike (1 )
77
- o = OptOut ()
78
- assert_ (isinstance (x + o , OptOut ))
79
- assert_ (isinstance (o + x , OptOut ))
128
+ array_like = ArrayLike (1 )
129
+ opt_out = OptOut ()
130
+
131
+ # supported operations
132
+ assert_ (array_like + opt_out is opt_out )
133
+ assert_ (opt_out + array_like is opt_out )
134
+
135
+ # not supported
136
+ with assert_raises (TypeError ):
137
+ # don't use the Python default, array_like = array_like + opt_out
138
+ array_like += opt_out
139
+ with assert_raises (TypeError ):
140
+ array_like - opt_out
141
+ with assert_raises (TypeError ):
142
+ opt_out - array_like
80
143
81
144
def test_subclass (self ):
82
145
83
146
class SubArrayLike (ArrayLike ):
84
147
"""Should take precedence over ArrayLike."""
85
148
86
- # TODO
87
-
88
- def test_ndarray (self ):
89
- pass
90
-
91
- def test_ndarray_subclass (self ):
92
- pass
93
-
94
- def test_out (self ):
95
- pass
149
+ x = ArrayLike (0 )
150
+ y = SubArrayLike (1 )
151
+ _assert_equal_type_and_value (x + y , y )
152
+ _assert_equal_type_and_value (y + x , y )
96
153
97
- def test_all_operators (self ):
98
- pass
154
+ # TODO(shoyer): test every operator to ensure it's properly implemented
99
155
100
156
101
157
if __name__ == "__main__" :
0 commit comments