Skip to content

Commit

Permalink
Merge branch 'lamflam-raw_json'
Browse files Browse the repository at this point in the history
  • Loading branch information
etrepum committed Oct 28, 2016
2 parents 3233faa + dd0f99d commit e2f4fe2
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
# 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:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
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:
Expand Down
4 changes: 2 additions & 2 deletions simplejson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
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',
Expand All @@ -110,7 +110,7 @@

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:
Expand Down
22 changes: 22 additions & 0 deletions simplejson/_speedups.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)) {
Expand Down
14 changes: 14 additions & 0 deletions simplejson/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ def _import_speedups():

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
Expand Down Expand Up @@ -472,6 +480,8 @@ def _iterencode_list(lst, _current_indent_level):
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:
Expand Down Expand Up @@ -590,6 +600,8 @@ def _iterencode_dict(dct, _current_indent_level):
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:
Expand Down Expand Up @@ -632,6 +644,8 @@ def _iterencode(o, _current_indent_level):
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:
Expand Down
1 change: 1 addition & 0 deletions simplejson/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def get_suite():
'simplejson.tests.test_tool',
'simplejson.tests.test_for_json',
'simplejson.tests.test_subclass',
'simplejson.tests.test_raw_json',
]))
suite = get_suite()
import simplejson
Expand Down
47 changes: 47 additions & 0 deletions simplejson/tests/test_raw_json.py
Original file line number Diff line number Diff line change
@@ -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)))))

0 comments on commit e2f4fe2

Please sign in to comment.