Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions pandas/_libs/src/vendored/ujson/python/objToJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -1280,13 +1280,10 @@ char **NpyArr_encodeLabels(PyArrayObject *labels, PyObjectEncoder *enc,
NPY_DATETIMEUNIT dateUnit = NPY_FR_ns;
if (PyTypeNum_ISDATETIME(type_num)) {
is_datetimelike = 1;
PyArray_VectorUnaryFunc *castfunc =
PyArray_GetCastFunc(PyArray_DescrFromType(type_num), NPY_INT64);
if (!castfunc) {
PyErr_Format(PyExc_ValueError, "Cannot cast numpy dtype %d to long",
enc->npyType);
}
castfunc(dataptr, &i8date, 1, NULL, NULL);
PyObject *scalarItem = PyArray_ToScalar(dataptr, labels);
PyArray_CastScalarToCtype(scalarItem, &i8date,
PyArray_DescrFromType(NPY_INT64));
Py_DECREF(scalarItem);
Copy link
Contributor

@seberg seberg Nov 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, you can just use:

memcpy(&i8date, dataptr, sizeof(i8data));

I think, since you know this is an int64, as datetimes are int64 (I am unsure about alignment, thus the memcpy).

Same below? (at last I would think so?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, this is even easier, thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I just realized the cast function doesn't handle alignment, so even i8data = *(npy_int64 *)dataptr; should work.

dateUnit = get_datetime_metadata_from_dtype(dtype).base;
} else if (PyDate_Check(item) || PyDelta_Check(item)) {
is_datetimelike = 1;
Expand Down Expand Up @@ -1432,6 +1429,13 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
enc->npyType);
}
castfunc(enc->npyValue, &longVal, 1, NULL, NULL);

PyObject *scalar =
PyArray_ToScalar(enc->npyValue, enc->npyCtxtPassthru->array);
PyArray_Scalar(enc->npyValue, PyArray_DescrFromType(enc->npyType), NULL);
PyArray_CastScalarToCtype(scalar, &longVal,
PyArray_DescrFromType(NPY_INT64));
Py_DECREF(scalar);
if (longVal == get_nat()) {
tc->type = JT_NULL;
} else {
Expand Down Expand Up @@ -1532,7 +1536,6 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {

PyArray_Descr *outcode = PyArray_DescrFromType(NPY_INT64);
PyArray_CastScalarToCtype(obj, &longVal, outcode);
Py_DECREF(outcode);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just confirming this was also an intentional cleanup?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is an accident and shouldn't be included.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the catch.

I wonder if we're leaking references to PyArray_Descr elsewhere than.

The numpy docs don't seem too clear about whether we're borrowing references or owning it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah the deleted code here used to leak them... One point is that array creation functions steal them, though.


if (enc->datetimeIso) {
GET_TC(tc)->longValue = longVal;
Expand Down