Skip to content

Commit 8814211

Browse files
authored
Merge pull request numpy#12524 from mattip/pypy-cleanup
BUG: fix improper use of C-API
2 parents f521b20 + ff32c7f commit 8814211

File tree

5 files changed

+46
-21
lines changed

5 files changed

+46
-21
lines changed

numpy/core/src/common/ufunc_override.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,19 @@ PyUFuncOverride_GetOutObjects(PyObject *kwds, PyObject **out_kwd_obj, PyObject *
9393
return 0;
9494
}
9595
if (PyTuple_CheckExact(*out_kwd_obj)) {
96-
*out_objs = PySequence_Fast_ITEMS(*out_kwd_obj);
97-
return PySequence_Fast_GET_SIZE(*out_kwd_obj);
96+
/*
97+
* The C-API recommends calling PySequence_Fast before any of the other
98+
* PySequence_Fast* functions. This is required for PyPy
99+
*/
100+
PyObject *seq = PySequence_Fast(*out_kwd_obj, "Could not convert object to sequence");
101+
int ret;
102+
if (seq == NULL) {
103+
return -1;
104+
}
105+
*out_objs = PySequence_Fast_ITEMS(seq);
106+
ret = PySequence_Fast_GET_SIZE(seq);
107+
Py_SETREF(*out_kwd_obj, seq);
108+
return ret;
98109
}
99110
else {
100111
*out_objs = out_kwd_obj;

numpy/core/src/multiarray/common.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,12 +440,18 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
440440
return 0;
441441
}
442442

443-
/* Recursive case, first check the sequence contains only one type */
443+
/*
444+
* The C-API recommends calling PySequence_Fast before any of the other
445+
* PySequence_Fast* functions. This is required for PyPy
446+
*/
444447
seq = PySequence_Fast(obj, "Could not convert object to sequence");
445448
if (seq == NULL) {
446449
goto fail;
447450
}
451+
452+
/* Recursive case, first check the sequence contains only one type */
448453
size = PySequence_Fast_GET_SIZE(seq);
454+
/* objects is borrowed, do not release seq */
449455
objects = PySequence_Fast_ITEMS(seq);
450456
common_type = size > 0 ? Py_TYPE(objects[0]) : NULL;
451457
for (i = 1; i < size; ++i) {

numpy/core/src/multiarray/methods.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1003,19 +1003,26 @@ any_array_ufunc_overrides(PyObject *args, PyObject *kwds)
10031003
int i;
10041004
int nin, nout;
10051005
PyObject *out_kwd_obj;
1006+
PyObject *fast;
10061007
PyObject **in_objs, **out_objs;
10071008

10081009
/* check inputs */
10091010
nin = PyTuple_Size(args);
10101011
if (nin < 0) {
10111012
return -1;
10121013
}
1013-
in_objs = PySequence_Fast_ITEMS(args);
1014+
fast = PySequence_Fast(args, "Could not convert object to sequence");
1015+
if (fast == NULL) {
1016+
return -1;
1017+
}
1018+
in_objs = PySequence_Fast_ITEMS(fast);
10141019
for (i = 0; i < nin; ++i) {
10151020
if (PyUFunc_HasOverride(in_objs[i])) {
1021+
Py_DECREF(fast);
10161022
return 1;
10171023
}
10181024
}
1025+
Py_DECREF(fast);
10191026
/* check outputs, if any */
10201027
nout = PyUFuncOverride_GetOutObjects(kwds, &out_kwd_obj, &out_objs);
10211028
if (nout < 0) {

numpy/core/src/multiarray/multiarraymodule.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out)
982982
for (i = 0; i < PyArray_NDIM(ap2) - 2; i++) {
983983
dimensions[j++] = PyArray_DIMS(ap2)[i];
984984
}
985-
if(PyArray_NDIM(ap2) > 1) {
985+
if (PyArray_NDIM(ap2) > 1) {
986986
dimensions[j++] = PyArray_DIMS(ap2)[PyArray_NDIM(ap2)-1];
987987
}
988988

@@ -1318,7 +1318,7 @@ PyArray_Correlate2(PyObject *op1, PyObject *op2, int mode)
13181318
*/
13191319
if (inverted) {
13201320
st = _pyarray_revert(ret);
1321-
if(st) {
1321+
if (st) {
13221322
goto clean_ret;
13231323
}
13241324
}
@@ -1365,7 +1365,7 @@ PyArray_Correlate(PyObject *op1, PyObject *op2, int mode)
13651365
}
13661366

13671367
ret = _pyarray_correlate(ap1, ap2, typenum, mode, &unused);
1368-
if(ret == NULL) {
1368+
if (ret == NULL) {
13691369
goto fail;
13701370
}
13711371
Py_DECREF(ap1);
@@ -1654,7 +1654,7 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
16541654
}
16551655

16561656
full_path:
1657-
if(!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&i:array", kwd,
1657+
if (!PyArg_ParseTupleAndKeywords(args, kws, "O|O&O&O&O&i:array", kwd,
16581658
&op,
16591659
PyArray_DescrConverter2, &type,
16601660
PyArray_BoolConverter, &copy,
@@ -2489,7 +2489,7 @@ einsum_sub_op_from_lists(PyObject *args,
24892489
"operand and a subscripts list to einsum");
24902490
return -1;
24912491
}
2492-
else if(nop >= NPY_MAXARGS) {
2492+
else if (nop >= NPY_MAXARGS) {
24932493
PyErr_SetString(PyExc_ValueError, "too many operands");
24942494
return -1;
24952495
}
@@ -2724,7 +2724,7 @@ array_arange(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws) {
27242724
static char *kwd[]= {"start", "stop", "step", "dtype", NULL};
27252725
PyArray_Descr *typecode = NULL;
27262726

2727-
if(!PyArg_ParseTupleAndKeywords(args, kws, "O|OOO&:arange", kwd,
2727+
if (!PyArg_ParseTupleAndKeywords(args, kws, "O|OOO&:arange", kwd,
27282728
&o_start,
27292729
&o_stop,
27302730
&o_step,
@@ -2762,7 +2762,7 @@ array__get_ndarray_c_version(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObje
27622762
{
27632763
static char *kwlist[] = {NULL};
27642764

2765-
if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist )) {
2765+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist )) {
27662766
return NULL;
27672767
}
27682768
return PyInt_FromLong( (long) PyArray_GetNDArrayCVersion() );
@@ -2835,7 +2835,7 @@ array_set_string_function(PyObject *NPY_UNUSED(self), PyObject *args,
28352835
int repr = 1;
28362836
static char *kwlist[] = {"f", "repr", NULL};
28372837

2838-
if(!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:set_string_function", kwlist, &op, &repr)) {
2838+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:set_string_function", kwlist, &op, &repr)) {
28392839
return NULL;
28402840
}
28412841
/* reset the array_repr function to built-in */
@@ -3145,7 +3145,7 @@ array_promote_types(PyObject *NPY_UNUSED(dummy), PyObject *args)
31453145
PyArray_Descr *d1 = NULL;
31463146
PyArray_Descr *d2 = NULL;
31473147
PyObject *ret = NULL;
3148-
if(!PyArg_ParseTuple(args, "O&O&:promote_types",
3148+
if (!PyArg_ParseTuple(args, "O&O&:promote_types",
31493149
PyArray_DescrConverter2, &d1, PyArray_DescrConverter2, &d2)) {
31503150
goto finish;
31513151
}
@@ -3171,7 +3171,7 @@ array_min_scalar_type(PyObject *NPY_UNUSED(dummy), PyObject *args)
31713171
PyArrayObject *array;
31723172
PyObject *ret = NULL;
31733173

3174-
if(!PyArg_ParseTuple(args, "O:min_scalar_type", &array_in)) {
3174+
if (!PyArg_ParseTuple(args, "O:min_scalar_type", &array_in)) {
31753175
return NULL;
31763176
}
31773177

@@ -3248,7 +3248,7 @@ array_datetime_data(PyObject *NPY_UNUSED(dummy), PyObject *args)
32483248
PyArray_Descr *dtype;
32493249
PyArray_DatetimeMetaData *meta;
32503250

3251-
if(!PyArg_ParseTuple(args, "O&:datetime_data",
3251+
if (!PyArg_ParseTuple(args, "O&:datetime_data",
32523252
PyArray_DescrConverter, &dtype)) {
32533253
return NULL;
32543254
}
@@ -3267,7 +3267,7 @@ new_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args)
32673267
{
32683268
int size;
32693269

3270-
if(!PyArg_ParseTuple(args, "i:buffer", &size)) {
3270+
if (!PyArg_ParseTuple(args, "i:buffer", &size)) {
32713271
return NULL;
32723272
}
32733273
return PyBuffer_New(size);
@@ -4570,6 +4570,10 @@ PyMODINIT_FUNC init_multiarray_umath(void) {
45704570
*/
45714571
PyArray_Type.tp_hash = PyObject_HashNotImplemented;
45724572

4573+
if (PyType_Ready(&PyUFunc_Type) < 0) {
4574+
goto err;
4575+
}
4576+
45734577
/* Load the ufunc operators into the array module's namespace */
45744578
if (InitOperators(d) < 0) {
45754579
goto err;
@@ -4580,8 +4584,9 @@ PyMODINIT_FUNC init_multiarray_umath(void) {
45804584
}
45814585
initialize_casting_tables();
45824586
initialize_numeric_types();
4583-
if(initscalarmath(m) < 0)
4587+
if (initscalarmath(m) < 0) {
45844588
goto err;
4589+
}
45854590

45864591
if (PyType_Ready(&PyArray_Type) < 0) {
45874592
goto err;

numpy/core/src/umath/umathmodule.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,6 @@ int initumath(PyObject *m)
268268
UFUNC_FLOATING_POINT_SUPPORT = 0;
269269
#endif
270270

271-
/* Initialize the types */
272-
if (PyType_Ready(&PyUFunc_Type) < 0)
273-
return -1;
274-
275271
/* Add some symbolic constants to the module */
276272
d = PyModule_GetDict(m);
277273

0 commit comments

Comments
 (0)