Skip to content

Commit 743084e

Browse files
committed
MAINT: some hacks to fix pypy support
1 parent 420501c commit 743084e

File tree

1 file changed

+60
-25
lines changed
  • numpy/_core/src/multiarray/stringdtype

1 file changed

+60
-25
lines changed

numpy/_core/src/multiarray/stringdtype/dtype.c

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,27 @@ string_discover_descriptor_from_pyobject(PyTypeObject *NPY_UNUSED(cls),
248248
return ret;
249249
}
250250

251+
#ifndef PYPY_VERSION
252+
#define NA_IS_COMPARE(a, b) a == b
253+
#else
254+
static PyObject *py_id = NULL;
255+
256+
static int
257+
eq_compare_pypy_na(PyObject *a, PyObject *b) {
258+
PyObject *a_id = PyObject_CallOneArg(py_id, a);
259+
if (a_id == NULL) {
260+
return -1;
261+
}
262+
PyObject *b_id = PyObject_CallOneArg(py_id, b);
263+
if (b_id == NULL) {
264+
return -1;
265+
}
266+
return PyObject_RichCompareBool(a_id, b_id, Py_EQ);
267+
}
268+
269+
#define NA_IS_COMPARE(a, b) eq_compare_pypy_na(a, b)
270+
#endif
271+
251272
// Take a python object `obj` and insert it into the array of dtype `descr` at
252273
// the position given by dataptr.
253274
int
@@ -260,40 +281,47 @@ stringdtype_setitem(StringDTypeObject *descr, PyObject *obj, char **dataptr)
260281
// borrow reference
261282
PyObject *na_object = descr->na_object;
262283

263-
// setting NA *must* check pointer equality since NA types might not
264-
// allow equality
265-
if (na_object != NULL && obj == na_object) {
266-
if (NpyString_pack_null(allocator, sdata) < 0) {
267-
PyErr_SetString(PyExc_MemoryError,
268-
"Failed to pack null string during StringDType "
269-
"setitem");
284+
if (na_object != NULL) {
285+
// specifically for pandas.NA, we *have* to use "is" comparison
286+
// because there's no other way to identify NA, since "NA == anything"
287+
// returns NA.
288+
int is_cmp = NA_IS_COMPARE(obj, na_object);
289+
if (is_cmp == -1) {
270290
goto fail;
271291
}
292+
if (is_cmp) {
293+
if (NpyString_pack_null(allocator, sdata) < 0) {
294+
PyErr_SetString(PyExc_MemoryError,
295+
"Failed to pack null string during StringDType "
296+
"setitem");
297+
goto fail;
298+
}
299+
goto success;
300+
}
272301
}
273-
else {
274-
PyObject *val_obj = get_value(obj, descr->coerce);
302+
PyObject *val_obj = get_value(obj, descr->coerce);
275303

276-
if (val_obj == NULL) {
277-
goto fail;
278-
}
304+
if (val_obj == NULL) {
305+
goto fail;
306+
}
279307

280-
Py_ssize_t length = 0;
281-
const char *val = PyUnicode_AsUTF8AndSize(val_obj, &length);
282-
if (val == NULL) {
283-
Py_DECREF(val_obj);
284-
goto fail;
285-
}
308+
Py_ssize_t length = 0;
309+
const char *val = PyUnicode_AsUTF8AndSize(val_obj, &length);
310+
if (val == NULL) {
311+
Py_DECREF(val_obj);
312+
goto fail;
313+
}
286314

287-
if (NpyString_pack(allocator, sdata, val, length) < 0) {
288-
PyErr_SetString(PyExc_MemoryError,
289-
"Failed to pack string during StringDType "
290-
"setitem");
291-
Py_DECREF(val_obj);
292-
goto fail;
293-
}
315+
if (NpyString_pack(allocator, sdata, val, length) < 0) {
316+
PyErr_SetString(PyExc_MemoryError,
317+
"Failed to pack string during StringDType "
318+
"setitem");
294319
Py_DECREF(val_obj);
320+
goto fail;
295321
}
322+
Py_DECREF(val_obj);
296323

324+
success:
297325
NpyString_release_allocator(descr);
298326

299327
return 0;
@@ -853,6 +881,13 @@ init_string_dtype(void)
853881
.casts = StringDType_casts,
854882
};
855883

884+
#ifdef PYPY_VERSION
885+
py_id = PyDict_GetItemString(PyEval_GetBuiltins(), "id");
886+
if (py_id == NULL) {
887+
return -1;
888+
}
889+
#endif
890+
856891
/* Loaded dynamically, so may need to be set here: */
857892
((PyObject *)&StringDType)->ob_type = &PyArrayDTypeMeta_Type;
858893
((PyTypeObject *)&StringDType)->tp_base = &PyArrayDescr_Type;

0 commit comments

Comments
 (0)