mirror of https://github.com/django/django.git
Fixed #3320: upgraded django.utils.simplejson to simplejson version 1.5. Thanks, Lawrence Oluyede.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4454 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
1e3d035fcc
commit
695302ce92
|
@ -1,4 +1,4 @@
|
||||||
simplejson 1.3
|
simplejson 1.5
|
||||||
Copyright (c) 2006 Bob Ippolito
|
Copyright (c) 2006 Bob Ippolito
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
|
|
@ -27,6 +27,21 @@ Encoding basic Python object hierarchies::
|
||||||
>>> io.getvalue()
|
>>> io.getvalue()
|
||||||
'["streaming API"]'
|
'["streaming API"]'
|
||||||
|
|
||||||
|
Compact encoding::
|
||||||
|
|
||||||
|
>>> import simplejson
|
||||||
|
>>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
|
||||||
|
'[1,2,3,{"4":5,"6":7}]'
|
||||||
|
|
||||||
|
Pretty printing::
|
||||||
|
|
||||||
|
>>> import simplejson
|
||||||
|
>>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
|
||||||
|
{
|
||||||
|
"4": 5,
|
||||||
|
"6": 7
|
||||||
|
}
|
||||||
|
|
||||||
Decoding JSON::
|
Decoding JSON::
|
||||||
|
|
||||||
>>> import simplejson
|
>>> import simplejson
|
||||||
|
@ -68,10 +83,10 @@ Extending JSONEncoder::
|
||||||
['[', '2.0', ', ', '1.0', ']']
|
['[', '2.0', ', ', '1.0', ']']
|
||||||
|
|
||||||
|
|
||||||
Note that the JSON produced by this module is a subset of YAML,
|
Note that the JSON produced by this module's default settings
|
||||||
so it may be used as a serializer for that as well.
|
is a subset of YAML, so it may be used as a serializer for that as well.
|
||||||
"""
|
"""
|
||||||
__version__ = '1.3'
|
__version__ = '1.5'
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'dump', 'dumps', 'load', 'loads',
|
'dump', 'dumps', 'load', 'loads',
|
||||||
'JSONDecoder', 'JSONEncoder',
|
'JSONDecoder', 'JSONEncoder',
|
||||||
|
@ -81,7 +96,7 @@ from django.utils.simplejson.decoder import JSONDecoder
|
||||||
from django.utils.simplejson.encoder import JSONEncoder
|
from django.utils.simplejson.encoder import JSONEncoder
|
||||||
|
|
||||||
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
|
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||||
allow_nan=True, cls=None, **kw):
|
allow_nan=True, cls=None, indent=None, **kw):
|
||||||
"""
|
"""
|
||||||
Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
|
Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
|
||||||
``.write()``-supporting file-like object).
|
``.write()``-supporting file-like object).
|
||||||
|
@ -105,6 +120,10 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||||
in strict compliance of the JSON specification, instead of using the
|
in strict compliance of the JSON specification, instead of using the
|
||||||
JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
|
JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
|
||||||
|
|
||||||
|
If ``indent`` is a non-negative integer, then JSON array elements and object
|
||||||
|
members will be pretty-printed with that indent level. An indent level
|
||||||
|
of 0 will only insert newlines. ``None`` is the most compact representation.
|
||||||
|
|
||||||
To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
|
To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
|
||||||
``.default()`` method to serialize additional types), specify it with
|
``.default()`` method to serialize additional types), specify it with
|
||||||
the ``cls`` kwarg.
|
the ``cls`` kwarg.
|
||||||
|
@ -112,7 +131,7 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||||
if cls is None:
|
if cls is None:
|
||||||
cls = JSONEncoder
|
cls = JSONEncoder
|
||||||
iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
|
iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
|
||||||
check_circular=check_circular, allow_nan=allow_nan,
|
check_circular=check_circular, allow_nan=allow_nan, indent=indent,
|
||||||
**kw).iterencode(obj)
|
**kw).iterencode(obj)
|
||||||
# could accelerate with writelines in some versions of Python, at
|
# could accelerate with writelines in some versions of Python, at
|
||||||
# a debuggability cost
|
# a debuggability cost
|
||||||
|
@ -120,7 +139,7 @@ def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||||
fp.write(chunk)
|
fp.write(chunk)
|
||||||
|
|
||||||
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
|
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||||
allow_nan=True, cls=None, **kw):
|
allow_nan=True, cls=None, indent=None, separators=None, **kw):
|
||||||
"""
|
"""
|
||||||
Serialize ``obj`` to a JSON formatted ``str``.
|
Serialize ``obj`` to a JSON formatted ``str``.
|
||||||
|
|
||||||
|
@ -141,14 +160,26 @@ def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
|
||||||
strict compliance of the JSON specification, instead of using the
|
strict compliance of the JSON specification, instead of using the
|
||||||
JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
|
JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
|
||||||
|
|
||||||
|
If ``indent`` is a non-negative integer, then JSON array elements and
|
||||||
|
object members will be pretty-printed with that indent level. An indent
|
||||||
|
level of 0 will only insert newlines. ``None`` is the most compact
|
||||||
|
representation.
|
||||||
|
|
||||||
|
If ``separators`` is an ``(item_separator, dict_separator)`` tuple
|
||||||
|
then it will be used instead of the default ``(', ', ': ')`` separators.
|
||||||
|
``(',', ':')`` is the most compact JSON representation.
|
||||||
|
|
||||||
To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
|
To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
|
||||||
``.default()`` method to serialize additional types), specify it with
|
``.default()`` method to serialize additional types), specify it with
|
||||||
the ``cls`` kwarg.
|
the ``cls`` kwarg.
|
||||||
"""
|
"""
|
||||||
if cls is None:
|
if cls is None:
|
||||||
cls = JSONEncoder
|
cls = JSONEncoder
|
||||||
return cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
|
return cls(
|
||||||
check_circular=check_circular, allow_nan=allow_nan, **kw).encode(obj)
|
skipkeys=skipkeys, ensure_ascii=ensure_ascii,
|
||||||
|
check_circular=check_circular, allow_nan=allow_nan, indent=indent,
|
||||||
|
separators=separators,
|
||||||
|
**kw).encode(obj)
|
||||||
|
|
||||||
def load(fp, encoding=None, cls=None, object_hook=None, **kw):
|
def load(fp, encoding=None, cls=None, object_hook=None, **kw):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -127,6 +127,7 @@ def JSONObject(match, context, _w=WHITESPACE.match):
|
||||||
raise ValueError(errmsg("Expecting property name", s, end))
|
raise ValueError(errmsg("Expecting property name", s, end))
|
||||||
end += 1
|
end += 1
|
||||||
encoding = getattr(context, 'encoding', None)
|
encoding = getattr(context, 'encoding', None)
|
||||||
|
iterscan = JSONScanner.iterscan
|
||||||
while True:
|
while True:
|
||||||
key, end = scanstring(s, end, encoding)
|
key, end = scanstring(s, end, encoding)
|
||||||
end = _w(s, end).end()
|
end = _w(s, end).end()
|
||||||
|
@ -134,7 +135,7 @@ def JSONObject(match, context, _w=WHITESPACE.match):
|
||||||
raise ValueError(errmsg("Expecting : delimiter", s, end))
|
raise ValueError(errmsg("Expecting : delimiter", s, end))
|
||||||
end = _w(s, end + 1).end()
|
end = _w(s, end + 1).end()
|
||||||
try:
|
try:
|
||||||
value, end = JSONScanner.iterscan(s, idx=end).next()
|
value, end = iterscan(s, idx=end, context=context).next()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
raise ValueError(errmsg("Expecting object", s, end))
|
raise ValueError(errmsg("Expecting object", s, end))
|
||||||
pairs[key] = value
|
pairs[key] = value
|
||||||
|
@ -164,9 +165,10 @@ def JSONArray(match, context, _w=WHITESPACE.match):
|
||||||
nextchar = s[end:end + 1]
|
nextchar = s[end:end + 1]
|
||||||
if nextchar == ']':
|
if nextchar == ']':
|
||||||
return values, end + 1
|
return values, end + 1
|
||||||
|
iterscan = JSONScanner.iterscan
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
value, end = JSONScanner.iterscan(s, idx=end).next()
|
value, end = iterscan(s, idx=end, context=context).next()
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
raise ValueError(errmsg("Expecting object", s, end))
|
raise ValueError(errmsg("Expecting object", s, end))
|
||||||
values.append(value)
|
values.append(value)
|
||||||
|
|
|
@ -3,11 +3,11 @@ Implementation of JSONEncoder
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# this should match any kind of infinity
|
|
||||||
INFCHARS = re.compile(r'[infINF]')
|
|
||||||
ESCAPE = re.compile(r'[\x00-\x19\\"\b\f\n\r\t]')
|
ESCAPE = re.compile(r'[\x00-\x19\\"\b\f\n\r\t]')
|
||||||
ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
|
ESCAPE_ASCII = re.compile(r'([\\"/]|[^\ -~])')
|
||||||
ESCAPE_DCT = {
|
ESCAPE_DCT = {
|
||||||
|
# escape all forward slashes to prevent </script> attack
|
||||||
|
'/': '\\/',
|
||||||
'\\': '\\\\',
|
'\\': '\\\\',
|
||||||
'"': '\\"',
|
'"': '\\"',
|
||||||
'\b': '\\b',
|
'\b': '\\b',
|
||||||
|
@ -16,31 +16,31 @@ ESCAPE_DCT = {
|
||||||
'\r': '\\r',
|
'\r': '\\r',
|
||||||
'\t': '\\t',
|
'\t': '\\t',
|
||||||
}
|
}
|
||||||
for i in range(20):
|
for i in range(0x20):
|
||||||
ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
|
ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
|
||||||
|
|
||||||
|
# assume this produces an infinity on all machines (probably not guaranteed)
|
||||||
|
INFINITY = float('1e66666')
|
||||||
|
|
||||||
def floatstr(o, allow_nan=True):
|
def floatstr(o, allow_nan=True):
|
||||||
s = str(o)
|
# Check for specials. Note that this type of test is processor- and/or
|
||||||
# If the first non-sign is a digit then it's not a special value
|
# platform-specific, so do tests which don't depend on the internals.
|
||||||
if (o < 0.0 and s[1].isdigit()) or s[0].isdigit():
|
|
||||||
return s
|
if o != o:
|
||||||
elif not allow_nan:
|
text = 'NaN'
|
||||||
|
elif o == INFINITY:
|
||||||
|
text = 'Infinity'
|
||||||
|
elif o == -INFINITY:
|
||||||
|
text = '-Infinity'
|
||||||
|
else:
|
||||||
|
return str(o)
|
||||||
|
|
||||||
|
if not allow_nan:
|
||||||
raise ValueError("Out of range float values are not JSON compliant: %r"
|
raise ValueError("Out of range float values are not JSON compliant: %r"
|
||||||
% (o,))
|
% (o,))
|
||||||
# These are the string representations on the platforms I've tried
|
|
||||||
if s == 'nan':
|
return text
|
||||||
return 'NaN'
|
|
||||||
if s == 'inf':
|
|
||||||
return 'Infinity'
|
|
||||||
if s == '-inf':
|
|
||||||
return '-Infinity'
|
|
||||||
# NaN should either be inequal to itself, or equal to everything
|
|
||||||
if o != o or o == 0.0:
|
|
||||||
return 'NaN'
|
|
||||||
# Last ditch effort, assume inf
|
|
||||||
if o < 0:
|
|
||||||
return '-Infinity'
|
|
||||||
return 'Infinity'
|
|
||||||
|
|
||||||
def encode_basestring(s):
|
def encode_basestring(s):
|
||||||
"""
|
"""
|
||||||
|
@ -90,8 +90,11 @@ class JSONEncoder(object):
|
||||||
implementation (to raise ``TypeError``).
|
implementation (to raise ``TypeError``).
|
||||||
"""
|
"""
|
||||||
__all__ = ['__init__', 'default', 'encode', 'iterencode']
|
__all__ = ['__init__', 'default', 'encode', 'iterencode']
|
||||||
|
item_separator = ', '
|
||||||
|
key_separator = ': '
|
||||||
def __init__(self, skipkeys=False, ensure_ascii=True,
|
def __init__(self, skipkeys=False, ensure_ascii=True,
|
||||||
check_circular=True, allow_nan=True, sort_keys=False):
|
check_circular=True, allow_nan=True, sort_keys=False,
|
||||||
|
indent=None, separators=None):
|
||||||
"""
|
"""
|
||||||
Constructor for JSONEncoder, with sensible defaults.
|
Constructor for JSONEncoder, with sensible defaults.
|
||||||
|
|
||||||
|
@ -116,6 +119,15 @@ class JSONEncoder(object):
|
||||||
If sort_keys is True, then the output of dictionaries will be
|
If sort_keys is True, then the output of dictionaries will be
|
||||||
sorted by key; this is useful for regression tests to ensure
|
sorted by key; this is useful for regression tests to ensure
|
||||||
that JSON serializations can be compared on a day-to-day basis.
|
that JSON serializations can be compared on a day-to-day basis.
|
||||||
|
|
||||||
|
If indent is a non-negative integer, then JSON array
|
||||||
|
elements and object members will be pretty-printed with that
|
||||||
|
indent level. An indent level of 0 will only insert newlines.
|
||||||
|
None is the most compact representation.
|
||||||
|
|
||||||
|
If specified, separators should be a (item_separator, key_separator)
|
||||||
|
tuple. The default is (', ', ': '). To get the most compact JSON
|
||||||
|
representation you should specify (',', ':') to eliminate whitespace.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.skipkeys = skipkeys
|
self.skipkeys = skipkeys
|
||||||
|
@ -123,6 +135,13 @@ class JSONEncoder(object):
|
||||||
self.check_circular = check_circular
|
self.check_circular = check_circular
|
||||||
self.allow_nan = allow_nan
|
self.allow_nan = allow_nan
|
||||||
self.sort_keys = sort_keys
|
self.sort_keys = sort_keys
|
||||||
|
self.indent = indent
|
||||||
|
self.current_indent_level = 0
|
||||||
|
if separators is not None:
|
||||||
|
self.item_separator, self.key_separator = separators
|
||||||
|
|
||||||
|
def _newline_indent(self):
|
||||||
|
return '\n' + (' ' * (self.indent * self.current_indent_level))
|
||||||
|
|
||||||
def _iterencode_list(self, lst, markers=None):
|
def _iterencode_list(self, lst, markers=None):
|
||||||
if not lst:
|
if not lst:
|
||||||
|
@ -134,14 +153,25 @@ class JSONEncoder(object):
|
||||||
raise ValueError("Circular reference detected")
|
raise ValueError("Circular reference detected")
|
||||||
markers[markerid] = lst
|
markers[markerid] = lst
|
||||||
yield '['
|
yield '['
|
||||||
|
if self.indent is not None:
|
||||||
|
self.current_indent_level += 1
|
||||||
|
newline_indent = self._newline_indent()
|
||||||
|
separator = self.item_separator + newline_indent
|
||||||
|
yield newline_indent
|
||||||
|
else:
|
||||||
|
newline_indent = None
|
||||||
|
separator = self.item_separator
|
||||||
first = True
|
first = True
|
||||||
for value in lst:
|
for value in lst:
|
||||||
if first:
|
if first:
|
||||||
first = False
|
first = False
|
||||||
else:
|
else:
|
||||||
yield ', '
|
yield separator
|
||||||
for chunk in self._iterencode(value, markers):
|
for chunk in self._iterencode(value, markers):
|
||||||
yield chunk
|
yield chunk
|
||||||
|
if newline_indent is not None:
|
||||||
|
self.current_indent_level -= 1
|
||||||
|
yield self._newline_indent()
|
||||||
yield ']'
|
yield ']'
|
||||||
if markers is not None:
|
if markers is not None:
|
||||||
del markers[markerid]
|
del markers[markerid]
|
||||||
|
@ -156,6 +186,15 @@ class JSONEncoder(object):
|
||||||
raise ValueError("Circular reference detected")
|
raise ValueError("Circular reference detected")
|
||||||
markers[markerid] = dct
|
markers[markerid] = dct
|
||||||
yield '{'
|
yield '{'
|
||||||
|
key_separator = self.key_separator
|
||||||
|
if self.indent is not None:
|
||||||
|
self.current_indent_level += 1
|
||||||
|
newline_indent = self._newline_indent()
|
||||||
|
item_separator = self.item_separator + newline_indent
|
||||||
|
yield newline_indent
|
||||||
|
else:
|
||||||
|
newline_indent = None
|
||||||
|
item_separator = self.item_separator
|
||||||
first = True
|
first = True
|
||||||
if self.ensure_ascii:
|
if self.ensure_ascii:
|
||||||
encoder = encode_basestring_ascii
|
encoder = encode_basestring_ascii
|
||||||
|
@ -165,7 +204,7 @@ class JSONEncoder(object):
|
||||||
if self.sort_keys:
|
if self.sort_keys:
|
||||||
keys = dct.keys()
|
keys = dct.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
items = [(k,dct[k]) for k in keys]
|
items = [(k, dct[k]) for k in keys]
|
||||||
else:
|
else:
|
||||||
items = dct.iteritems()
|
items = dct.iteritems()
|
||||||
for key, value in items:
|
for key, value in items:
|
||||||
|
@ -190,11 +229,14 @@ class JSONEncoder(object):
|
||||||
if first:
|
if first:
|
||||||
first = False
|
first = False
|
||||||
else:
|
else:
|
||||||
yield ', '
|
yield item_separator
|
||||||
yield encoder(key)
|
yield encoder(key)
|
||||||
yield ': '
|
yield key_separator
|
||||||
for chunk in self._iterencode(value, markers):
|
for chunk in self._iterencode(value, markers):
|
||||||
yield chunk
|
yield chunk
|
||||||
|
if newline_indent is not None:
|
||||||
|
self.current_indent_level -= 1
|
||||||
|
yield self._newline_indent()
|
||||||
yield '}'
|
yield '}'
|
||||||
if markers is not None:
|
if markers is not None:
|
||||||
del markers[markerid]
|
del markers[markerid]
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
from django.utils import simplejson
|
||||||
|
import cgi
|
||||||
|
|
||||||
|
class JSONFilter(object):
|
||||||
|
def __init__(self, app, mime_type='text/x-json'):
|
||||||
|
self.app = app
|
||||||
|
self.mime_type = mime_type
|
||||||
|
|
||||||
|
def __call__(self, environ, start_response):
|
||||||
|
# Read JSON POST input to jsonfilter.json if matching mime type
|
||||||
|
response = {'status': '200 OK', 'headers': []}
|
||||||
|
def json_start_response(status, headers):
|
||||||
|
response['status'] = status
|
||||||
|
response['headers'].extend(headers)
|
||||||
|
environ['jsonfilter.mime_type'] = self.mime_type
|
||||||
|
if environ.get('REQUEST_METHOD', '') == 'POST':
|
||||||
|
if environ.get('CONTENT_TYPE', '') == self.mime_type:
|
||||||
|
args = [_ for _ in [environ.get('CONTENT_LENGTH')] if _]
|
||||||
|
data = environ['wsgi.input'].read(*map(int, args))
|
||||||
|
environ['jsonfilter.json'] = simplejson.loads(data)
|
||||||
|
res = simplejson.dumps(self.app(environ, json_start_response))
|
||||||
|
jsonp = cgi.parse_qs(environ.get('QUERY_STRING', '')).get('jsonp')
|
||||||
|
if jsonp:
|
||||||
|
content_type = 'text/javascript'
|
||||||
|
res = ''.join(jsonp + ['(', res, ')'])
|
||||||
|
elif 'Opera' in environ.get('HTTP_USER_AGENT', ''):
|
||||||
|
# Opera has bunk XMLHttpRequest support for most mime types
|
||||||
|
content_type = 'text/plain'
|
||||||
|
else:
|
||||||
|
content_type = self.mime_type
|
||||||
|
headers = [
|
||||||
|
('Content-type', content_type),
|
||||||
|
('Content-length', len(res)),
|
||||||
|
]
|
||||||
|
headers.extend(response['headers'])
|
||||||
|
start_response(response['status'], headers)
|
||||||
|
return [res]
|
||||||
|
|
||||||
|
def factory(app, global_conf, **kw):
|
||||||
|
return JSONFilter(app, **kw)
|
|
@ -3,11 +3,12 @@ Iterator based sre token scanner
|
||||||
"""
|
"""
|
||||||
import sre_parse, sre_compile, sre_constants
|
import sre_parse, sre_compile, sre_constants
|
||||||
from sre_constants import BRANCH, SUBPATTERN
|
from sre_constants import BRANCH, SUBPATTERN
|
||||||
|
from re import VERBOSE, MULTILINE, DOTALL
|
||||||
import re
|
import re
|
||||||
|
|
||||||
__all__ = ['Scanner', 'pattern']
|
__all__ = ['Scanner', 'pattern']
|
||||||
|
|
||||||
FLAGS = (re.VERBOSE | re.MULTILINE | re.DOTALL)
|
FLAGS = (VERBOSE | MULTILINE | DOTALL)
|
||||||
class Scanner(object):
|
class Scanner(object):
|
||||||
def __init__(self, lexicon, flags=FLAGS):
|
def __init__(self, lexicon, flags=FLAGS):
|
||||||
self.actions = [None]
|
self.actions = [None]
|
||||||
|
|
Loading…
Reference in New Issue