diff --git a/CHANGES.txt b/CHANGES.txt index 8b702c529647350d2e08ca0e2c790a94e2bf5492_Q0hBTkdFUy50eHQ=..14971dfa0c671f7c0de3c1f6e5fdd7aefbd07a43_Q0hBTkdFUy50eHQ= 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,9 @@ +Version 3.5.0 released 2014-05-20 + +* Added int_as_string_bitcount encoder option + https://github.com/simplejson/pull/96 +* Fixed potential crash when encoder created with incorrect options + Version 3.4.1 released 2014-04-30 * Fixed tests to run on Python 3.4 diff --git a/conf.py b/conf.py index 8b702c529647350d2e08ca0e2c790a94e2bf5492_Y29uZi5weQ==..14971dfa0c671f7c0de3c1f6e5fdd7aefbd07a43_Y29uZi5weQ== 100644 --- a/conf.py +++ b/conf.py @@ -42,5 +42,5 @@ # other places throughout the built documents. # # The short X.Y version. -version = '3.4' +version = '3.5' # The full version, including alpha/beta/rc tags. @@ -46,5 +46,5 @@ # The full version, including alpha/beta/rc tags. -release = '3.4.1' +release = '3.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 8b702c529647350d2e08ca0e2c790a94e2bf5492_aW5kZXgucnN0..14971dfa0c671f7c0de3c1f6e5fdd7aefbd07a43_aW5kZXgucnN0 100644 --- a/index.rst +++ b/index.rst @@ -129,7 +129,7 @@ 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[, bigint_as_string[, sort_keys[, item_sort_key[, [for_json[, ignore_nan[, **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[, [for_json[, ignore_nan[, int_as_string_bitcount[, **kw]]]]]]]]]]]]]]]]]]]) Serialize *obj* as a JSON formatted stream to *fp* (a ``.write()``-supporting file-like object). @@ -216,7 +216,7 @@ .. 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`` + 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. @@ -220,6 +220,7 @@ 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. + See also *int_as_string_bitcount*. .. versionchanged:: 2.4.0 *bigint_as_string* is new in 2.4.0. @@ -261,6 +262,15 @@ .. versionchanged:: 3.2.0 *ignore_nan* is new in 3.2.0. + If *int_as_string_bitcount* is a positive number ``n`` (default: ``False``), + :class:`int` ``2**n`` and higher or lower than ``-2**n`` 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. + See also *bigint_as_string* (which is equivalent to `int_as_string_bitcount=53`). + + .. versionchanged:: 3.5.0 + *int_as_string_bitcount* is new in 3.5.0. + .. note:: JSON is not a framed protocol so unlike :mod:`pickle` or :mod:`marshal` it @@ -268,7 +278,7 @@ 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[, bigint_as_string[, sort_keys[, item_sort_key[, for_json[, ignore_nan[, **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[, for_json[, ignore_nan[, int_as_string_bitcount[, **kw]]]]]]]]]]]]]]]]]]) Serialize *obj* to a JSON formatted :class:`str`. diff --git a/setup.py b/setup.py index 8b702c529647350d2e08ca0e2c790a94e2bf5492_c2V0dXAucHk=..14971dfa0c671f7c0de3c1f6e5fdd7aefbd07a43_c2V0dXAucHk= 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ DistutilsPlatformError IS_PYPY = hasattr(sys, 'pypy_translation_info') -VERSION = '3.4.1' +VERSION = '3.5.0' DESCRIPTION = "Simple, fast, extensible JSON encoder/decoder for Python" with open('README.rst', 'r') as f: @@ -30,6 +30,7 @@ Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.3 +Programming Language :: Python :: 3.4 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy Topic :: Software Development :: Libraries :: Python Modules diff --git a/simplejson/__init__.py b/simplejson/__init__.py index 8b702c529647350d2e08ca0e2c790a94e2bf5492_c2ltcGxlanNvbi9fX2luaXRfXy5weQ==..14971dfa0c671f7c0de3c1f6e5fdd7aefbd07a43_c2ltcGxlanNvbi9fX2luaXRfXy5weQ== 100644 --- a/simplejson/__init__.py +++ b/simplejson/__init__.py @@ -98,7 +98,7 @@ Expecting property name: line 1 column 3 (char 2) """ from __future__ import absolute_import -__version__ = '3.4.1' +__version__ = '3.5.0' __all__ = [ 'dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', @@ -211,7 +211,8 @@ sparingly. If *int_as_string_bitcount* is a positive number (n), then int of size - greater than 2**n or lower than -2**n will be encoded as strings. + greater than or equal to 2**n or lower than or equal to -2**n will be + encoded as strings. 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 @@ -325,7 +326,8 @@ rounding that happens in Javascript otherwise. If *int_as_string_bitcount* is a positive number (n), then int of size - greater than 2**n or lower than -2**n will be encoded as strings. + greater than or equal to 2**n or lower than or equal to -2**n will be + encoded as strings. 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 diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c index 8b702c529647350d2e08ca0e2c790a94e2bf5492_c2ltcGxlanNvbi9fc3BlZWR1cHMuYw==..14971dfa0c671f7c0de3c1f6e5fdd7aefbd07a43_c2ltcGxlanNvbi9fc3BlZWR1cHMuYw== 100644 --- a/simplejson/_speedups.c +++ b/simplejson/_speedups.c @@ -2608,4 +2608,5 @@ &ignore_nan, &Decimal)) return -1; + Py_INCREF(markers); s->markers = markers; @@ -2611,2 +2612,3 @@ s->markers = markers; + Py_INCREF(defaultfn); s->defaultfn = defaultfn; @@ -2612,5 +2614,6 @@ s->defaultfn = defaultfn; + Py_INCREF(encoder); s->encoder = encoder; s->encoding = JSON_ParseEncoding(encoding); if (s->encoding == NULL) return -1; @@ -2613,5 +2616,6 @@ s->encoder = encoder; s->encoding = JSON_ParseEncoding(encoding); if (s->encoding == NULL) return -1; + Py_INCREF(indent); s->indent = indent; @@ -2617,2 +2621,3 @@ s->indent = indent; + Py_INCREF(key_separator); s->key_separator = key_separator; @@ -2618,2 +2623,3 @@ s->key_separator = key_separator; + Py_INCREF(item_separator); s->item_separator = item_separator; @@ -2619,3 +2625,4 @@ s->item_separator = item_separator; + Py_INCREF(skipkeys); s->skipkeys_bool = skipkeys; s->skipkeys = PyObject_IsTrue(skipkeys); @@ -2620,5 +2627,6 @@ s->skipkeys_bool = skipkeys; s->skipkeys = PyObject_IsTrue(skipkeys); + Py_INCREF(key_memo); s->key_memo = key_memo; s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii); s->allow_or_ignore_nan = ( @@ -2627,12 +2635,7 @@ s->use_decimal = PyObject_IsTrue(use_decimal); s->namedtuple_as_object = PyObject_IsTrue(namedtuple_as_object); s->tuple_as_array = PyObject_IsTrue(tuple_as_array); - - s->max_long_size = Py_None; - Py_INCREF(Py_None); - s->min_long_size = Py_None; - Py_INCREF(Py_None); if (PyInt_Check(int_as_string_bitcount) || PyLong_Check(int_as_string_bitcount)) { static const unsigned int long_long_bitsize = SIZEOF_LONG_LONG * 8; int int_as_string_bitcount_val = PyLong_AsLong(int_as_string_bitcount); if (int_as_string_bitcount_val > 0 && int_as_string_bitcount_val < long_long_bitsize) { @@ -2635,9 +2638,7 @@ if (PyInt_Check(int_as_string_bitcount) || PyLong_Check(int_as_string_bitcount)) { static const unsigned int long_long_bitsize = SIZEOF_LONG_LONG * 8; int int_as_string_bitcount_val = PyLong_AsLong(int_as_string_bitcount); if (int_as_string_bitcount_val > 0 && int_as_string_bitcount_val < long_long_bitsize) { - Py_DECREF(Py_None); - Py_DECREF(Py_None); s->max_long_size = PyLong_FromUnsignedLongLong(1LLU << int_as_string_bitcount_val); s->min_long_size = PyLong_FromLongLong(-1LL << int_as_string_bitcount_val); if (s->min_long_size == NULL || s->max_long_size == NULL) { @@ -2648,5 +2649,6 @@ PyErr_Format(PyExc_TypeError, "int_as_string_bitcount (%d) must be greater than 0 and less than the number of bits of a `long long` type (%u bits)", int_as_string_bitcount_val, long_long_bitsize); + return -1; } } @@ -2651,6 +2653,15 @@ } } - + else if (int_as_string_bitcount == Py_None) { + Py_INCREF(Py_None); + s->max_long_size = Py_None; + Py_INCREF(Py_None); + s->min_long_size = Py_None; + } + else { + PyErr_SetString(PyExc_TypeError, "int_as_string_bitcount must be None or an integer"); + return -1; + } if (item_sort_key != Py_None) { if (!PyCallable_Check(item_sort_key)) { PyErr_SetString(PyExc_TypeError, "item_sort_key must be None or callable"); @@ -2681,4 +2692,5 @@ if (PyDict_SetItemString(s->item_sort_kw, "key", item_sort_key)) return -1; } + Py_INCREF(sort_keys); s->sort_keys = sort_keys; @@ -2684,2 +2696,3 @@ s->sort_keys = sort_keys; + Py_INCREF(item_sort_key); s->item_sort_key = item_sort_key; @@ -2685,4 +2698,5 @@ s->item_sort_key = item_sort_key; + Py_INCREF(Decimal); s->Decimal = Decimal; s->for_json = PyObject_IsTrue(for_json); @@ -2686,17 +2700,6 @@ s->Decimal = Decimal; s->for_json = PyObject_IsTrue(for_json); - Py_INCREF(s->markers); - Py_INCREF(s->defaultfn); - Py_INCREF(s->encoder); - Py_INCREF(s->indent); - Py_INCREF(s->key_separator); - Py_INCREF(s->item_separator); - Py_INCREF(s->key_memo); - Py_INCREF(s->skipkeys_bool); - Py_INCREF(s->sort_keys); - Py_INCREF(s->item_sort_key); - Py_INCREF(s->Decimal); return 0; } diff --git a/simplejson/encoder.py b/simplejson/encoder.py index 8b702c529647350d2e08ca0e2c790a94e2bf5492_c2ltcGxlanNvbi9lbmNvZGVyLnB5..14971dfa0c671f7c0de3c1f6e5fdd7aefbd07a43_c2ltcGxlanNvbi9lbmNvZGVyLnB5 100644 --- a/simplejson/encoder.py +++ b/simplejson/encoder.py @@ -183,7 +183,8 @@ rounding that happens in Javascript otherwise. If int_as_string_bitcount is a positive number (n), then int of size - greater than 2**n or lower than -2**n will be encoded as strings. + greater than or equal to 2**n or lower than or equal to -2**n will be + encoded as strings. 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 @@ -323,10 +324,7 @@ key_memo = {} int_as_string_bitcount = ( - (self.bigint_as_string and 53) - or - self.int_as_string_bitcount - ) + 53 if self.bigint_as_string else self.int_as_string_bitcount) if (_one_shot and c_make_encoder is not None and self.indent is None): _iterencode = c_make_encoder(