@@ -184,6 +184,43 @@ _find_array_method(PyObject *args, int nin, PyObject *method_name)
184
184
return method ;
185
185
}
186
186
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
+
187
224
/*
188
225
* This function analyzes the input arguments
189
226
* and determines an appropriate __array_prepare__ function to call
@@ -206,13 +243,12 @@ _find_array_prepare(PyObject *args, PyObject *kwds,
206
243
{
207
244
Py_ssize_t nargs ;
208
245
int i ;
209
- PyObject * obj , * prep ;
210
246
211
247
/*
212
248
* Determine the prepping function given by the input arrays
213
249
* (could be NULL).
214
250
*/
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 );
216
252
/*
217
253
* For all the output arrays decide what to do.
218
254
*
@@ -228,9 +264,7 @@ _find_array_prepare(PyObject *args, PyObject *kwds,
228
264
nargs = PyTuple_GET_SIZE (args );
229
265
for (i = 0 ; i < nout ; i ++ ) {
230
266
int j = nin + i ;
231
- int incref = 1 ;
232
- output_prep [i ] = prep ;
233
- obj = NULL ;
267
+ PyObject * obj = NULL ;
234
268
if (j < nargs ) {
235
269
obj = PyTuple_GET_ITEM (args , j );
236
270
/* Output argument one may also be in a keyword argument */
@@ -243,27 +277,13 @@ _find_array_prepare(PyObject *args, PyObject *kwds,
243
277
obj = PyDict_GetItem (kwds , npy_um_str_out );
244
278
}
245
279
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 ;
263
283
}
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 );
267
287
}
268
288
}
269
289
Py_XDECREF (prep );
@@ -3893,38 +3913,6 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
3893
3913
return NULL ;
3894
3914
}
3895
3915
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
-
3928
3916
/*
3929
3917
* This function analyzes the input arguments
3930
3918
* and determines an appropriate __array_wrap__ function to call
@@ -4001,7 +3989,8 @@ _find_array_wrap(PyObject *args, PyObject *kwds,
4001
3989
}
4002
3990
else {
4003
3991
/* 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 );
4005
3994
start_idx = 1 ;
4006
3995
nargs = 1 ;
4007
3996
}
@@ -4012,8 +4001,8 @@ _find_array_wrap(PyObject *args, PyObject *kwds,
4012
4001
int j = idx_offset + i ;
4013
4002
4014
4003
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 );
4017
4006
}
4018
4007
else {
4019
4008
output_wrap [i ] = wrap ;
0 commit comments