@@ -116,6 +116,8 @@ raise_errmsg(char *msg, PyObject *s, Py_ssize_t end);
116116static PyObject *
117117encoder_encode_string (PyEncoderObject * s , PyObject * obj );
118118static PyObject *
119+ encoder_encode_long (PyEncoderObject * s UNUSED , PyObject * obj );
120+ static PyObject *
119121encoder_encode_float (PyEncoderObject * s , PyObject * obj );
120122
121123#define S_CHAR (c ) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
@@ -1301,14 +1303,46 @@ _encoded_const(PyObject *obj)
13011303 }
13021304}
13031305
1306+ static PyObject *
1307+ encoder_encode_long (PyEncoderObject * s UNUSED , PyObject * obj )
1308+ {
1309+ /* Return the JSON representation of a PyLong and PyLong subclasses.
1310+ Calls int() on PyLong subclasses in case the str() was changed.
1311+ Added specifically to deal with IntEnum. See Issue18264. */
1312+ PyObject * encoded , * longobj ;
1313+ if (PyLong_CheckExact (obj )) {
1314+ encoded = PyObject_Str (obj );
1315+ }
1316+ else {
1317+ longobj = PyNumber_Long (obj );
1318+ if (longobj == NULL ) {
1319+ PyErr_SetString (
1320+ PyExc_ValueError ,
1321+ "Unable to coerce int subclass to int"
1322+ );
1323+ return NULL ;
1324+ }
1325+ encoded = PyObject_Str (longobj );
1326+ Py_DECREF (longobj );
1327+ }
1328+ return encoded ;
1329+ }
1330+
1331+
13041332static PyObject *
13051333encoder_encode_float (PyEncoderObject * s , PyObject * obj )
13061334{
1307- /* Return the JSON representation of a PyFloat */
1335+ /* Return the JSON representation of a PyFloat.
1336+ Modified to call float() on float subclasses in case the subclass
1337+ changes the repr. See Issue18264. */
1338+ PyObject * encoded , * floatobj ;
13081339 double i = PyFloat_AS_DOUBLE (obj );
13091340 if (!Py_IS_FINITE (i )) {
13101341 if (!s -> allow_nan ) {
1311- PyErr_SetString (PyExc_ValueError , "Out of range float values are not JSON compliant" );
1342+ PyErr_SetString (
1343+ PyExc_ValueError ,
1344+ "Out of range float values are not JSON compliant"
1345+ );
13121346 return NULL ;
13131347 }
13141348 if (i > 0 ) {
@@ -1321,8 +1355,24 @@ encoder_encode_float(PyEncoderObject *s, PyObject *obj)
13211355 return PyUnicode_FromString ("NaN" );
13221356 }
13231357 }
1324- /* Use a better float format here? */
1325- return PyObject_Repr (obj );
1358+ /* coerce float subclasses to float (primarily for Enum) */
1359+ if (PyFloat_CheckExact (obj )) {
1360+ /* Use a better float format here? */
1361+ encoded = PyObject_Repr (obj );
1362+ }
1363+ else {
1364+ floatobj = PyNumber_Float (obj );
1365+ if (floatobj == NULL ) {
1366+ PyErr_SetString (
1367+ PyExc_ValueError ,
1368+ "Unable to coerce float subclass to float"
1369+ );
1370+ return NULL ;
1371+ }
1372+ encoded = PyObject_Repr (floatobj );
1373+ Py_DECREF (floatobj );
1374+ }
1375+ return encoded ;
13261376}
13271377
13281378static PyObject *
@@ -1366,7 +1416,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyAccu *acc,
13661416 return _steal_accumulate (acc , encoded );
13671417 }
13681418 else if (PyLong_Check (obj )) {
1369- PyObject * encoded = PyObject_Str ( obj );
1419+ PyObject * encoded = encoder_encode_long ( s , obj );
13701420 if (encoded == NULL )
13711421 return -1 ;
13721422 return _steal_accumulate (acc , encoded );
@@ -1551,9 +1601,10 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
15511601 goto bail ;
15521602 }
15531603 else if (PyLong_Check (key )) {
1554- kstr = PyObject_Str ( key );
1555- if (kstr == NULL )
1604+ kstr = encoder_encode_long ( s , key );
1605+ if (kstr == NULL ) {
15561606 goto bail ;
1607+ }
15571608 }
15581609 else if (skipkeys ) {
15591610 Py_DECREF (item );
0 commit comments