summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Ippolito <bob@redivi.com>2012-03-29 11:59:33 -0700
committerBob Ippolito <bob@redivi.com>2012-03-29 11:59:33 -0700
commita19eb434a6733cf97dd5e4dd4721416743b840aa (patch)
tree1569f32629fd3659f850311bf6bd8f11b3dc984b
parentfb26048e3983c098c8fa2d21009a6695cb128b5a (diff)
downloadsimplejson-a19eb434a6733cf97dd5e4dd4721416743b840aa.tar.gz
bump version to 2.5.0, add docs for item_sort_key
-rw-r--r--CHANGES.txt5
-rw-r--r--conf.py4
-rw-r--r--index.rst69
-rw-r--r--setup.py2
-rw-r--r--simplejson/__init__.py30
-rw-r--r--simplejson/_speedups.c4
-rw-r--r--simplejson/encoder.py2
-rw-r--r--simplejson/tests/test_item_sort_key.py11
8 files changed, 91 insertions, 36 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 94e4434..b03ba76 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,8 @@
+Version 2.5.0 released 2012-03-29
+
+* New item_sort_key option for encoder to allow fine grained control of sorted
+ output
+
Version 2.4.0 released 2012-03-06
* New bigint_as_string option for encoder to trade JavaScript number precision
diff --git a/conf.py b/conf.py
index 150c7cc..4614307 100644
--- a/conf.py
+++ b/conf.py
@@ -42,9 +42,9 @@ copyright = '2011, Bob Ippolito'
# other places throughout the built documents.
#
# The short X.Y version.
-version = '2.4'
+version = '2.5'
# The full version, including alpha/beta/rc tags.
-release = '2.4.0'
+release = '2.5.0'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
diff --git a/index.rst b/index.rst
index fd92f4d..527721f 100644
--- a/index.rst
+++ b/index.rst
@@ -129,7 +129,7 @@ Using :mod:`simplejson.tool` from the shell to validate and pretty-print::
Basic Usage
-----------
-.. function:: dump(obj, fp[, skipkeys[, ensure_ascii[, check_circular[, allow_nan[, cls[, indent[, separators[, encoding[, default[, use_decimal[, namedtuple_as_object[, tuple_as_array[, **kw]]]]]]]]]]]]])
+.. function:: dump(obj, fp[, skipkeys[, ensure_ascii[, check_circular[, allow_nan[, cls[, indent[, separators[, encoding[, default[, use_decimal[, namedtuple_as_object[, tuple_as_array[, bigint_as_string[, sort_keys[, item_sort_key[, **kw]]]]]]]]]]]]]]]])
Serialize *obj* as a JSON formatted stream to *fp* (a ``.write()``-supporting
file-like object).
@@ -189,22 +189,42 @@ Basic Usage
.. versionchanged:: 2.2.0
The default of *use_decimal* changed to ``True`` in 2.2.0.
- If *namedtuple_as_object* is true (default: ``True``),
- objects with ``_asdict()`` methods will be encoded
- as JSON objects.
+ If *namedtuple_as_object* is true (default: ``True``),
+ objects with ``_asdict()`` methods will be encoded
+ as JSON objects.
- .. versionchanged:: 2.2.0
- *namedtuple_as_object* is new in 2.2.0.
+ .. versionchanged:: 2.2.0
+ *namedtuple_as_object* is new in 2.2.0.
- .. versionchanged:: 2.3.0
- *namedtuple_as_object* no longer requires that these objects be
- subclasses of :class:`tuple`.
+ .. versionchanged:: 2.3.0
+ *namedtuple_as_object* no longer requires that these objects be
+ subclasses of :class:`tuple`.
+
+ If *tuple_as_array* is true (default: ``True``),
+ :class:`tuple` (and subclasses) will be encoded as JSON arrays.
- If *tuple_as_array* is true (default: ``True``),
- :class:`tuple` (and subclasses) will be encoded as JSON arrays.
+ .. versionchanged:: 2.2.0
+ *tuple_as_array* is new in 2.2.0.
- .. versionchanged:: 2.2.0
- *tuple_as_array* is new in 2.2.0.
+ If *bigint_as_string* is true (default: ``False``), :class:`int`` ``2**53``
+ and higher or lower than ``-2**53`` will be encoded as strings. This is to
+ avoid the rounding that happens in Javascript otherwise. Note that this
+ option loses type information, so use with extreme caution.
+
+ .. versionchanged:: 2.4.0
+ *bigint_as_string* is new in 2.4.0.
+
+ If *sort_keys* is true (not the default), then the output of dictionaries
+ will be sorted by key; this is useful for regression tests to ensure that
+ JSON serializations can be compared on a day-to-day basis.
+
+ If *item_sort_key* is a callable (not the default), then the output of
+ dictionaries will be sorted with it. The callable will be used like this:
+ ``sorted(dct.items(), key=sort_item_key)``. This option takes precedence
+ over *sort_keys*.
+
+ .. versionchanged:: 2.5.0
+ *item_sort_key* is new in 2.5.0.
.. note::
@@ -213,7 +233,7 @@ Basic Usage
container protocol to delimit them.
-.. function:: dumps(obj[, skipkeys[, ensure_ascii[, check_circular[, allow_nan[, cls[, indent[, separators[, encoding[, default[, use_decimal[, namedtuple_as_object[, tuple_as_array[, **kw]]]]]]]]]]]]])
+.. function:: dumps(obj[, skipkeys[, ensure_ascii[, check_circular[, allow_nan[, cls[, indent[, separators[, encoding[, default[, use_decimal[, namedtuple_as_object[, tuple_as_array[, bigint_as_string[, sort_keys[, item_sort_key[, **kw]]]]]]]]]]]]]]]])
Serialize *obj* to a JSON formatted :class:`str`.
@@ -410,7 +430,7 @@ Encoders and decoders
:exc:`JSONDecodeError` will be raised if the given JSON
document is not valid.
-.. class:: JSONEncoder([skipkeys[, ensure_ascii[, check_circular[, allow_nan[, sort_keys[, indent[, separators[, encoding[, default[, use_decimal[, namedtuple_as_object[, tuple_as_array]]]]]]]]]]]])
+.. class:: JSONEncoder([skipkeys[, ensure_ascii[, check_circular[, allow_nan[, sort_keys[, indent[, separators[, encoding[, default[, use_decimal[, namedtuple_as_object[, tuple_as_array[, bigint_as_string[, item_sort_key]]]]]]]]]]]]])
Extensible JSON encoder for Python data structures.
@@ -465,6 +485,14 @@ Encoders and decoders
will be sorted by key; this is useful for regression tests to ensure that
JSON serializations can be compared on a day-to-day basis.
+ If *item_sort_key* is a callable (not the default), then the output of
+ dictionaries will be sorted with it. The callable will be used like this:
+ ``sorted(dct.items(), key=sort_item_key)``. This option takes precedence
+ over *sort_keys*.
+
+ .. versionchanged:: 2.5.0
+ *item_sort_key* is new in 2.5.0.
+
If *indent* is a string, then JSON array elements and object members
will be pretty-printed with a newline followed by that string repeated
for each level of nesting. ``None`` (the default) selects the most compact
@@ -504,6 +532,15 @@ Encoders and decoders
.. versionchanged:: 2.2.0
*tuple_as_array* is new in 2.2.0.
+ If *bigint_as_string* is true (default: ``False``), :class:`int`` ``2**53``
+ and higher or lower than ``-2**53`` will be encoded as strings. This is to
+ avoid the rounding that happens in Javascript otherwise. Note that this
+ option loses type information, so use with extreme caution.
+
+ .. versionchanged:: 2.4.0
+ *bigint_as_string* is new in 2.4.0.
+
+
.. method:: default(o)
Implement this method in a subclass such that it returns a serializable
@@ -544,7 +581,7 @@ Encoders and decoders
Note that :meth:`encode` has much better performance than
:meth:`iterencode`.
-.. class:: JSONEncoderForHTML([skipkeys[, ensure_ascii[, check_circular[, allow_nan[, sort_keys[, indent[, separators[, encoding[, default]]]]]]]]])
+.. class:: JSONEncoderForHTML([skipkeys[, ensure_ascii[, check_circular[, allow_nan[, sort_keys[, indent[, separators[, encoding[, default[, use_decimal[, namedtuple_as_object[, tuple_as_array[, bigint_as_string[, item_sort_key]]]]]]]]]]]]])
Subclass of :class:`JSONEncoder` that escapes &, <, and > for embedding in HTML.
diff --git a/setup.py b/setup.py
index 68fb1db..aa2f515 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@ from distutils.errors import CCompilerError, DistutilsExecError, \
DistutilsPlatformError
IS_PYPY = hasattr(sys, 'pypy_translation_info')
-VERSION = '2.4.0'
+VERSION = '2.5.0'
DESCRIPTION = "Simple, fast, extensible JSON encoder/decoder for Python"
LONG_DESCRIPTION = open('README.rst', 'r').read()
diff --git a/simplejson/__init__.py b/simplejson/__init__.py
index 3de54de..eb38b46 100644
--- a/simplejson/__init__.py
+++ b/simplejson/__init__.py
@@ -97,11 +97,11 @@ Using simplejson.tool from the shell to validate and pretty-print::
$ echo '{ 1.2:3.4}' | python -m simplejson.tool
Expecting property name: line 1 column 2 (char 2)
"""
-__version__ = '2.4.0'
+__version__ = '2.5.0'
__all__ = [
'dump', 'dumps', 'load', 'loads',
'JSONDecoder', 'JSONDecodeError', 'JSONEncoder',
- 'OrderedDict', 'simple_first'
+ 'OrderedDict', 'simple_first',
]
__author__ = 'Bob Ippolito <bob@redivi.com>'
@@ -146,7 +146,8 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
encoding='utf-8', default=None, use_decimal=True,
namedtuple_as_object=True, tuple_as_array=True,
- bigint_as_string=False, item_sort_key=None, **kw):
+ bigint_as_string=False, sort_keys=False, item_sort_key=None,
+ **kw):
"""Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
``.write()``-supporting file-like object).
@@ -203,7 +204,11 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
If specified, *item_sort_key* is a callable used to sort the items in
each dictionary. This is useful if you want to sort items other than
- in alphabetical order by key.
+ in alphabetical order by key. This option takes precedence over
+ *sort_keys*.
+
+ If *sort_keys* is true (default: ``False``), the output of dictionaries
+ will be sorted by item.
To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
``.default()`` method to serialize additional types), specify it with
@@ -228,6 +233,7 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
namedtuple_as_object=namedtuple_as_object,
tuple_as_array=tuple_as_array,
bigint_as_string=bigint_as_string,
+ sort_keys=sort_keys,
item_sort_key=item_sort_key,
**kw).iterencode(obj)
# could accelerate with writelines in some versions of Python, at
@@ -240,7 +246,7 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
encoding='utf-8', default=None, use_decimal=True,
namedtuple_as_object=True, tuple_as_array=True,
- bigint_as_string=False, item_sort_key=None,
+ bigint_as_string=False, sort_keys=False, item_sort_key=None,
**kw):
"""Serialize ``obj`` to a JSON formatted ``str``.
@@ -287,13 +293,17 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
If *tuple_as_array* is true (default: ``True``),
:class:`tuple` (and subclasses) will be encoded as JSON arrays.
- If bigint_as_string is true (not the default), ints 2**53 and higher
+ If *bigint_as_string* is true (not the default), ints 2**53 and higher
or lower than -2**53 will be encoded as strings. This is to avoid the
rounding that happens in Javascript otherwise.
If specified, *item_sort_key* is a callable used to sort the items in
each dictionary. This is useful if you want to sort items other than
- in alphabetical order by key.
+ in alphabetical order by key. This option takes precendence over
+ *sort_keys*.
+
+ If *sort_keys* is true (default: ``False``), the output of dictionaries
+ will be sorted by item.
To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
``.default()`` method to serialize additional types), specify it with
@@ -306,7 +316,8 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
cls is None and indent is None and separators is None and
encoding == 'utf-8' and default is None and use_decimal
and namedtuple_as_object and tuple_as_array
- and not bigint_as_string and not item_sort_key and not kw):
+ and not bigint_as_string and not sort_keys
+ and not item_sort_key and not kw):
return _default_encoder.encode(obj)
if cls is None:
cls = JSONEncoder
@@ -318,6 +329,7 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
namedtuple_as_object=namedtuple_as_object,
tuple_as_array=tuple_as_array,
bigint_as_string=bigint_as_string,
+ sort_keys=sort_keys,
item_sort_key=item_sort_key,
**kw).encode(obj)
@@ -495,4 +507,4 @@ def simple_first(kv):
"""Helper function to pass to item_sort_key to sort simple
elements to the top, then container elements.
"""
- return isinstance(kv[1],(list,dict,tuple)), kv[0]
+ return (isinstance(kv[1], (list, dict, tuple)), kv[0])
diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c
index f6eef80..e8d6563 100644
--- a/simplejson/_speedups.c
+++ b/simplejson/_speedups.c
@@ -2361,13 +2361,13 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
*/
}
- if (PyCallable_Check(s->item_sort_key)) {
+ if (PyCallable_Check(s->item_sort_key)) {
if (PyDict_CheckExact(dct))
items = PyDict_Items(dct);
else
items = PyMapping_Items(dct);
PyObject_CallMethod(items, "sort", "OO", Py_None, s->item_sort_key);
- }
+ }
else if (PyObject_IsTrue(s->sort_keys)) {
/* First sort the keys then replace them with (key, value) tuples. */
Py_ssize_t i, nitems;
diff --git a/simplejson/encoder.py b/simplejson/encoder.py
index 1790e70..05dd05c 100644
--- a/simplejson/encoder.py
+++ b/simplejson/encoder.py
@@ -358,6 +358,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
str=str,
tuple=tuple,
):
+ if _item_sort_key and not callable(_item_sort_key):
+ raise TypeError("item_sort_key must be None or callable")
def _iterencode_list(lst, _current_indent_level):
if not lst:
diff --git a/simplejson/tests/test_item_sort_key.py b/simplejson/tests/test_item_sort_key.py
index f630d8e..83bea1e 100644
--- a/simplejson/tests/test_item_sort_key.py
+++ b/simplejson/tests/test_item_sort_key.py
@@ -5,17 +5,16 @@ from operator import itemgetter
class TestItemSortKey(TestCase):
def test_simple_first(self):
- a={'a': 1, 'c': 5, 'jack': 'jill', 'pick': 'axe', 'array': [1, 5, 6, 9], 'tuple': (83, 12, 3), 'crate': 'dog', 'zeak': 'oh'}
+ a = {'a': 1, 'c': 5, 'jack': 'jill', 'pick': 'axe', 'array': [1, 5, 6, 9], 'tuple': (83, 12, 3), 'crate': 'dog', 'zeak': 'oh'}
self.assertEquals(
'{"a": 1, "c": 5, "crate": "dog", "jack": "jill", "pick": "axe", "zeak": "oh", "array": [1, 5, 6, 9], "tuple": [83, 12, 3]}',
- json.dumps(a,item_sort_key=json.simple_first))
+ json.dumps(a, item_sort_key=json.simple_first))
def test_case(self):
- a={'a': 1, 'c': 5, 'Jack': 'jill', 'pick': 'axe', 'Array': [1, 5, 6, 9], 'tuple': (83, 12, 3), 'crate': 'dog', 'zeak': 'oh'}
+ a = {'a': 1, 'c': 5, 'Jack': 'jill', 'pick': 'axe', 'Array': [1, 5, 6, 9], 'tuple': (83, 12, 3), 'crate': 'dog', 'zeak': 'oh'}
self.assertEquals(
'{"Array": [1, 5, 6, 9], "Jack": "jill", "a": 1, "c": 5, "crate": "dog", "pick": "axe", "tuple": [83, 12, 3], "zeak": "oh"}',
- json.dumps(a,item_sort_key=itemgetter(0)))
+ json.dumps(a, item_sort_key=itemgetter(0)))
self.assertEquals(
'{"a": 1, "Array": [1, 5, 6, 9], "c": 5, "crate": "dog", "Jack": "jill", "pick": "axe", "tuple": [83, 12, 3], "zeak": "oh"}',
- json.dumps(a,item_sort_key=lambda kv: kv[0].lower()))
-
+ json.dumps(a, item_sort_key=lambda kv: kv[0].lower()))