8000 ENH: Rename __numpy_ufunc__ to __array_ufunc__. · charris/numpy@db5878d · GitHub
[go: up one dir, main page]

Skip to content

Commit db5878d

Browse files
committed
ENH: Rename __numpy_ufunc__ to __array_ufunc__.
The first commit in changing __numpy_ufunc__ by removing the index argument and making the out argument value always a tuple. These changes were proposed in numpygh-5986 and have been accepted. Renaming before further changes avoids triggering tests in scipy and astropy while keeping the numpy tests working.
1 parent 8ea1993 commit db5878d

File tree

10 files changed

+61
-61
lines changed

10 files changed

+61
-61
lines changed

doc/source/reference/arrays.classes.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Special attributes and methods
3939

4040
NumPy provides several hooks that classes can customize:
4141

42-
.. method:: class.__numpy_ufunc__(ufunc, method, i, inputs, **kwargs)
42+
.. method:: class.__array_ufunc__(ufunc, method, i, inputs, **kwargs)
4343

4444
.. versionadded:: 1.11
4545

@@ -62,51 +62,51 @@ NumPy provides several hooks that classes can customize:
6262
:obj:`NotImplemented` if the operation requested is not
6363
implemented.
6464

65-
If one of the arguments has a :func:`__numpy_ufunc__` method, it is
65+
If one of the arguments has a :func:`__array_ufunc__` method, it is
6666
executed *instead* of the ufunc. If more than one of the input
67-
arguments implements :func:`__numpy_ufunc__`, they are tried in the
67+
arguments implements :func:`__array_ufunc__`, they are tried in the
6868
order: subclasses before superclasses, otherwise left to right. The
6969
first routine returning something else than :obj:`NotImplemented`
70-
determines the result. If all of the :func:`__numpy_ufunc__`
70+
determines the result. If all of the :func:`__array_ufunc__`
7171
operations return :obj:`NotImplemented`, a :exc:`TypeError` is
7272
raised.
7373

74-
If an :class:`ndarray` subclass defines the :func:`__numpy_ufunc__`
74+
If an :class:`ndarray` subclass defines the :func:`__array_ufunc__`
7575
method, this disables the :func:`__array_wrap__`,
7676
:func:`__array_prepare__`, :data:`__array_priority__` mechanism
7777
described below.
7878

79-
.. note:: In addition to ufuncs, :func:`__numpy_ufunc__` also
79+
.. note:: In addition to ufuncs, :func:`__array_ufunc__` also
8080
overrides the behavior of :func:`numpy.dot` even though it is
8181
not an Ufunc.
8282

8383
.. note:: If you also define right-hand binary operator override
8484
methods (such as ``__rmul__``) or comparison operations (such as
8585
``__gt__``) in your class, they take precedence over the
86-
:func:`__numpy_ufunc__` mechanism when resolving results of
86+
:func:`__array_ufunc__` mechanism when resolving results of
8787
binary operations (such as ``ndarray_obj * your_obj``).
8888

8989
The technical special case is: ``ndarray.__mul__`` returns
9090
``NotImplemented`` if the other object is *not* a subclass of
91-
:class:`ndarray`, and defines both ``__numpy_ufunc__`` and
91+
:class:`ndarray`, and defines both ``__array_ufunc__`` and
9292
``__rmul__``. Similar exception applies for the other operations
9393
than multiplication.
9494

9595
In such a case, when computing a binary operation such as
96-
``ndarray_obj * your_obj``, your ``__numpy_ufunc__`` method
96+
``ndarray_obj * your_obj``, your ``__array_ufunc__`` method
9797
*will not* be called. Instead, the execution passes on to your
9898
right-hand ``__rmul__`` operation, as per standard Python
9999
operator override rules.
100100

101101
Similar special case applies to *in-place operations*: If you
102102
define ``__rmul__``, then ``ndarray_obj *= your_obj`` *will not*
103-
call your ``__numpy_ufunc__`` implementation. Instead, the
103+
call your ``__array_ufunc__`` implementation. Instead, the
104104
default Python behavior ``ndarray_obj = ndarray_obj * your_obj``
105105
occurs.
106106

107107
Note that the above discussion applies only to Python's builtin
108108
binary operation mechanism. ``np.multiply(ndarray_obj,
109-
your_obj)`` always calls only your ``__numpy_ufunc__``, as
109+
your_obj)`` always calls only your ``__array_ufunc__``, as
110110
expected.
111111

112112
.. method:: class.__array_finalize__(obj)

numpy/core/src/multiarray/cblasfuncs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ _bad_strides(PyArrayObject *ap)
237237
* This is for use by PyArray_MatrixProduct2. It is assumed on entry that
238238
* the arrays ap1 and ap2 have a common data type given by typenum that is
239239
* float, double, cfloat, or cdouble and have dimension <= 2. The
240-
* __numpy_ufunc__ nonsense is also assumed to have been taken care of.
240+
* __array_ufunc__ nonsense is also assumed to have been taken care of.
241241
*/
242242
NPY_NO_EXPORT PyObject *
243243
cblas_matrixproduct(int typenum, PyArrayObject *ap1, PyArrayObject *ap2,

numpy/core/src/multiarray/multiarraymodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4535,7 +4535,7 @@ intern_strings(void)
45354535
npy_ma_str_array_wrap = PyUString_InternFromString("__array_wrap__");
45364536
npy_ma_str_array_finalize = PyUString_InternFromString("__array_finalize__");
45374537
npy_ma_str_buffer = PyUString_InternFromString("__buffer__");
4538-
npy_ma_str_ufunc = PyUString_InternFromString("__numpy_ufunc__");
4538+
npy_ma_str_ufunc = PyUString_InternFromString("__array_ufunc__");
45394539
npy_ma_str_order = PyUString_InternFromString("order");
45404540
npy_ma_str_copy = PyUString_InternFromString("copy");
45414541
npy_ma_str_dtype = PyUString_InternFromString("dtype");

numpy/core/src/multiarray/number.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ has_ufunc_attr(PyObject * obj) {
9595
return 0;
9696
}
9797
else {
98-
return PyObject_HasAttrString(obj, "__numpy_ufunc__");
98+
return PyObject_HasAttrString(obj, "__array_ufunc__");
9999
}
100100
}
101101

@@ -105,7 +105,7 @@ has_ufunc_attr(PyObject * obj) {
105105
*
106106
* This is the case when all of the following conditions apply:
107107
*
108-
* (i) the other object defines __numpy_ufunc__
108+
* (i) the other object defines __array_ufunc__
109109
* (ii) the other object defines the right-hand operation __r*__
110110
* (iii) Python hasn't already called the right-hand operation
111111
* [occurs if the other object is a strict subclass provided
@@ -118,7 +118,7 @@ has_ufunc_attr(PyObject * obj) {
118118
* This is needed, because CPython does not call __rmul__ if
119119
* the tp_number slots of the two objects are the same.
120120
*
121-
* This always prioritizes the __r*__ routines over __numpy_ufunc__, independent
121+
* This always prioritizes the __r*__ routines over __array_ufunc__, independent
122122
* of whether the other object is an ndarray subclass or not.
123123
*/
124124

numpy/core/src/private/ufunc_override.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,11 @@ normalize_at_args(PyUFuncObject *ufunc, PyObject *args,
160160
}
161161

162162
/*
163-
* Check a set of args for the `__numpy_ufunc__` method. If more than one of
164-
* the input arguments implements `__numpy_ufunc__`, they are tried in the
163+
* Check a set of args for the `__array_ufunc__` method. If more than one of
164+
* the input arguments implements `__array_ufunc__`, they are tried in the
165165
* order: subclasses before superclasses, otherwise left to right. The first
166166
* routine returning something other than `NotImplemented` determines the
167-
* result. If all of the `__numpy_ufunc__` operations returns `NotImplemented`,
167+
* result. If all of the `__array_ufunc__` operations returns `NotImplemented`,
168168
* a `TypeError` is raised.
169169
*
170170
* Returns 0 on success and 1 on exception. On success, *result contains the
@@ -249,7 +249,7 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
249249
_is_basic_python_type(obj)) {
250250
continue;
251251
}
252-
if (PyObject_HasAttrString(obj, "__numpy_ufunc__")) {
252+
if (PyObject_HasAttrString(obj, "__array_ufunc__")) {
253253
with_override[noa] = obj;
254254
with_override_pos[noa] = i;
255255
++noa;
@@ -318,7 +318,7 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
318318
}
319319

320320
/*
321-
* Call __numpy_ufunc__ functions in correct order
321+
* Call __array_ufunc__ functions in correct order
322322
*/
323323
while (1) {
324324
PyObject *numpy_ufunc;
@@ -361,13 +361,13 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
361361
if (!override_obj) {
362362
/* No acceptable override found. */
363363
PyErr_SetString(PyExc_TypeError,
364-
"__numpy_ufunc__ not implemented for this type.");
364+
"__array_ufunc__ not implemented for this type.");
365365
goto fail;
366366
}
367367

368368
/* Call the override */
369369
numpy_ufunc = PyObject_GetAttrString(override_obj,
370-
"__numpy_ufunc__");
370+
"__array_ufunc__");
371371
if (numpy_ufunc == NULL) {
372372
goto fail;
373373
}

numpy/core/src/umath/umathmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ intern_strings(void)
266266
npy_um_str_array_prepare = PyUString_InternFromString("__array_prepare__");
267267
npy_um_str_array_wrap = PyUString_InternFromString("__array_wrap__");
268268
npy_um_str_array_finalize = PyUString_InternFromString("__array_finalize__");
269-
npy_um_str_ufunc = PyUString_InternFromString("__numpy_ufunc__");
269+
npy_um_str_ufunc = PyUString_InternFromString("__array_ufunc__");
270270
npy_um_str_pyvals_name = PyUString_InternFromString(UFUNC_PYVALS_NAME);
271271

272272
return npy_um_str_out && npy_um_str_subok && npy_um_str_array_prepare &&

numpy/core/tests/test_multiarray.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,11 +2327,11 @@ def test_dot(self):
23272327

23282328
def test_dot_override(self):
23292329
class A(object):
2330-
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
2330+
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
23312331
return "A"
23322332

23332333
class B(object):
2334-
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
2334+
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
23352335
return NotImplemented
23362336

23372337
a = A()
@@ -2804,7 +2804,7 @@ def test_elide_scalar(self):
28042804

28052805
def test_ufunc_override_rop_precedence(self):
28062806
# Check that __rmul__ and other right-hand operations have
2807-
# precedence over __numpy_ufunc__
2807+
# precedence over __array_ufunc__
28082808

28092809
ops = {
28102810
'__add__': ('__radd__', np.add, True),
@@ -2832,8 +2832,8 @@ class OtherNdarraySubclass(np.ndarray):
28322832
pass
28332833

28342834
class OtherNdarraySubclassWithOverride(np.ndarray):
2835-
def __numpy_ufunc__(self, *a, **kw):
2836-
raise AssertionError(("__numpy_ufunc__ %r %r shouldn't have "
2835+
def __array_ufunc__(self, *a, **kw):
2836+
raise AssertionError(("__array_ufunc__ %r %r shouldn't have "
28372837
"been called!") % (a, kw))
28382838

28392839
def check(op_name, ndsubclass):
@@ -2852,8 +2852,8 @@ def check(op_name, ndsubclass):
28522852
def __init__(self, *a, **kw):
28532853
pass
28542854

2855-
def __numpy_ufunc__(self, *a, **kw):
2856-
raise AssertionError(("__numpy_ufunc__ %r %r shouldn't have "
2855+
def __array_ufunc__(self, *a, **kw):
2856+
raise AssertionError(("__array_ufunc__ %r %r shouldn't have "
28572857
"been called!") % (a, kw))
28582858

28592859
def __op__(self, *other):
@@ -2868,7 +2868,7 @@ def __rop__(self, *other):
28682868
bases = (object,)
28692869

28702870
dct = {'__init__': __init__,
2871-
'__numpy_ufunc__': __numpy_ufunc__,
2871+
'__array_ufunc__': __array_ufunc__,
28722872
op_name: __op__}
28732873
if op_name != rop_name:
28742874
dct[rop_name] = __rop__
@@ -2908,7 +2908,7 @@ def __rop__(self, *other):
29082908
# integer-like?
29092909
assert_equal(iop(arr, obj), "rop", err_msg=err_msg)
29102910

2911-
# Check that ufunc call __numpy_ufunc__ normally
2911+
# Check that ufunc call __array_ufunc__ normally
29122912
if np_op is not None:
29132913
assert_raises(AssertionError, np_op, arr, obj,
29142914
err_msg=err_msg)
@@ -2924,7 +2924,7 @@ def test_ufunc_override_rop_simple(self):
29242924
# Check parts of the binary op overriding behavior in an
29252925
# explicit test case that is easier to understand.
29262926
class SomeClass(object):
2927-
def __numpy_ufunc__(self, *a, **kw):
2927+
def __array_ufunc__(self, *a, **kw):
29282928
return "ufunc"
29292929

29302930
def __mul__(self, other):
@@ -2943,7 +2943,7 @@ def __lt__(self, other):
29432943
return "nope"
29442944

29452945
class SomeClass2(SomeClass, np.ndarray):
2946-
def __numpy_ufunc__(self, ufunc, method, i, inputs, **kw):
2946+
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
29472947
if ufunc is np.multiply or ufunc is np.bitwise_and:
29482948
return "ufunc"
29492949
else:
@@ -2971,17 +2971,17 @@ def __rsub__(self, other):
29712971

29722972
# obj is first, so should get to define outcome.
29732973
assert_equal(obj * arr, 123)
2974-
# obj is second, but has __numpy_ufunc__ and defines __rmul__.
2974+
# obj is second, but has __array_ufunc__ and defines __rmul__.
29752975
assert_equal(arr * obj, 321)
2976-
# obj is second, but has __numpy_ufunc__ and defines __rsub__.
2976+
# obj is second, but has __array_ufunc__ and defines __rsub__.
29772977
assert_equal(arr - obj, "no subs for me")
2978-
# obj is second, but has __numpy_ufunc__ and defines __lt__.
2978+
# obj is second, but has __array_ufunc__ and defines __lt__.
29792979
assert_equal(arr > obj, "nope")
2980-
# obj is second, but has __numpy_ufunc__ and defines __gt__.
2980+
# obj is second, but has __array_ufunc__ and defines __gt__.
29812981
assert_equal(arr < obj, "yep")
2982-
# Called as a ufunc, obj.__numpy_ufunc__ is used.
2982+
# Called as a ufunc, obj.__array_ufunc__ is used.
29832983
assert_equal(np.multiply(arr, obj), "ufunc")
2984-
# obj is second, but has __numpy_ufunc__ and defines __rmul__.
2984+
# obj is second, but has __array_ufunc__ and defines __rmul__.
29852985
arr *= obj
29862986
assert_equal(arr, 321)
29872987

@@ -2991,7 +2991,7 @@ def __rsub__(self, other):
29912991
assert_equal(arr - obj2, "no subs for me")
29922992
assert_equal(arr > obj2, "nope")
29932993
assert_equal(arr < obj2, "yep")
2994-
# Called as a ufunc, obj2.__numpy_ufunc__ is called.
2994+
# Called as a ufunc, obj2.__array_ufunc__ is called.
29952995
assert_equal(np.multiply(arr, obj2), "ufunc")
29962996
# Also when the method is not overridden.
29972997
assert_equal(arr & obj2, "ufunc")
@@ -3012,13 +3012,13 @@ def __rsub__(self, other):
30123012
assert_equal(obj2 * obj3, 123)
30133013
# And of course, here obj3.__mul__ should be called.
30143014
assert_equal(obj3 * obj2, 123)
3015-
# obj3 defines __numpy_ufunc__ but obj3.__radd__ is obj2.__radd__.
3015+
# obj3 defines __array_ufunc__ but obj3.__radd__ is obj2.__radd__.
30163016
# (and both are just ndarray.__radd__); see #4815.
30173017
res = obj2 + obj3
30183018
assert_equal(res, 46)
30193019
assert_(isinstance(res, SomeClass2))
30203020
# Since obj3 is a subclass, it should have precedence, like CPython
3021-
# would give, even though obj2 has __numpy_ufunc__ and __radd__.
3021+
# would give, even though obj2 has __array_ufunc__ and __radd__.
30223022
# See gh-4815 and gh-5747.
30233023
res = obj3 + obj2
30243024
assert_equal(res, 46)
@@ -3027,7 +3027,7 @@ def __rsub__(self, other):
30273027
def test_ufunc_override_normalize_signature(self):
30283028
# gh-5674
30293029
class SomeClass(object):
3030-
def __numpy_ufunc__(self, ufunc, method, i, inputs, **kw):
3030+
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
30313031
return kw
30323032

30333033
a = SomeClass()
@@ -3044,7 +3044,7 @@ def test_numpy_ufunc_index(self):
30443044
# Check that index is set appropriately, also if only an output
30453045
# is passed on (latter is another regression tests for github bug 4753)
30463046
class CheckIndex(object):
3047-
def __numpy_ufunc__(self, ufunc, method, i, inputs, **kw):
3047+
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
30483048
return i
30493049

30503050
a = CheckIndex()
@@ -3080,7 +3080,7 @@ def __numpy_ufunc__(self, ufunc, method, i, inputs, **kw):
30803080
def test_out_override(self):
30813081
# regression test for github bug 4753
30823082
class OutClass(np.ndarray):
3083-
def __numpy_ufunc__(self, ufunc, method, i, inputs, **kw):
3083+
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
30843084
if 'out' in kw:
30853085
tmp_kw = kw.copy()
30863086
tmp_kw.pop('out')
@@ -5213,14 +5213,14 @@ class A(np.ndarray):
52135213
def __new__(cls, *args, **kwargs):
52145214
return np.array(*args, **kwargs).view(cls)
52155215

5216-
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
5216+
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
52175217
return "A"
52185218

52195219
class B(np.ndarray):
52205220
def __new__(cls, *args, **kwargs):
52215221
return np.array(*args, **kwargs).view(cls)
52225222

5223-
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
5223+
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
52245224
return NotImplemented
52255225

52265226
a = A([1, 2])

numpy/core/tests/test_ufunc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ def test_structured_equal(self):
12251225
# https://github.com/numpy/numpy/issues/4855
12261226

12271227
class MyA(np.ndarray):
1228-
def __numpy_ufunc__(self, ufunc, method, i, inputs, **kwargs):
1228+
def __array_ufunc__(self, ufunc, method, i, inputs, **kwargs):
12291229
return getattr(ufunc, method)(*(input.view(np.ndarray)
12301230
for input in inputs), **kwargs)
12311231
a = np.arange(12.).reshape(4,3)

0 commit comments

Comments
 (0)
0