Skip to content

Commit 9cd9c6c

Browse files
committed
Merge pull request numpy#4920 from juliantaylor/ufunc-disable
disable ufunc override for 1.9 release
2 parents d3efa83 + 2acbfa7 commit 9cd9c6c

File tree

8 files changed

+37
-81
lines changed

8 files changed

+37
-81
lines changed

doc/release/1.9.0-notes.rst

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ This release supports Python 2.6 - 2.7 and 3.2 - 3.4.
66

77
Highlights
88
==========
9-
* Addition of `__numpy_ufunc__` to allow overriding ufuncs in ndarray
10-
subclasses.
119
* Numerous performance improvements in various areas, most notably indexing and
1210
operations on small arrays are significantly faster.
1311
Indexing operations now also release the GIL.
@@ -269,13 +267,6 @@ ufunc reductions do since 1.7. One can now say axis=(index, index) to pick a
269267
list of axes for the reduction. The ``keepdims`` keyword argument was also
270268
added to allow convenient broadcasting to arrays of the original shape.
271269

272-
Ufunc and Dot Overrides
273-
~~~~~~~~~~~~~~~~~~~~~~~
274-
For better compatibility with external objects you can now override
275-
universal functions (ufuncs), ``numpy.core._dotblas.dot``, and
276-
``numpy.core.multiarray.dot`` (the numpy.dot functions). By defining a
277-
``__numpy_ufunc__`` method.
278-
279270
Dtype parameter added to ``np.linspace`` and ``np.logspace``
280271
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
281272
The returned data type from the ``linspace`` and ``logspace`` functions can

doc/source/reference/arrays.classes.rst

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -39,76 +39,6 @@ Special attributes and methods
3939

4040
Numpy provides several hooks that classes can customize:
4141

42-
.. function:: class.__numpy_ufunc__(self, ufunc, method, i, inputs, **kwargs)
43-
44-
.. versionadded:: 1.9
45-
46-
Any class (ndarray subclass or not) can define this method to
47-
override behavior of Numpy's ufuncs. This works quite similarly to
48-
Python's ``__mul__`` and other binary operation routines.
49-
50-
- *ufunc* is the ufunc object that was called.
51-
- *method* is a string indicating which Ufunc method was called
52-
(one of ``"__call__"``, ``"reduce"``, ``"reduceat"``,
53-
``"accumulate"``, ``"outer"``, ``"inner"``).
54-
- *i* is the index of *self* in *inputs*.
55-
- *inputs* is a tuple of the input arguments to the ``ufunc``
56-
- *kwargs* is a dictionary containing the optional input arguments
57-
of the ufunc. The ``out`` argument is always contained in
58-
*kwargs*, if given. See the discussion in :ref:`ufuncs` for
59-
details.
60-
61-
The method should return either the result of the operation, or
62-
:obj:`NotImplemented` if the operation requested is not
63-
implemented.
64-
65-
If one of the arguments has a :func:`__numpy_ufunc__` method, it is
66-
executed *instead* of the ufunc. If more than one of the input
67-
arguments implements :func:`__numpy_ufunc__`, they are tried in the
68-
order: subclasses before superclasses, otherwise left to right. The
69-
first routine returning something else than :obj:`NotImplemented`
70-
determines the result. If all of the :func:`__numpy_ufunc__`
71-
operations return :obj:`NotImplemented`, a :exc:`TypeError` is
72-
raised.
73-
74-
If an :class:`ndarray` subclass defines the :func:`__numpy_ufunc__`
75-
method, this disables the :func:`__array_wrap__`,
76-
:func:`__array_prepare__`, :data:`__array_priority__` mechanism
77-
described below.
78-
79-
.. note:: In addition to ufuncs, :func:`__numpy_ufunc__` also
80-
overrides the behavior of :func:`numpy.dot` even though it is
81-
not an Ufunc.
82-
83-
.. note:: If you also define right-hand binary operator override
84-
methods (such as ``__rmul__``) or comparison operations (such as
85-
``__gt__``) in your class, they take precedence over the
86-
:func:`__numpy_ufunc__` mechanism when resolving results of
87-
binary operations (such as ``ndarray_obj * your_obj``).
88-
89-
The technical special case is: ``ndarray.__mul__`` returns
90-
``NotImplemented`` if the other object is *not* a subclass of
91-
:class:`ndarray`, and defines both ``__numpy_ufunc__`` and
92-
``__rmul__``. Similar exception applies for the other operations
93-
than multiplication.
94-
95-
In such a case, when computing a binary operation such as
96-
``ndarray_obj * your_obj``, your ``__numpy_ufunc__`` method
97-
*will not* be called. Instead, the execution passes on to your
98-
right-hand ``__rmul__`` operation, as per standard Python
99-
operator override rules.
100-
101-
Similar special case applies to *in-place operations*: If you
102-
define ``__rmul__``, then ``ndarray_obj *= your_obj`` *will not*
103-
call your ``__numpy_ufunc__`` implementation. Instead, the
104-
default Python behavior ``ndarray_obj = ndarray_obj * your_obj``
105-
occurs.
106-
107-
Note that the above discussion applies only to Python's builtin
108-
binary operation mechanism. ``np.multiply(ndarray_obj,
109-
your_obj)`` always calls only your ``__numpy_ufunc__``, as
110-
expected.
111-
11242
.. function:: class.__array_finalize__(self)
11343

11444
This method is called whenever the system internally allocates a

numpy/core/src/private/ufunc_override.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
188188
/* Pos of each override in args */
189189
int with_override_pos[NPY_MAXARGS];
190190

191+
/* disabled until remaining issues are fixed */
192+
*result = NULL;
193+
return 0;
194+
191195
/*
192196
* Check inputs
193197
*/

numpy/core/tests/test_blasdot.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def test_dot_array_order():
152152
assert_almost_equal(b.dot(c), _dot(b, c), decimal=prec)
153153
assert_almost_equal(c.T.dot(b.T), _dot(c.T, b.T), decimal=prec)
154154

155+
@dec.skipif(True) # ufunc override disabled for 1.9
155156
def test_dot_override():
156157
class A(object):
157158
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):

numpy/core/tests/test_multiarray.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,7 @@ def test_dot(self):
16401640
a.dot(b=b, out=c)
16411641
assert_equal(c, np.dot(a, b))
16421642

1643+
@dec.skipif(True) # ufunc override disabled for 1.9
16431644
def test_dot_override(self):
16441645
class A(object):
16451646
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
@@ -1770,6 +1771,7 @@ def test_conjugate(self):
17701771

17711772

17721773
class TestBinop(object):
1774+
@dec.skipif(True) # ufunc override disabled for 1.9
17731775
def test_ufunc_override_rop_precedence(self):
17741776
# Check that __rmul__ and other right-hand operations have
17751777
# precedence over __numpy_ufunc__
@@ -1888,6 +1890,7 @@ def __rop__(self, *other):
18881890
yield check, op_name, True
18891891
yield check, op_name, False
18901892

1893+
@dec.skipif(True) # ufunc override disabled for 1.9
18911894
def test_ufunc_override_rop_simple(self):
18921895
# Check parts of the binary op overriding behavior in an
18931896
# explicit test case that is easier to understand.

numpy/core/tests/test_umath.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ def __array__(self):
962962
assert_equal(ncu.maximum(a, B()), 0)
963963
assert_equal(ncu.maximum(a, C()), 0)
964964

965+
@dec.skipif(True) # ufunc override disabled for 1.9
965966
def test_ufunc_override(self):
966967
class A(object):
967968
def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs):
@@ -988,6 +989,7 @@ def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs):
988989
assert_equal(res0[5], {})
989990
assert_equal(res1[5], {})
990991

992+
@dec.skipif(True) # ufunc override disabled for 1.9
991993
def test_ufunc_override_mro(self):
992994

993995
# Some multi arg functions for testing.
@@ -1081,6 +1083,7 @@ def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs):
10811083
assert_raises(TypeError, four_mul_ufunc, 1, 2, c_sub, c)
10821084
assert_raises(TypeError, four_mul_ufunc, 1, c, c_sub, c)
10831085

1086+
@dec.skipif(True) # ufunc override disabled for 1.9
10841087
def test_ufunc_override_methods(self):
10851088
class A(object):
10861089
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
@@ -1184,6 +1187,7 @@ def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
11841187
assert_equal(res[3], 0)
11851188
assert_equal(res[4], (a, [4, 2], 'b0'))
11861189

1190+
@dec.skipif(True) # ufunc override disabled for 1.9
11871191
def test_ufunc_override_out(self):
11881192
class A(object):
11891193
def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
@@ -1218,6 +1222,7 @@ def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
12181222
assert_equal(res7['out'][0], 'out0')
12191223
assert_equal(res7['out'][1], 'out1')
12201224

1225+
@dec.skipif(True) # ufunc override disabled for 1.9
12211226
def test_ufunc_override_exception(self):
12221227
class A(object):
12231228
def __numpy_ufunc__(self, *a, **kwargs):

numpy/lib/tests/test_twodim_base.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,28 @@ def test_tril_triu_with_inf():
324324
assert_array_equal(np.tril(arr), out_tril)
325325

326326

327+
def test_tril_triu_dtype():
328+
# Issue 4916
329+
# tril and triu should return the same dtype as input
330+
for c in np.typecodes['All']:
331+
if c == 'V':
332+
continue
333+
arr = np.zeros((3, 3), dtype=c)
334+
assert_equal(np.triu(arr).dtype, arr.dtype)
335+
assert_equal(np.tril(arr).dtype, arr.dtype)
336+
337+
# check special cases
338+
arr = np.array([['2001-01-01T12:00', '2002-02-03T13:56'],
339+
['2004-01-01T12:00', '2003-01-03T13:45']],
340+
dtype='datetime64')
341+
assert_equal(np.triu(arr).dtype, arr.dtype)
342+
assert_equal(np.tril(arr).dtype, arr.dtype)
343+
344+
arr = np.zeros((3,3), dtype='f4,f4')
345+
assert_equal(np.triu(arr).dtype, arr.dtype)
346+
assert_equal(np.tril(arr).dtype, arr.dtype)
347+
348+
327349
def test_mask_indices():
328350
# simple test without offset
329351
iu = mask_indices(3, np.triu)

numpy/lib/twodim_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ def tril(m, k=0):
453453
m = asanyarray(m)
454454
mask = tri(*m.shape[-2:], k=k, dtype=bool)
455455

456-
return where(mask, m, 0)
456+
return where(mask, m, zeros(1, m.dtype))
457457

458458

459459
def triu(m, k=0):
@@ -481,7 +481,7 @@ def triu(m, k=0):
481481
m = asanyarray(m)
482482
mask = tri(*m.shape[-2:], k=k-1, dtype=bool)
483483

484-
return where(mask, 0, m)
484+
return where(mask, zeros(1, m.dtype), m)
485485

486486

487487
# Originally borrowed from John Hunter and matplotlib

0 commit comments

Comments
 (0)