Skip to content

BUG: ufunc.__call__ treats out passed by position and keyword differently #10450

@eric-wieser

Description

@eric-wieser

Extracted from #10382, which this is partly the cause of.

Using this simple class to debug:

class MyArray(np.ndarray):
    def __array_wrap__(self, obj, context=None):
        print('__array_wrap__   ({}, {}, {})'.format(self, obj,context))
        return self
    def __array_prepare__(self, obj, context=None):
        print('__array_prepare__({}, {}, {})'.format(self, obj,context))
        return self

a = np.zeros((), int).view(MyArray)

we have:

# all ok
>>> np.add(-1, 1, a)
__array_prepare__(0, 0, (<ufunc 'add'>, (-1, 1, MyArray(0)), 0))
__array_wrap__   (0, 0, (<ufunc 'add'>, (-1, 1, MyArray(0)), 0))

# no out argument to __array_wrap__
>>> np.add(-1, 1, out=a)
__array_prepare__(0, 0, (<ufunc 'add'>, (-1, 1, MyArray(0)), 0))
__array_wrap__   (0, 0, (<ufunc 'add'>, (-1, 1), 0))

# where did __array_prepare__ go?
>>> np.add(-1, 1, out=(a,))
__array_wrap__   (0, 0, (<ufunc 'add'>, (-1, 1), 0))

and with an input

#ok
>>> np.add(0, a, a)
__array_prepare__(0, 0, (<ufunc 'add'>, (0, MyArray(0), MyArray(0)), 0))
__array_wrap__   (0, 0, (<ufunc 'add'>, (0, MyArray(0), MyArray(0)), 0))

# no out argument to __array_wrap__
>>> np.add(0, a, out=a)
__array_prepare__(0, 0, (<ufunc 'add'>, (0, MyArray(0), MyArray(0)), 0))
__array_wrap__   (0, 0, (<ufunc 'add'>, (0, MyArray(0)), 0))

# holy tuple batman
>>> np.add(0, a, out=(a,))
__array_prepare__(0, 0, (<ufunc 'add'>, (0, MyArray(0), (MyArray(0),)), 0))
__array_wrap__   (0, 0, (<ufunc 'add'>, (0, MyArray(0)), 0))

I can see a few other places where this bug might exist too - anything passing args in PyUfunc_GenericFunction` may be guilty. I think we need to fix this at the earliest possible location, and convert positional to keyword arguments as soon as possible.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions