| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -244,15 +244,18 @@ def floatstr(o, allow_nan=self.allow_nan, | |||
| 244 | 244 | return text | |
| 245 | 245 | ||
| 246 | 246 | ||
| 247 | - if (_one_shot and c_make_encoder is not None | ||
| 248 | - and self.indent is None): | ||
| 247 | + if self.indent is None or isinstance(self.indent, str): | ||
| 248 | + indent = self.indent | ||
| 249 | + else: | ||
| 250 | + indent = ' ' * self.indent | ||
| 251 | + if _one_shot and c_make_encoder is not None: | ||
| 249 | 252 | _iterencode = c_make_encoder( | |
| 250 | - markers, self.default, _encoder, self.indent, | ||
| 253 | + markers, self.default, _encoder, indent, | ||
| 251 | 254 | self.key_separator, self.item_separator, self.sort_keys, | |
| 252 | 255 | self.skipkeys, self.allow_nan) | |
| 253 | 256 | else: | |
| 254 | 257 | _iterencode = _make_iterencode( | |
| 255 | - markers, self.default, _encoder, self.indent, floatstr, | ||
| 258 | + markers, self.default, _encoder, indent, floatstr, | ||
| 256 | 259 | self.key_separator, self.item_separator, self.sort_keys, | |
| 257 | 260 | self.skipkeys, _one_shot) | |
| 258 | 261 | return _iterencode(o, 0) | |
@@ -272,9 +275,6 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, | |||
| 272 | 275 | _intstr=int.__repr__, | |
| 273 | 276 | ): | |
| 274 | 277 | ||
| 275 | - if _indent is not None and not isinstance(_indent, str): | ||
| 276 | - _indent = ' ' * _indent | ||
| 277 | - | ||
| 278 | 278 | def _iterencode_list(lst, _current_indent_level): | |
| 279 | 279 | if not lst: | |
| 280 | 280 | yield '[]' | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + Improve performance of :func:`json.dumps` and :func:`json.dump` when using the argument *indent*. Depending on the data the encoding using | ||
| 2 | + :func:`json.dumps` with *indent* can be up to 2 to 3 times faster. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -85,11 +85,11 @@ encoder_dealloc(PyObject *self); | |||
| 85 | 85 | static int | |
| 86 | 86 | encoder_clear(PyEncoderObject *self); | |
| 87 | 87 | static int | |
| 88 | - encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *seq, Py_ssize_t indent_level); | ||
| 88 | + encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *seq, PyObject *newline_indent); | ||
| 89 | 89 | static int | |
| 90 | - encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *obj, Py_ssize_t indent_level); | ||
| 90 | + encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *obj, PyObject *newline_indent); | ||
| 91 | 91 | static int | |
| 92 | - encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *dct, Py_ssize_t indent_level); | ||
| 92 | + encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, PyObject *dct, PyObject *newline_indent); | ||
| 93 | 93 | static PyObject * | |
| 94 | 94 | _encoded_const(PyObject *obj); | |
| 95 | 95 | static void | |
@@ -1251,6 +1251,17 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |||
| 1251 | 1251 | return (PyObject *)s; | |
| 1252 | 1252 | } | |
| 1253 | 1253 | ||
| 1254 | + static PyObject * | ||
| 1255 | + _create_newline_indent(PyObject *indent, Py_ssize_t indent_level) | ||
| 1256 | + { | ||
| 1257 | + PyObject *newline_indent = PyUnicode_FromOrdinal('\n'); | ||
| 1258 | + if (newline_indent != NULL && indent_level) { | ||
| 1259 | + PyUnicode_AppendAndDel(&newline_indent, | ||
| 1260 | + PySequence_Repeat(indent, indent_level)); | ||
| 1261 | + } | ||
| 1262 | + return newline_indent; | ||
| 1263 | + } | ||
| 1264 | + | ||
| 1254 | 1265 | static PyObject * | |
| 1255 | 1266 | encoder_call(PyEncoderObject *self, PyObject *args, PyObject *kwds) | |
| 1256 | 1267 | { | |
@@ -1267,10 +1278,20 @@ encoder_call(PyEncoderObject *self, PyObject *args, PyObject *kwds) | |||
| 1267 | 1278 | _PyUnicodeWriter_Init(&writer); | |
| 1268 | 1279 | writer.overallocate = 1; | |
| 1269 | 1280 | ||
| 1270 | - if (encoder_listencode_obj(self, &writer, obj, indent_level)) { | ||
| 1281 | + PyObject *newline_indent = NULL; | ||
| 1282 | + if (self->indent != Py_None) { | ||
| 1283 | + newline_indent = _create_newline_indent(self->indent, indent_level); | ||
| 1284 | + if (newline_indent == NULL) { | ||
| 1285 | + _PyUnicodeWriter_Dealloc(&writer); | ||
| 1286 | + return NULL; | ||
| 1287 | + } | ||
| 1288 | + } | ||
| 1289 | + if (encoder_listencode_obj(self, &writer, obj, newline_indent)) { | ||
| 1271 | 1290 | _PyUnicodeWriter_Dealloc(&writer); | |
| 1291 | + Py_XDECREF(newline_indent); | ||
| 1272 | 1292 | return NULL; | |
| 1273 | 1293 | } | |
| 1294 | + Py_XDECREF(newline_indent); | ||
| 1274 | 1295 | ||
| 1275 | 1296 | result = PyTuple_New(1); | |
| 1276 | 1297 | if (result == NULL || | |
@@ -1358,7 +1379,7 @@ _steal_accumulate(_PyUnicodeWriter *writer, PyObject *stolen) | |||
| 1358 | 1379 | ||
| 1359 | 1380 | static int | |
| 1360 | 1381 | encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, | |
| 1361 | - PyObject *obj, Py_ssize_t indent_level) | ||
| 1382 | + PyObject *obj, PyObject *newline_indent) | ||
| 1362 | 1383 | { | |
| 1363 | 1384 | /* Encode Python object obj to a JSON term */ | |
| 1364 | 1385 | PyObject *newobj; | |
@@ -1394,14 +1415,14 @@ encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1394 | 1415 | else if (PyList_Check(obj) || PyTuple_Check(obj)) { | |
| 1395 | 1416 | if (_Py_EnterRecursiveCall(" while encoding a JSON object")) | |
| 1396 | 1417 | return -1; | |
| 1397 | - rv = encoder_listencode_list(s, writer, obj, indent_level); | ||
| 1418 | + rv = encoder_listencode_list(s, writer, obj, newline_indent); | ||
| 1398 | 1419 | _Py_LeaveRecursiveCall(); | |
| 1399 | 1420 | return rv; | |
| 1400 | 1421 | } | |
| 1401 | 1422 | else if (PyDict_Check(obj)) { | |
| 1402 | 1423 | if (_Py_EnterRecursiveCall(" while encoding a JSON object")) | |
| 1403 | 1424 | return -1; | |
| 1404 | - rv = encoder_listencode_dict(s, writer, obj, indent_level); | ||
| 1425 | + rv = encoder_listencode_dict(s, writer, obj, newline_indent); | ||
| 1405 | 1426 | _Py_LeaveRecursiveCall(); | |
| 1406 | 1427 | return rv; | |
| 1407 | 1428 | } | |
@@ -1435,7 +1456,7 @@ encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1435 | 1456 | Py_XDECREF(ident); | |
| 1436 | 1457 | return -1; | |
| 1437 | 1458 | } | |
| 1438 | - rv = encoder_listencode_obj(s, writer, newobj, indent_level); | ||
| 1459 | + rv = encoder_listencode_obj(s, writer, newobj, newline_indent); | ||
| 1439 | 1460 | _Py_LeaveRecursiveCall(); | |
| 1440 | 1461 | ||
| 1441 | 1462 | Py_DECREF(newobj); | |
@@ -1456,7 +1477,9 @@ encoder_listencode_obj(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1456 | 1477 | ||
| 1457 | 1478 | static int | |
| 1458 | 1479 | encoder_encode_key_value(PyEncoderObject *s, _PyUnicodeWriter *writer, bool *first, | |
| 1459 | - PyObject *key, PyObject *value, Py_ssize_t indent_level) | ||
| 1480 | + PyObject *key, PyObject *value, | ||
| 1481 | + PyObject *newline_indent, | ||
| 1482 | + PyObject *item_separator) | ||
| 1460 | 1483 | { | |
| 1461 | 1484 | PyObject *keystr = NULL; | |
| 1462 | 1485 | PyObject *encoded; | |
@@ -1493,7 +1516,7 @@ encoder_encode_key_value(PyEncoderObject *s, _PyUnicodeWriter *writer, bool *fir | |||
| 1493 | 1516 | *first = false; | |
| 1494 | 1517 | } | |
| 1495 | 1518 | else { | |
| 1496 | - if (_PyUnicodeWriter_WriteStr(writer, s->item_separator) < 0) { | ||
| 1519 | + if (_PyUnicodeWriter_WriteStr(writer, item_separator) < 0) { | ||
| 1497 | 1520 | Py_DECREF(keystr); | |
| 1498 | 1521 | return -1; | |
| 1499 | 1522 | } | |
@@ -1511,21 +1534,23 @@ encoder_encode_key_value(PyEncoderObject *s, _PyUnicodeWriter *writer, bool *fir | |||
| 1511 | 1534 | if (_PyUnicodeWriter_WriteStr(writer, s->key_separator) < 0) { | |
| 1512 | 1535 | return -1; | |
| 1513 | 1536 | } | |
| 1514 | - if (encoder_listencode_obj(s, writer, value, indent_level) < 0) { | ||
| 1537 | + if (encoder_listencode_obj(s, writer, value, newline_indent) < 0) { | ||
| 1515 | 1538 | return -1; | |
| 1516 | 1539 | } | |
| 1517 | 1540 | return 0; | |
| 1518 | 1541 | } | |
| 1519 | 1542 | ||
| 1520 | 1543 | static int | |
| 1521 | 1544 | encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, | |
| 1522 | - PyObject *dct, Py_ssize_t indent_level) | ||
| 1545 | + PyObject *dct, PyObject *newline_indent) | ||
| 1523 | 1546 | { | |
| 1524 | 1547 | /* Encode Python dict dct a JSON term */ | |
| 1525 | 1548 | PyObject *ident = NULL; | |
| 1526 | 1549 | PyObject *items = NULL; | |
| 1527 | 1550 | PyObject *key, *value; | |
| 1528 | 1551 | bool first = true; | |
| 1552 | + PyObject *new_newline_indent = NULL; | ||
| 1553 | + PyObject *separator_indent = NULL; | ||
| 1529 | 1554 | ||
| 1530 | 1555 | if (PyDict_GET_SIZE(dct) == 0) /* Fast path */ | |
| 1531 | 1556 | return _PyUnicodeWriter_WriteASCIIString(writer, "{}", 2); | |
@@ -1549,14 +1574,21 @@ encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1549 | 1574 | if (_PyUnicodeWriter_WriteChar(writer, '{')) | |
| 1550 | 1575 | goto bail; | |
| 1551 | 1576 | ||
| 1577 | + PyObject *current_item_separator = s->item_separator; // borrowed reference | ||
| 1552 | 1578 | if (s->indent != Py_None) { | |
| 1553 | - /* TODO: DOES NOT RUN */ | ||
| 1554 | - indent_level += 1; | ||
| 1555 | - /* | ||
| 1556 | - newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) | ||
| 1557 | - separator = _item_separator + newline_indent | ||
| 1558 | - buf += newline_indent | ||
| 1559 | - */ | ||
| 1579 | + new_newline_indent = PyUnicode_Concat(newline_indent, s->indent); | ||
| 1580 | + if (new_newline_indent == NULL) { | ||
| 1581 | + goto bail; | ||
| 1582 | + } | ||
| 1583 | + separator_indent = PyUnicode_Concat(current_item_separator, new_newline_indent); | ||
| 1584 | + if (separator_indent == NULL) { | ||
| 1585 | + goto bail; | ||
| 1586 | + } | ||
| 1587 | + // update item separator with a borrowed reference | ||
| 1588 | + current_item_separator = separator_indent; | ||
| 1589 | + if (_PyUnicodeWriter_WriteStr(writer, new_newline_indent) < 0) { | ||
| 1590 | + goto bail; | ||
| 1591 | + } | ||
| 1560 | 1592 | } | |
| 1561 | 1593 | ||
| 1562 | 1594 | if (s->sort_keys || !PyDict_CheckExact(dct)) { | |
@@ -1574,15 +1606,19 @@ encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1574 | 1606 | ||
| 1575 | 1607 | key = PyTuple_GET_ITEM(item, 0); | |
| 1576 | 1608 | value = PyTuple_GET_ITEM(item, 1); | |
| 1577 | - if (encoder_encode_key_value(s, writer, &first, key, value, indent_level) < 0) | ||
| 1609 | + if (encoder_encode_key_value(s, writer, &first, key, value, | ||
| 1610 | + new_newline_indent, | ||
| 1611 | + current_item_separator) < 0) | ||
| 1578 | 1612 | goto bail; | |
| 1579 | 1613 | } | |
| 1580 | 1614 | Py_CLEAR(items); | |
| 1581 | 1615 | ||
| 1582 | 1616 | } else { | |
| 1583 | 1617 | Py_ssize_t pos = 0; | |
| 1584 | 1618 | while (PyDict_Next(dct, &pos, &key, &value)) { | |
| 1585 | - if (encoder_encode_key_value(s, writer, &first, key, value, indent_level) < 0) | ||
| 1619 | + if (encoder_encode_key_value(s, writer, &first, key, value, | ||
| 1620 | + new_newline_indent, | ||
| 1621 | + current_item_separator) < 0) | ||
| 1586 | 1622 | goto bail; | |
| 1587 | 1623 | } | |
| 1588 | 1624 | } | |
@@ -1592,29 +1628,36 @@ encoder_listencode_dict(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1592 | 1628 | goto bail; | |
| 1593 | 1629 | Py_CLEAR(ident); | |
| 1594 | 1630 | } | |
| 1595 | - /* TODO DOES NOT RUN; dead code | ||
| 1596 | 1631 | if (s->indent != Py_None) { | |
| 1597 | - indent_level -= 1; | ||
| 1632 | + Py_CLEAR(new_newline_indent); | ||
| 1633 | + Py_CLEAR(separator_indent); | ||
| 1634 | + | ||
| 1635 | + if (_PyUnicodeWriter_WriteStr(writer, newline_indent) < 0) { | ||
| 1636 | + goto bail; | ||
| 1637 | + } | ||
| 1638 | + } | ||
| 1598 | 1639 | ||
| 1599 | - yield '\n' + (' ' * (_indent * _current_indent_level)) | ||
| 1600 | - }*/ | ||
| 1601 | 1640 | if (_PyUnicodeWriter_WriteChar(writer, '}')) | |
| 1602 | 1641 | goto bail; | |
| 1603 | 1642 | return 0; | |
| 1604 | 1643 | ||
| 1605 | 1644 | bail: | |
| 1606 | 1645 | Py_XDECREF(items); | |
| 1607 | 1646 | Py_XDECREF(ident); | |
| 1647 | + Py_XDECREF(separator_indent); | ||
| 1648 | + Py_XDECREF(new_newline_indent); | ||
| 1608 | 1649 | return -1; | |
| 1609 | 1650 | } | |
| 1610 | 1651 | ||
| 1611 | 1652 | static int | |
| 1612 | 1653 | encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, | |
| 1613 | - PyObject *seq, Py_ssize_t indent_level) | ||
| 1654 | + PyObject *seq, PyObject *newline_indent) | ||
| 1614 | 1655 | { | |
| 1615 | 1656 | PyObject *ident = NULL; | |
| 1616 | 1657 | PyObject *s_fast = NULL; | |
| 1617 | 1658 | Py_ssize_t i; | |
| 1659 | + PyObject *new_newline_indent = NULL; | ||
| 1660 | + PyObject *separator_indent = NULL; | ||
| 1618 | 1661 | ||
| 1619 | 1662 | ident = NULL; | |
| 1620 | 1663 | s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); | |
@@ -1643,22 +1686,31 @@ encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1643 | 1686 | ||
| 1644 | 1687 | if (_PyUnicodeWriter_WriteChar(writer, '[')) | |
| 1645 | 1688 | goto bail; | |
| 1689 | + | ||
| 1690 | + PyObject *separator = s->item_separator; // borrowed reference | ||
| 1646 | 1691 | if (s->indent != Py_None) { | |
| 1647 | - /* TODO: DOES NOT RUN */ | ||
| 1648 | - indent_level += 1; | ||
| 1649 | - /* | ||
| 1650 | - newline_indent = '\n' + (' ' * (_indent * _current_indent_level)) | ||
| 1651 | - separator = _item_separator + newline_indent | ||
| 1652 | - buf += newline_indent | ||
| 1653 | - */ | ||
| 1692 | + new_newline_indent = PyUnicode_Concat(newline_indent, s->indent); | ||
| 1693 | + if (new_newline_indent == NULL) { | ||
| 1694 | + goto bail; | ||
| 1695 | + } | ||
| 1696 | + | ||
| 1697 | + if (_PyUnicodeWriter_WriteStr(writer, new_newline_indent) < 0) { | ||
| 1698 | + goto bail; | ||
| 1699 | + } | ||
| 1700 | + | ||
| 1701 | + separator_indent = PyUnicode_Concat(separator, new_newline_indent); | ||
| 1702 | + if (separator_indent == NULL) { | ||
| 1703 | + goto bail; | ||
| 1704 | + } | ||
| 1705 | + separator = separator_indent; // assign separator with borrowed reference | ||
| 1654 | 1706 | } | |
| 1655 | 1707 | for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { | |
| 1656 | 1708 | PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); | |
| 1657 | 1709 | if (i) { | |
| 1658 | - if (_PyUnicodeWriter_WriteStr(writer, s->item_separator)) | ||
| 1710 | + if (_PyUnicodeWriter_WriteStr(writer, separator) < 0) | ||
| 1659 | 1711 | goto bail; | |
| 1660 | 1712 | } | |
| 1661 | - if (encoder_listencode_obj(s, writer, obj, indent_level)) | ||
| 1713 | + if (encoder_listencode_obj(s, writer, obj, new_newline_indent)) | ||
| 1662 | 1714 | goto bail; | |
| 1663 | 1715 | } | |
| 1664 | 1716 | if (ident != NULL) { | |
@@ -1667,12 +1719,14 @@ encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1667 | 1719 | Py_CLEAR(ident); | |
| 1668 | 1720 | } | |
| 1669 | 1721 | ||
| 1670 | - /* TODO: DOES NOT RUN | ||
| 1671 | 1722 | if (s->indent != Py_None) { | |
| 1672 | - indent_level -= 1; | ||
| 1723 | + Py_CLEAR(new_newline_indent); | ||
| 1724 | + Py_CLEAR(separator_indent); | ||
| 1725 | + if (_PyUnicodeWriter_WriteStr(writer, newline_indent) < 0) { | ||
| 1726 | + goto bail; | ||
| 1727 | + } | ||
| 1728 | + } | ||
| 1673 | 1729 | ||
| 1674 | - yield '\n' + (' ' * (_indent * _current_indent_level)) | ||
| 1675 | - }*/ | ||
| 1676 | 1730 | if (_PyUnicodeWriter_WriteChar(writer, ']')) | |
| 1677 | 1731 | goto bail; | |
| 1678 | 1732 | Py_DECREF(s_fast); | |
@@ -1681,6 +1735,8 @@ encoder_listencode_list(PyEncoderObject *s, _PyUnicodeWriter *writer, | |||
| 1681 | 1735 | bail: | |
| 1682 | 1736 | Py_XDECREF(ident); | |
| 1683 | 1737 | Py_DECREF(s_fast); | |
| 1738 | + Py_XDECREF(separator_indent); | ||
| 1739 | + Py_XDECREF(new_newline_indent); | ||
| 1684 | 1740 | return -1; | |
| 1685 | 1741 | } | |
| 1686 | 1742 | ||
@@ -1721,7 +1777,7 @@ encoder_clear(PyEncoderObject *self) | |||
| 1721 | 1777 | return 0; | |
| 1722 | 1778 | } | |
| 1723 | 1779 | ||
| 1724 | - PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable"); | ||
| 1780 | + PyDoc_STRVAR(encoder_doc, "Encoder(markers, default, encoder, indent, key_separator, item_separator, sort_keys, skipkeys, allow_nan)"); | ||
| 1725 | 1781 | ||
| 1726 | 1782 | static PyType_Slot PyEncoderType_slots[] = { | |
| 1727 | 1783 | {Py_tp_doc, (void *)encoder_doc}, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments