diff options
author | Bob Ippolito <bob@redivi.com> | 2016-10-28 17:25:45 +0800 |
---|---|---|
committer | Bob Ippolito <bob@redivi.com> | 2016-10-28 17:25:45 +0800 |
commit | e2f4fe262576c659dad214c1144cd941dcf400b8 (patch) | |
tree | 47c875fd61c3c9a1f1c9f56fb535ff68dae82ff5 | |
parent | 3233faaf438690d0aa853d131ead4a9c99935485 (diff) | |
parent | dd0f99d6431b5e75293369f5554a1396f8ae6251 (diff) | |
download | simplejson-e2f4fe262576c659dad214c1144cd941dcf400b8.tar.gz |
Merge branch 'lamflam-raw_json'
-rw-r--r-- | CHANGES.txt | 5 | ||||
-rw-r--r-- | conf.py | 4 | ||||
-rw-r--r-- | setup.py | 2 | ||||
-rw-r--r-- | simplejson/__init__.py | 4 | ||||
-rw-r--r-- | simplejson/_speedups.c | 22 | ||||
-rw-r--r-- | simplejson/encoder.py | 14 | ||||
-rw-r--r-- | simplejson/tests/__init__.py | 1 | ||||
-rw-r--r-- | simplejson/tests/test_raw_json.py | 47 |
8 files changed, 94 insertions, 5 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 06bb692..f6b8c25 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,8 @@ +Version 3.10.0 released XXXX-XX-XX + +* Add RawJSON class to allow a faster path for already encoded JSON. + https://github.com/simplejson/simplejson/pull/143 + Version 3.9.0 released 2016-10-21 * Workaround for bad behavior in string subclasses @@ -42,9 +42,9 @@ copyright = '2016, Bob Ippolito' # other places throughout the built documents. # # The short X.Y version. -version = '3.9' +version = '3.10' # The full version, including alpha/beta/rc tags. -release = '3.9.0' +release = '3.10.0' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: @@ -11,7 +11,7 @@ from distutils.errors import CCompilerError, DistutilsExecError, \ DistutilsPlatformError IS_PYPY = hasattr(sys, 'pypy_translation_info') -VERSION = '3.9.0' +VERSION = '3.10.0' DESCRIPTION = "Simple, fast, extensible JSON encoder/decoder for Python" with open('README.rst', 'r') as f: diff --git a/simplejson/__init__.py b/simplejson/__init__.py index 84acfa4..d4876cd 100644 --- a/simplejson/__init__.py +++ b/simplejson/__init__.py @@ -97,7 +97,7 @@ Using simplejson.tool from the shell to validate and pretty-print:: Expecting property name: line 1 column 3 (char 2) """ from __future__ import absolute_import -__version__ = '3.9.0' +__version__ = '3.10.0' __all__ = [ 'dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder', @@ -110,7 +110,7 @@ from decimal import Decimal from .scanner import JSONDecodeError from .decoder import JSONDecoder -from .encoder import JSONEncoder, JSONEncoderForHTML +from .encoder import JSONEncoder, JSONEncoderForHTML, RawJSON def _import_OrderedDict(): import collections try: diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c index 9976464..2d81063 100644 --- a/simplejson/_speedups.c +++ b/simplejson/_speedups.c @@ -245,6 +245,8 @@ static void encoder_dealloc(PyObject *self); static int encoder_clear(PyObject *self); +static int +is_raw_json(PyObject *obj); static PyObject * encoder_stringify_key(PyEncoderObject *s, PyObject *key); static int @@ -277,6 +279,20 @@ moduleinit(void); #define MIN_EXPANSION 6 +static PyObject* RawJSONType; +static int +is_raw_json(PyObject *obj) +{ + if (RawJSONType == NULL) { + PyObject *encoder_module = PyImport_ImportModule("simplejson.encoder"); + RawJSONType = PyObject_GetAttrString(encoder_module, "RawJSON"); + Py_DECREF(encoder_module); + if (RawJSONType == NULL) + return 0; + } + return PyObject_IsInstance(obj, RawJSONType) ? 1 : 0; +} + static int JSON_Accu_Init(JSON_Accu *acc) { @@ -2868,6 +2884,12 @@ encoder_listencode_obj(PyEncoderObject *s, JSON_Accu *rval, PyObject *obj, Py_ss if (encoded != NULL) rv = _steal_accumulate(rval, encoded); } + else if (is_raw_json(obj)) + { + PyObject *encoded = PyObject_GetAttrString(obj, "encoded_json"); + if (encoded != NULL) + rv = _steal_accumulate(rval, encoded); + } else if (PyInt_Check(obj) || PyLong_Check(obj)) { PyObject *encoded; if (PyInt_CheckExact(obj) || PyLong_CheckExact(obj)) { diff --git a/simplejson/encoder.py b/simplejson/encoder.py index d453d09..226480f 100644 --- a/simplejson/encoder.py +++ b/simplejson/encoder.py @@ -39,6 +39,14 @@ for i in [0x2028, 0x2029]: FLOAT_REPR = repr +class RawJSON(object): + """Wrap an encoded JSON document for direct embedding in the output + + """ + def __init__(self, encoded_json): + self.encoded_json = encoded_json + + def encode_basestring(s, _PY3=PY3, _q=u('"')): """Return a JSON representation of a Python string @@ -472,6 +480,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, if (isinstance(value, string_types) or (_PY3 and isinstance(value, binary_type))): yield buf + _encoder(value) + elif isinstance(value, RawJSON): + yield buf + value.encoded_json elif value is None: yield buf + 'null' elif value is True: @@ -590,6 +600,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, if (isinstance(value, string_types) or (_PY3 and isinstance(value, binary_type))): yield _encoder(value) + elif isinstance(value, RawJSON): + yield value.encoded_json elif value is None: yield 'null' elif value is True: @@ -632,6 +644,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, if (isinstance(o, string_types) or (_PY3 and isinstance(o, binary_type))): yield _encoder(o) + elif isinstance(o, RawJSON): + yield o.encoded_json elif o is None: yield 'null' elif o is True: diff --git a/simplejson/tests/__init__.py b/simplejson/tests/__init__.py index 3a00b08..95e98e5 100644 --- a/simplejson/tests/__init__.py +++ b/simplejson/tests/__init__.py @@ -65,6 +65,7 @@ def all_tests_suite(): 'simplejson.tests.test_tool', 'simplejson.tests.test_for_json', 'simplejson.tests.test_subclass', + 'simplejson.tests.test_raw_json', ])) suite = get_suite() import simplejson diff --git a/simplejson/tests/test_raw_json.py b/simplejson/tests/test_raw_json.py new file mode 100644 index 0000000..1dfcc2c --- /dev/null +++ b/simplejson/tests/test_raw_json.py @@ -0,0 +1,47 @@ +import unittest +import simplejson as json + +dct1 = { + 'key1': 'value1' +} + +dct2 = { + 'key2': 'value2', + 'd1': dct1 +} + +dct3 = { + 'key2': 'value2', + 'd1': json.dumps(dct1) +} + +dct4 = { + 'key2': 'value2', + 'd1': json.RawJSON(json.dumps(dct1)) +} + + +class TestRawJson(unittest.TestCase): + + def test_normal_str(self): + self.assertNotEqual(json.dumps(dct2), json.dumps(dct3)) + + def test_raw_json_str(self): + self.assertEqual(json.dumps(dct2), json.dumps(dct4)) + self.assertEqual(dct2, json.loads(json.dumps(dct4))) + + def test_list(self): + self.assertEqual( + json.dumps([dct2]), + json.dumps([json.RawJSON(json.dumps(dct2))])) + self.assertEqual( + [dct2], + json.loads(json.dumps([json.RawJSON(json.dumps(dct2))]))) + + def test_direct(self): + self.assertEqual( + json.dumps(dct2), + json.dumps(json.RawJSON(json.dumps(dct2)))) + self.assertEqual( + dct2, + json.loads(json.dumps(json.RawJSON(json.dumps(dct2))))) |