Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e6956dd

Browse files
committed
MAINT: Remove duplicated logic between array_wrap and array_prepare
This behaves exactly as before
1 parent 8a772dd commit e6956dd

File tree

1 file changed

+49
-60
lines changed

1 file changed

+49
-60
lines changed

numpy/core/src/umath/ufunc_object.c

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,43 @@ _find_array_method(PyObject *args, int nin, PyObject *method_name)
184184
return method;
185185
}
186186

187+
/*
188+
* Returns an incref'ed pointer to the proper __array_prepare__/__array_wrap__
189+
* method for a ufunc output argument, given the output argument `obj`, and the
190+
* method chosen from the inputs `input_method`.
191+
*/
192+
static PyObject *
193+
_get_output_array_method(PyObject *obj, PyObject *method,
194+
PyObject *input_method) {
195+
if (obj != Py_None) {
196+
PyObject *ometh;
197+
198+
if (PyArray_CheckExact(obj)) {
199+
/*
200+
* No need to wrap regular arrays - None signals to not call
201+
* wrap/prepare at all
202+
*/
203+
Py_RETURN_NONE;
204+
}
205+
206+
ometh = PyObject_GetAttr(obj, method);
207+
if (ometh == NULL) {
208+
PyErr_Clear();
209+
}
210+
else if (!PyCallable_Check(ometh)) {
211+
Py_DECREF(ometh);
212+
}
213+
else {
214+
/* Use the wrap/prepare method of the output if it's callable */
215+
return ometh;
216+
}
217+
}
218+
219+
/* Fall back on the input's wrap/prepare */
220+
Py_XINCREF(input_method);
221+
return input_method;
222+
}
223+
187224
/*
188225
* This function analyzes the input arguments
189226
* and determines an appropriate __array_prepare__ function to call
@@ -206,13 +243,12 @@ _find_array_prepare(PyObject *args, PyObject *kwds,
206243
{
207244
Py_ssize_t nargs;
208245
int i;
209-
PyObject *obj, *prep;
210246

211247
/*
212248
* Determine the prepping function given by the input arrays
213249
* (could be NULL).
214250
*/
215-
prep = _find_array_method(args, nin, npy_um_str_array_prepare);
251+
PyObject *prep = _find_array_method(args, nin, npy_um_str_array_prepare);
216252
/*
217253
* For all the output arrays decide what to do.
218254
*
@@ -228,9 +264,7 @@ _find_array_prepare(PyObject *args, PyObject *kwds,
228264
nargs = PyTuple_GET_SIZE(args);
229265
for (i = 0; i < nout; i++) {
230266
int j = nin + i;
231-
int incref = 1;
232-
output_prep[i] = prep;
233-
obj = NULL;
267+
PyObject *obj = NULL;
234268
if (j < nargs) {
235269
obj = PyTuple_GET_ITEM(args, j);
236270
/* Output argument one may also be in a keyword argument */
@@ -243,27 +277,13 @@ _find_array_prepare(PyObject *args, PyObject *kwds,
243277
obj = PyDict_GetItem(kwds, npy_um_str_out);
244278
}
245279

246-
if (obj != Py_None && obj != NULL) {
247-
if (PyArray_CheckExact(obj)) {
248-
/* None signals to not call any wrapping */
249-
output_prep[i] = Py_None;
250-
}
251-
else {
252-
PyObject *oprep = PyObject_GetAttr(obj,
253-
npy_um_str_array_prepare);
254-
incref = 0;
255-
if (!(oprep) || !(PyCallable_Check(oprep))) {
256-
Py_XDECREF(oprep);
257-
oprep = prep;
258-
incref = 1;
259-
PyErr_Clear();
260-
}
261-
output_prep[i] = oprep;
262-
}
280+
if (obj == NULL) {
281+
Py_XINCREF(prep);
282+
output_prep[i] = prep;
263283
}
264-
265-
if (incref) {
266-
Py_XINCREF(output_prep[i]);
284+
else {
285+
output_prep[i] = _get_output_array_method(
286+
obj, npy_um_str_array_prepare, prep);
267287
}
268288
}
269289
Py_XDECREF(prep);
@@ -3893,38 +3913,6 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
38933913
return NULL;
38943914
}
38953915

3896-
/*
3897-
* Returns an incref'ed pointer to the proper wrapping object for a
3898-
* ufunc output argument, given the output argument 'out', and the
3899-
* input's wrapping function, 'wrap'.
3900-
*/
3901-
static PyObject*
3902-
_get_out_wrap(PyObject *out, PyObject *wrap) {
3903-
PyObject *owrap;
3904-
3905-
if (out == Py_None) {
3906-
/* Iterator allocated outputs get the input's wrapping */
3907-
Py_XINCREF(wrap);
3908-
return wrap;
3909-
}
3910-
if (PyArray_CheckExact(out)) {
3911-
/* None signals to not call any wrapping */
3912-
Py_RETURN_NONE;
3913-
}
3914-
/*
3915-
* For array subclasses use their __array_wrap__ method, or the
3916-
* input's wrapping if not available
3917-
*/
3918-
owrap = PyObject_GetAttr(out, npy_um_str_array_wrap);
3919-
if (owrap == NULL || !PyCallable_Check(owrap)) {
3920-
Py_XDECREF(owrap);
3921-
owrap = wrap;
3922-
Py_XINCREF(wrap);
3923-
PyErr_Clear();
3924-
}
3925-
return owrap;
3926-
}
3927-
39283916
/*
39293917
* This function analyzes the input arguments
39303918
* and determines an appropriate __array_wrap__ function to call
@@ -4001,7 +3989,8 @@ _find_array_wrap(PyObject *args, PyObject *kwds,
40013989
}
40023990
else {
40033991
/* If the kwarg is not a tuple then it is an array (or None) */
4004-
output_wrap[0] = _get_out_wrap(obj, wrap);
3992+
output_wrap[0] = _get_output_array_method(
3993+
obj, npy_um_str_array_wrap, wrap);
40053994
start_idx = 1;
40063995
nargs = 1;
40073996
}
@@ -4012,8 +4001,8 @@ _find_array_wrap(PyObject *args, PyObject *kwds,
40124001
int j = idx_offset + i;
40134002

40144003
if (j < nargs) {
4015-
output_wrap[i] = _get_out_wrap(PyTuple_GET_ITEM(obj, j),
4016-
wrap);
4004+
output_wrap[i] = _get_output_array_method(
4005+
PyTuple_GET_ITEM(obj, j), npy_um_str_array_wrap, wrap);
40174006
}
40184007
else {
40194008
output_wrap[i] = wrap;

0 commit comments

Comments
 (0)