Skip to content

Commit 4d9de8d

Browse files
WillAydjreback
authored andcommitted
ujson Py2 compat removal (#26199)
1 parent b62e9ae commit 4d9de8d

File tree

5 files changed

+48
-126
lines changed

5 files changed

+48
-126
lines changed

pandas/_libs/src/ujson/python/JSONtoObj.c

+9-11
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,12 @@ Numeric decoder derived from from TCL library
3535
* Copyright (c) 1994 Sun Microsystems, Inc.
3636
*/
3737

38-
// "py_defines.h" needs to be included first to
39-
// avoid compilation errors, but it does violate
40-
// styleguide checks with regards to include order.
41-
#include "py_defines.h"
4238
#define PY_ARRAY_UNIQUE_SYMBOL UJSON_NUMPY
4339
#define NO_IMPORT_ARRAY
44-
#include <numpy/arrayobject.h> // NOLINT(build/include_order)
45-
#include <ultrajson.h> // NOLINT(build/include_order)
40+
#define PY_SSIZE_T_CLEAN
41+
#include <Python.h>
42+
#include <numpy/arrayobject.h>
43+
#include <ultrajson.h>
4644

4745
#define PRINTMARK()
4846

@@ -470,7 +468,7 @@ JSOBJ Object_newArray(void *prv, void *decoder) { return PyList_New(0); }
470468
JSOBJ Object_endArray(void *prv, JSOBJ obj) { return obj; }
471469

472470
JSOBJ Object_newInteger(void *prv, JSINT32 value) {
473-
return PyInt_FromLong((long)value);
471+
return PyLong_FromLong((long)value);
474472
}
475473

476474
JSOBJ Object_newLong(void *prv, JSINT64 value) {
@@ -530,7 +528,7 @@ PyObject *JSONToObj(PyObject *self, PyObject *args, PyObject *kwargs) {
530528
decoder->preciseFloat = 1;
531529
}
532530

533-
if (PyString_Check(arg)) {
531+
if (PyBytes_Check(arg)) {
534532
sarg = arg;
535533
} else if (PyUnicode_Check(arg)) {
536534
sarg = PyUnicode_AsUTF8String(arg);
@@ -539,7 +537,7 @@ PyObject *JSONToObj(PyObject *self, PyObject *args, PyObject *kwargs) {
539537
return NULL;
540538
}
541539
} else {
542-
PyErr_Format(PyExc_TypeError, "Expected String or Unicode");
540+
PyErr_Format(PyExc_TypeError, "Expected 'str' or 'bytes'");
543541
return NULL;
544542
}
545543

@@ -559,8 +557,8 @@ PyObject *JSONToObj(PyObject *self, PyObject *args, PyObject *kwargs) {
559557
}
560558
}
561559

562-
ret = JSON_DecodeObject(decoder, PyString_AS_STRING(sarg),
563-
PyString_GET_SIZE(sarg));
560+
ret = JSON_DecodeObject(decoder, PyBytes_AS_STRING(sarg),
561+
PyBytes_GET_SIZE(sarg));
564562

565563
if (sarg != arg) {
566564
Py_DECREF(sarg);

pandas/_libs/src/ujson/python/objToJSON.c

+31-43
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,16 @@ Numeric decoder derived from from TCL library
3636
*/
3737
#define PY_ARRAY_UNIQUE_SYMBOL UJSON_NUMPY
3838

39-
// "py_defines.h" needs to be included first to
40-
// avoid compilation errors, but it does violate
41-
// styleguide checks with regards to include order.
42-
#include "py_defines.h" // NOLINT(build/include_order)
43-
#include <math.h> // NOLINT(build/include_order)
44-
#include <numpy/arrayobject.h> // NOLINT(build/include_order)
45-
#include <numpy/arrayscalars.h> // NOLINT(build/include_order)
46-
#include <numpy/ndarraytypes.h> // NOLINT(build/include_order)
47-
#include <numpy/npy_math.h> // NOLINT(build/include_order)
48-
#include <stdio.h> // NOLINT(build/include_order)
49-
#include <ultrajson.h> // NOLINT(build/include_order)
50-
#include <../../../tslibs/src/datetime/np_datetime.h> // NOLINT(build/include_order)
51-
#include <../../../tslibs/src/datetime/np_datetime_strings.h> // NOLINT(build/include_order)
39+
#define PY_SSIZE_T_CLEAN
40+
#include <Python.h>
41+
#include <math.h>
42+
#include <numpy/arrayobject.h>
43+
#include <numpy/arrayscalars.h>
44+
#include <numpy/ndarraytypes.h>
45+
#include <numpy/npy_math.h>
46+
#include <ultrajson.h>
47+
#include <../../../tslibs/src/datetime/np_datetime.h>
48+
#include <../../../tslibs/src/datetime/np_datetime_strings.h>
5249
#include "datetime.h"
5350

5451
static PyObject *type_decimal;
@@ -281,7 +278,7 @@ static PyObject *get_values(PyObject *obj) {
281278
repr = PyObject_Repr(dtype);
282279
Py_DECREF(dtype);
283280
} else {
284-
repr = PyString_FromString("<unknown dtype>");
281+
repr = PyUnicode_FromString("<unknown dtype>");
285282
}
286283

287284
PyErr_Format(PyExc_ValueError, "%R or %R are not JSON serializable yet",
@@ -341,7 +338,7 @@ static npy_int64 get_long_attr(PyObject *o, const char *attr) {
341338
npy_int64 long_val;
342339
PyObject *value = PyObject_GetAttrString(o, attr);
343340
long_val = (PyLong_Check(value) ?
344-
PyLong_AsLongLong(value) : PyInt_AS_LONG(value));
341+
PyLong_AsLongLong(value) : PyLong_AsLong(value));
345342
Py_DECREF(value);
346343
return long_val;
347344
}
@@ -355,7 +352,7 @@ static npy_float64 total_seconds(PyObject *td) {
355352
}
356353

357354
static PyObject *get_item(PyObject *obj, Py_ssize_t i) {
358-
PyObject *tmp = PyInt_FromSsize_t(i);
355+
PyObject *tmp = PyLong_FromSsize_t(i);
359356
PyObject *ret;
360357

361358
if (tmp == 0) {
@@ -385,14 +382,14 @@ static void *CLong(JSOBJ obj, JSONTypeContext *tc, void *outValue,
385382
static void *PyIntToINT64(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
386383
size_t *_outLen) {
387384
PyObject *obj = (PyObject *)_obj;
388-
*((JSINT64 *)outValue) = PyInt_AS_LONG(obj);
385+
*((JSINT64 *)outValue) = PyLong_AsLong(obj);
389386
return NULL;
390387
}
391388
#else
392389
static void *PyIntToINT32(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
393390
size_t *_outLen) {
394391
PyObject *obj = (PyObject *)_obj;
395-
*((JSINT32 *)outValue) = PyInt_AS_LONG(obj);
392+
*((JSINT32 *)outValue) = PyLong_AsLong(obj);
396393
return NULL;
397394
}
398395
#endif
@@ -420,8 +417,8 @@ static void *PyFloatToDOUBLE(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
420417
static void *PyStringToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
421418
size_t *_outLen) {
422419
PyObject *obj = (PyObject *)_obj;
423-
*_outLen = PyString_GET_SIZE(obj);
424-
return PyString_AS_STRING(obj);
420+
*_outLen = PyBytes_GET_SIZE(obj);
421+
return PyBytes_AS_STRING(obj);
425422
}
426423

427424
static void *PyUnicodeToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
@@ -442,8 +439,8 @@ static void *PyUnicodeToUTF8(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
442439

443440
GET_TC(tc)->newObj = newObj;
444441

445-
*_outLen = PyString_GET_SIZE(newObj);
446-
return PyString_AS_STRING(newObj);
442+
*_outLen = PyBytes_GET_SIZE(newObj);
443+
return PyBytes_AS_STRING(newObj);
447444
}
448445

449446
static void *PandasDateTimeStructToJSON(npy_datetimestruct *dts,
@@ -546,8 +543,8 @@ static void *PyTimeToJSON(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
546543

547544
GET_TC(tc)->newObj = str;
548545

549-
*outLen = PyString_GET_SIZE(str);
550-
outValue = (void *)PyString_AS_STRING(str);
546+
*outLen = PyBytes_GET_SIZE(str);
547+
outValue = (void *)PyBytes_AS_STRING(str);
551548
return outValue;
552549
}
553550

@@ -1248,13 +1245,8 @@ int Dir_iterNext(JSOBJ _obj, JSONTypeContext *tc) {
12481245

12491246
for (; GET_TC(tc)->index < GET_TC(tc)->size; GET_TC(tc)->index++) {
12501247
attrName = PyList_GET_ITEM(GET_TC(tc)->attrList, GET_TC(tc)->index);
1251-
#if PY_MAJOR_VERSION >= 3
12521248
attr = PyUnicode_AsUTF8String(attrName);
1253-
#else
1254-
attr = attrName;
1255-
Py_INCREF(attr);
1256-
#endif
1257-
attrStr = PyString_AS_STRING(attr);
1249+
attrStr = PyBytes_AS_STRING(attr);
12581250

12591251
if (attrStr[0] == '_') {
12601252
PRINTMARK();
@@ -1307,8 +1299,8 @@ JSOBJ Dir_iterGetValue(JSOBJ obj, JSONTypeContext *tc) {
13071299

13081300
char *Dir_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) {
13091301
PRINTMARK();
1310-
*outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
1311-
return PyString_AS_STRING(GET_TC(tc)->itemName);
1302+
*outLen = PyBytes_GET_SIZE(GET_TC(tc)->itemName);
1303+
return PyBytes_AS_STRING(GET_TC(tc)->itemName);
13121304
}
13131305

13141306
//=============================================================================
@@ -1525,9 +1517,7 @@ void Dict_iterBegin(JSOBJ obj, JSONTypeContext *tc) {
15251517
}
15261518

15271519
int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc) {
1528-
#if PY_MAJOR_VERSION >= 3
15291520
PyObject *itemNameTmp;
1530-
#endif
15311521

15321522
if (GET_TC(tc)->itemName) {
15331523
Py_DECREF(GET_TC(tc)->itemName);
@@ -1542,13 +1532,11 @@ int Dict_iterNext(JSOBJ obj, JSONTypeContext *tc) {
15421532

15431533
if (PyUnicode_Check(GET_TC(tc)->itemName)) {
15441534
GET_TC(tc)->itemName = PyUnicode_AsUTF8String(GET_TC(tc)->itemName);
1545-
} else if (!PyString_Check(GET_TC(tc)->itemName)) {
1535+
} else if (!PyBytes_Check(GET_TC(tc)->itemName)) {
15461536
GET_TC(tc)->itemName = PyObject_Str(GET_TC(tc)->itemName);
1547-
#if PY_MAJOR_VERSION >= 3
15481537
itemNameTmp = GET_TC(tc)->itemName;
15491538
GET_TC(tc)->itemName = PyUnicode_AsUTF8String(GET_TC(tc)->itemName);
15501539
Py_DECREF(itemNameTmp);
1551-
#endif
15521540
} else {
15531541
Py_INCREF(GET_TC(tc)->itemName);
15541542
}
@@ -1570,8 +1558,8 @@ JSOBJ Dict_iterGetValue(JSOBJ obj, JSONTypeContext *tc) {
15701558
}
15711559

15721560
char *Dict_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen) {
1573-
*outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
1574-
return PyString_AS_STRING(GET_TC(tc)->itemName);
1561+
*outLen = PyBytes_GET_SIZE(GET_TC(tc)->itemName);
1562+
return PyBytes_AS_STRING(GET_TC(tc)->itemName);
15751563
}
15761564

15771565
void NpyArr_freeLabels(char **labels, npy_intp len) {
@@ -1788,7 +1776,7 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
17881776
}
17891777

17901778
return;
1791-
} else if (PyInt_Check(obj)) {
1779+
} else if (PyLong_Check(obj)) {
17921780
PRINTMARK();
17931781

17941782
#ifdef _LP64
@@ -1809,7 +1797,7 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
18091797
tc->type = JT_DOUBLE;
18101798
}
18111799
return;
1812-
} else if (PyString_Check(obj)) {
1800+
} else if (PyBytes_Check(obj)) {
18131801
PRINTMARK();
18141802
pc->PyTypeToJSON = PyStringToUTF8;
18151803
tc->type = JT_UTF8;
@@ -1932,7 +1920,7 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
19321920
tmpObj = PyObject_Repr(obj);
19331921
PyErr_Format(PyExc_TypeError,
19341922
"%s (0d array) is not JSON serializable at the moment",
1935-
PyString_AS_STRING(tmpObj));
1923+
PyBytes_AS_STRING(tmpObj));
19361924
Py_DECREF(tmpObj);
19371925
goto INVALID;
19381926
}
@@ -2469,7 +2457,7 @@ PyObject *objToJSON(PyObject *self, PyObject *args, PyObject *kwargs) {
24692457
return NULL;
24702458
}
24712459

2472-
newobj = PyString_FromString(ret);
2460+
newobj = PyUnicode_FromString(ret);
24732461

24742462
if (ret != buffer) {
24752463
encoder->free(ret);

pandas/_libs/src/ujson/python/py_defines.h

-58
This file was deleted.

pandas/_libs/src/ujson/python/ujson.c

+3-14
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ Numeric decoder derived from from TCL library
3535
* Copyright (c) 1994 Sun Microsystems, Inc.
3636
*/
3737

38-
#include "py_defines.h"
3938
#include "version.h"
39+
#define PY_SSIZE_T_CLEAN
40+
#include <Python.h>
4041

4142
/* objToJSON */
4243
PyObject *objToJSON(PyObject *self, PyObject *args, PyObject *kwargs);
@@ -76,8 +77,6 @@ static PyMethodDef ujsonMethods[] = {
7677
{NULL, NULL, 0, NULL} /* Sentinel */
7778
};
7879

79-
#if PY_MAJOR_VERSION >= 3
80-
8180
static struct PyModuleDef moduledef = {
8281
PyModuleDef_HEAD_INIT,
8382
"_libjson",
@@ -94,14 +93,6 @@ static struct PyModuleDef moduledef = {
9493
#define PYMODULE_CREATE() PyModule_Create(&moduledef)
9594
#define MODINITERROR return NULL
9695

97-
#else
98-
99-
#define PYMODINITFUNC PyMODINIT_FUNC initjson(void)
100-
#define PYMODULE_CREATE() Py_InitModule("json", ujsonMethods)
101-
#define MODINITERROR return
102-
103-
#endif
104-
10596
PYMODINITFUNC {
10697
PyObject *module;
10798
PyObject *version_string;
@@ -113,10 +104,8 @@ PYMODINITFUNC {
113104
MODINITERROR;
114105
}
115106

116-
version_string = PyString_FromString(UJSON_VERSION);
107+
version_string = PyUnicode_FromString(UJSON_VERSION);
117108
PyModule_AddObject(module, "__version__", version_string);
118109

119-
#if PY_MAJOR_VERSION >= 3
120110
return module;
121-
#endif
122111
}

pandas/tests/io/json/test_ujson.py

+5
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,11 @@ def test_load_file_args_error(self):
618618
with pytest.raises(TypeError):
619619
ujson.load("[]")
620620

621+
def test_loads_non_str_bytes_raises(self):
622+
msg = "Expected 'str' or 'bytes'"
623+
with pytest.raises(TypeError, match=msg):
624+
ujson.loads(None)
625+
621626
def test_version(self):
622627
assert re.match(r'^\d+\.\d+(\.\d+)?$', ujson.__version__), \
623628
"ujson.__version__ must be a string like '1.4.0'"

0 commit comments

Comments
 (0)