@@ -1562,6 +1562,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
15621562 PyObject * ident = NULL ;
15631563 PyObject * it = NULL ;
15641564 PyObject * items ;
1565+ PyObject * coerced_items ;
15651566 PyObject * item = NULL ;
15661567 Py_ssize_t idx ;
15671568
@@ -1607,55 +1608,81 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
16071608 items = PyMapping_Items (dct );
16081609 if (items == NULL )
16091610 goto bail ;
1610- if (s -> sort_keys && PyList_Sort (items ) < 0 ) {
1611- Py_DECREF (items );
1611+
1612+ coerced_items = PyList_New (0 );
1613+ it = PyObject_GetIter (items );
1614+ Py_DECREF (items );
1615+ if (it == NULL )
1616+ goto bail ;
1617+
1618+ while ((item = PyIter_Next (it )) != NULL ) {
1619+ PyObject * key , * value , * coerced_item ;
1620+ if (!PyTuple_Check (item ) || PyTuple_GET_SIZE (item ) != 2 ) {
1621+ PyErr_SetString (PyExc_ValueError , "items must return 2-tuples" );
1622+ goto bail ;
1623+ }
1624+ key = PyTuple_GET_ITEM (item , 0 );
1625+ if (PyUnicode_Check (key )) {
1626+ Py_INCREF (key );
1627+ kstr = key ;
1628+ }
1629+ else if (PyFloat_Check (key )) {
1630+ kstr = encoder_encode_float (s , key );
1631+ if (kstr == NULL )
1632+ goto bail ;
1633+ }
1634+ else if (key == Py_True || key == Py_False || key == Py_None ) {
1635+ /* This must come before the PyLong_Check because
1636+ True and False are also 1 and 0.*/
1637+ kstr = _encoded_const (key );
1638+ if (kstr == NULL )
1639+ goto bail ;
1640+ }
1641+ else if (PyLong_Check (key )) {
1642+ kstr = PyLong_Type .tp_str (key );
1643+ if (kstr == NULL ) {
1644+ goto bail ;
1645+ }
1646+ }
1647+ else if (s -> skipkeys ) {
1648+ Py_DECREF (item );
1649+ continue ;
1650+ }
1651+ else {
1652+ PyErr_Format (PyExc_TypeError ,
1653+ "keys must be str, int, float, bool or None, "
1654+ "not %.100s" , key -> ob_type -> tp_name );
1655+ goto bail ;
1656+ }
1657+
1658+ value = PyTuple_GET_ITEM (item , 1 );
1659+ coerced_item = PyTuple_Pack (2 , kstr , value );
1660+ if (coerced_item == NULL ) {
1661+ goto bail ;
1662+ }
1663+ /* Append instead of set because skipkeys=True may
1664+ "shrink" the number of items */
1665+ if (-1 == PyList_Append (coerced_items , coerced_item ))
1666+ goto bail ;
1667+ }
1668+
1669+ if (s -> sort_keys && PyList_Sort (coerced_items ) < 0 ) {
1670+ Py_DECREF (coerced_items );
16121671 goto bail ;
16131672 }
1614- it = PyObject_GetIter (items );
1615- Py_DECREF (items );
1673+ it = PyObject_GetIter (coerced_items );
1674+ Py_DECREF (coerced_items );
16161675 if (it == NULL )
16171676 goto bail ;
16181677 idx = 0 ;
16191678 while ((item = PyIter_Next (it )) != NULL ) {
1620- PyObject * encoded , * key , * value ;
1679+ PyObject * encoded , * value ;
16211680 if (!PyTuple_Check (item ) || PyTuple_GET_SIZE (item ) != 2 ) {
16221681 PyErr_SetString (PyExc_ValueError , "items must return 2-tuples" );
16231682 goto bail ;
16241683 }
1625- key = PyTuple_GET_ITEM (item , 0 );
1626- if (PyUnicode_Check (key )) {
1627- Py_INCREF (key );
1628- kstr = key ;
1629- }
1630- else if (PyFloat_Check (key )) {
1631- kstr = encoder_encode_float (s , key );
1632- if (kstr == NULL )
1633- goto bail ;
1634- }
1635- else if (key == Py_True || key == Py_False || key == Py_None ) {
1636- /* This must come before the PyLong_Check because
1637- True and False are also 1 and 0.*/
1638- kstr = _encoded_const (key );
1639- if (kstr == NULL )
1640- goto bail ;
1641- }
1642- else if (PyLong_Check (key )) {
1643- kstr = PyLong_Type .tp_str (key );
1644- if (kstr == NULL ) {
1645- goto bail ;
1646- }
1647- }
1648- else if (s -> skipkeys ) {
1649- Py_DECREF (item );
1650- continue ;
1651- }
1652- else {
1653- PyErr_Format (PyExc_TypeError ,
1654- "keys must be str, int, float, bool or None, "
1655- "not %.100s" , key -> ob_type -> tp_name );
1656- goto bail ;
1657- }
1658-
1684+ kstr = PyTuple_GET_ITEM (item , 0 );
1685+
16591686 if (idx ) {
16601687 if (_PyAccu_Accumulate (acc , s -> item_separator ))
16611688 goto bail ;
@@ -1703,6 +1730,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
17031730 Py_XDECREF (item );
17041731 Py_XDECREF (kstr );
17051732 Py_XDECREF (ident );
1733+ Py_XDECREF (coerced_items );
17061734 return -1 ;
17071735}
17081736
0 commit comments