19113N/A# HG changeset patch
19113N/A# User Antoine Pitrou <solipsis@pitrou.net>
19113N/A# Date 1288889688 -3600
19113N/A# Branch trunk
19113N/A# Node ID ac61b03c19573cf0ebc27859ec48eddd276a7219
19113N/A# Parent 2cbf5e82b45ed5b95b2075c6bd7fe813bb306974
19113N/ASupport the sort_keys option in C encoding speedups.
19113N/AIt is a backport of CPython 3.x from SVN r72963, r72964, r86169.
19113N/A
19113N/Adiff -r 2cbf5e82b45e -r ac61b03c1957 simplejson/_speedups.c
19113N/A--- a/simplejson/_speedups.c Mon Nov 01 10:35:26 2010 +0100
19113N/A+++ b/simplejson/_speedups.c Thu Nov 04 17:54:48 2010 +0100
19113N/A@@ -2185,9 +2185,9 @@
19113N/A static PyObject *iteritems = NULL;
19113N/A PyObject *kstr = NULL;
19113N/A PyObject *ident = NULL;
19113N/A- PyObject *key, *value;
19113N/A PyObject *iter = NULL;
19113N/A PyObject *item = NULL;
19113N/A+ PyObject *items = NULL;
19113N/A PyObject *encoded = NULL;
19113N/A int skipkeys;
19113N/A Py_ssize_t idx;
19113N/A@@ -2232,22 +2232,61 @@
19113N/A */
19113N/A }
19113N/A
19113N/A- /* TODO: C speedup not implemented for sort_keys */
19113N/A+ if (PyObject_IsTrue(s->sort_keys)) {
19113N/A+ /* First sort the keys then replace them with (key, value) tuples. */
19113N/A+ Py_ssize_t i, nitems;
19113N/A+ if (PyDict_CheckExact(dct))
19113N/A+ items = PyDict_Keys(dct);
19113N/A+ else
19113N/A+ items = PyMapping_Keys(dct);
19113N/A+ if (items == NULL)
19113N/A+ goto bail;
19113N/A+ if (!PyList_Check(items)) {
19113N/A+ PyErr_SetString(PyExc_ValueError, "keys must return list");
19113N/A+ goto bail;
19113N/A+ }
19113N/A+ if (PyList_Sort(items) < 0)
19113N/A+ goto bail;
19113N/A+ nitems = PyList_GET_SIZE(items);
19113N/A+ for (i = 0; i < nitems; i++) {
19113N/A+ PyObject *key, *value;
19113N/A+ key = PyList_GET_ITEM(items, i);
19113N/A+ value = PyDict_GetItem(dct, key);
19113N/A+ item = PyTuple_Pack(2, key, value);
19113N/A+ if (item == NULL)
19113N/A+ goto bail;
19113N/A+ PyList_SET_ITEM(items, i, item);
19113N/A+ Py_DECREF(key);
19113N/A+ }
19113N/A+ }
19113N/A+ else {
19113N/A+ if (PyDict_CheckExact(dct))
19113N/A+ items = PyDict_Items(dct);
19113N/A+ else
19113N/A+ items = PyMapping_Items(dct);
19113N/A+ }
19113N/A+ if (items == NULL)
19113N/A+ goto bail;
19113N/A+ iter = PyObject_GetIter(items);
19113N/A+ Py_DECREF(items);
19113N/A+ if (iter == NULL)
19113N/A+ goto bail;
19113N/A
19113N/A skipkeys = PyObject_IsTrue(s->skipkeys);
19113N/A idx = 0;
19113N/A- iter = PyObject_CallMethodObjArgs(dct, iteritems, NULL);
19113N/A- if (iter == NULL)
19113N/A- goto bail;
19113N/A while ((item = PyIter_Next(iter))) {
19113N/A-
19113N/A- key = PyTuple_GetItem(item, 0);
19113N/A+ PyObject *encoded, *key, *value;
19113N/A+ if (!PyTuple_Check(item) || Py_SIZE(item) != 2) {
19113N/A+ PyErr_SetString(PyExc_ValueError, "items must return 2-tuples");
19113N/A+ goto bail;
19113N/A+ }
19113N/A+ key = PyTuple_GET_ITEM(item, 0);
19113N/A if (key == NULL)
19113N/A goto bail;
19113N/A- value = PyTuple_GetItem(item, 1);
19113N/A+ value = PyTuple_GET_ITEM(item, 1);
19113N/A if (value == NULL)
19113N/A goto bail;
19113N/A-
19113N/A+
19113N/A encoded = PyDict_GetItem(s->key_memo, key);
19113N/A if (encoded != NULL) {
19113N/A Py_INCREF(encoded);
19113N/A@@ -2261,13 +2300,15 @@
19113N/A if (kstr == NULL)
19113N/A goto bail;
19113N/A }
19113N/A- else if (PyInt_Check(key) || PyLong_Check(key)) {
19113N/A- kstr = PyObject_Str(key);
19113N/A+ else if (key == Py_True || key == Py_False || key == Py_None) {
19113N/A+ /* This must come before the PyInt_Check because
19113N/A+ True and False are also 1 and 0.*/
19113N/A+ kstr = _encoded_const(key);
19113N/A if (kstr == NULL)
19113N/A goto bail;
19113N/A }
19113N/A- else if (key == Py_True || key == Py_False || key == Py_None) {
19113N/A- kstr = _encoded_const(key);
19113N/A+ else if (PyInt_Check(key) || PyLong_Check(key)) {
19113N/A+ kstr = PyObject_Str(key);
19113N/A if (kstr == NULL)
19113N/A goto bail;
19113N/A }
19113N/A@@ -2326,7 +2367,7 @@
19113N/A
19113N/A bail:
19113N/A Py_XDECREF(encoded);
19113N/A- Py_XDECREF(item);
19113N/A+ Py_XDECREF(items);
19113N/A Py_XDECREF(iter);
19113N/A Py_XDECREF(kstr);
19113N/A Py_XDECREF(ident);
19113N/Adiff -r 2cbf5e82b45e -r ac61b03c1957 simplejson/encoder.py
19113N/A--- a/simplejson/encoder.py Mon Nov 01 10:35:26 2010 +0100
19113N/A+++ b/simplejson/encoder.py Thu Nov 04 17:54:48 2010 +0100
19113N/A@@ -268,7 +268,7 @@
19113N/A
19113N/A key_memo = {}
19113N/A if (_one_shot and c_make_encoder is not None
19113N/A- and self.indent is None and not self.sort_keys):
19113N/A+ and self.indent is None):
19113N/A _iterencode = c_make_encoder(
19113N/A markers, self.default, _encoder, self.indent,
19113N/A self.key_separator, self.item_separator, self.sort_keys,
19113N/Adiff -r 2cbf5e82b45e -r ac61b03c1957 simplejson/tests/test_encode_basestring_ascii.py
19113N/A--- a/simplejson/tests/test_encode_basestring_ascii.py Mon Nov 01 10:35:26 2010 +0100
19113N/A+++ b/simplejson/tests/test_encode_basestring_ascii.py Thu Nov 04 17:54:48 2010 +0100
19113N/A@@ -39,3 +39,8 @@
19113N/A # result, expect, fname, input_string))
19113N/A self.assertEquals(result, expect,
19113N/A '%r != %r for %s(%r)' % (result, expect, fname, input_string))
19113N/A+
19113N/A+ def test_sorted_dict(self):
19113N/A+ items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
19113N/A+ s = simplejson.dumps(dict(items), sort_keys=True)
19113N/A+ self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}')