| Index: src/third_party/pylib/simplejson/encoder.py
|
| ===================================================================
|
| --- src/third_party/pylib/simplejson/encoder.py (revision 9275)
|
| +++ src/third_party/pylib/simplejson/encoder.py (working copy)
|
| @@ -1,501 +0,0 @@
|
| -"""Implementation of JSONEncoder
|
| -"""
|
| -import re
|
| -from decimal import Decimal
|
| -
|
| -def _import_speedups():
|
| - try:
|
| - from simplejson import _speedups
|
| - return _speedups.encode_basestring_ascii, _speedups.make_encoder
|
| - except ImportError:
|
| - return None, None
|
| -c_encode_basestring_ascii, c_make_encoder = _import_speedups()
|
| -
|
| -from simplejson.decoder import PosInf
|
| -
|
| -ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
|
| -ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
|
| -HAS_UTF8 = re.compile(r'[\x80-\xff]')
|
| -ESCAPE_DCT = {
|
| - '\\': '\\\\',
|
| - '"': '\\"',
|
| - '\b': '\\b',
|
| - '\f': '\\f',
|
| - '\n': '\\n',
|
| - '\r': '\\r',
|
| - '\t': '\\t',
|
| -}
|
| -for i in range(0x20):
|
| - #ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
|
| - ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
|
| -
|
| -FLOAT_REPR = repr
|
| -
|
| -def encode_basestring(s):
|
| - """Return a JSON representation of a Python string
|
| -
|
| - """
|
| - if isinstance(s, str) and HAS_UTF8.search(s) is not None:
|
| - s = s.decode('utf-8')
|
| - def replace(match):
|
| - return ESCAPE_DCT[match.group(0)]
|
| - return u'"' + ESCAPE.sub(replace, s) + u'"'
|
| -
|
| -
|
| -def py_encode_basestring_ascii(s):
|
| - """Return an ASCII-only JSON representation of a Python string
|
| -
|
| - """
|
| - if isinstance(s, str) and HAS_UTF8.search(s) is not None:
|
| - s = s.decode('utf-8')
|
| - def replace(match):
|
| - s = match.group(0)
|
| - try:
|
| - return ESCAPE_DCT[s]
|
| - except KeyError:
|
| - n = ord(s)
|
| - if n < 0x10000:
|
| - #return '\\u{0:04x}'.format(n)
|
| - return '\\u%04x' % (n,)
|
| - else:
|
| - # surrogate pair
|
| - n -= 0x10000
|
| - s1 = 0xd800 | ((n >> 10) & 0x3ff)
|
| - s2 = 0xdc00 | (n & 0x3ff)
|
| - #return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
|
| - return '\\u%04x\\u%04x' % (s1, s2)
|
| - return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
|
| -
|
| -
|
| -encode_basestring_ascii = (
|
| - c_encode_basestring_ascii or py_encode_basestring_ascii)
|
| -
|
| -class JSONEncoder(object):
|
| - """Extensible JSON <http://json.org> encoder for Python data structures.
|
| -
|
| - Supports the following objects and types by default:
|
| -
|
| - +-------------------+---------------+
|
| - | Python | JSON |
|
| - +===================+===============+
|
| - | dict | object |
|
| - +-------------------+---------------+
|
| - | list, tuple | array |
|
| - +-------------------+---------------+
|
| - | str, unicode | string |
|
| - +-------------------+---------------+
|
| - | int, long, float | number |
|
| - +-------------------+---------------+
|
| - | True | true |
|
| - +-------------------+---------------+
|
| - | False | false |
|
| - +-------------------+---------------+
|
| - | None | null |
|
| - +-------------------+---------------+
|
| -
|
| - To extend this to recognize other objects, subclass and implement a
|
| - ``.default()`` method with another method that returns a serializable
|
| - object for ``o`` if possible, otherwise it should call the superclass
|
| - implementation (to raise ``TypeError``).
|
| -
|
| - """
|
| - item_separator = ', '
|
| - key_separator = ': '
|
| - def __init__(self, skipkeys=False, ensure_ascii=True,
|
| - check_circular=True, allow_nan=True, sort_keys=False,
|
| - indent=None, separators=None, encoding='utf-8', default=None,
|
| - use_decimal=False):
|
| - """Constructor for JSONEncoder, with sensible defaults.
|
| -
|
| - If skipkeys is false, then it is a TypeError to attempt
|
| - encoding of keys that are not str, int, long, float or None. If
|
| - skipkeys is True, such items are simply skipped.
|
| -
|
| - If ensure_ascii is true, the output is guaranteed to be str
|
| - objects with all incoming unicode characters escaped. If
|
| - ensure_ascii is false, the output will be unicode object.
|
| -
|
| - If check_circular is true, then lists, dicts, and custom encoded
|
| - objects will be checked for circular references during encoding to
|
| - prevent an infinite recursion (which would cause an OverflowError).
|
| - Otherwise, no such check takes place.
|
| -
|
| - If allow_nan is true, then NaN, Infinity, and -Infinity will be
|
| - encoded as such. This behavior is not JSON specification compliant,
|
| - but is consistent with most JavaScript based encoders and decoders.
|
| - Otherwise, it will be a ValueError to encode such floats.
|
| -
|
| - If sort_keys is true, 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 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
|
| - representation without any newlines. For backwards compatibility with
|
| - versions of simplejson earlier than 2.1.0, an integer is also accepted
|
| - and is converted to a string with that many spaces.
|
| -
|
| - 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.
|
| -
|
| - If specified, default is a function that gets called for objects
|
| - that can't otherwise be serialized. It should return a JSON encodable
|
| - version of the object or raise a ``TypeError``.
|
| -
|
| - If encoding is not None, then all input strings will be
|
| - transformed into unicode using that encoding prior to JSON-encoding.
|
| - The default is UTF-8.
|
| -
|
| - If use_decimal is true (not the default), ``decimal.Decimal`` will
|
| - be supported directly by the encoder. For the inverse, decode JSON
|
| - with ``parse_float=decimal.Decimal``.
|
| -
|
| - """
|
| -
|
| - self.skipkeys = skipkeys
|
| - self.ensure_ascii = ensure_ascii
|
| - self.check_circular = check_circular
|
| - self.allow_nan = allow_nan
|
| - self.sort_keys = sort_keys
|
| - self.use_decimal = use_decimal
|
| - if isinstance(indent, (int, long)):
|
| - indent = ' ' * indent
|
| - self.indent = indent
|
| - if separators is not None:
|
| - self.item_separator, self.key_separator = separators
|
| - if default is not None:
|
| - self.default = default
|
| - self.encoding = encoding
|
| -
|
| - def default(self, o):
|
| - """Implement this method in a subclass such that it returns
|
| - a serializable object for ``o``, or calls the base implementation
|
| - (to raise a ``TypeError``).
|
| -
|
| - For example, to support arbitrary iterators, you could
|
| - implement default like this::
|
| -
|
| - def default(self, o):
|
| - try:
|
| - iterable = iter(o)
|
| - except TypeError:
|
| - pass
|
| - else:
|
| - return list(iterable)
|
| - return JSONEncoder.default(self, o)
|
| -
|
| - """
|
| - raise TypeError(repr(o) + " is not JSON serializable")
|
| -
|
| - def encode(self, o):
|
| - """Return a JSON string representation of a Python data structure.
|
| -
|
| - >>> from simplejson import JSONEncoder
|
| - >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
|
| - '{"foo": ["bar", "baz"]}'
|
| -
|
| - """
|
| - # This is for extremely simple cases and benchmarks.
|
| - if isinstance(o, basestring):
|
| - if isinstance(o, str):
|
| - _encoding = self.encoding
|
| - if (_encoding is not None
|
| - and not (_encoding == 'utf-8')):
|
| - o = o.decode(_encoding)
|
| - if self.ensure_ascii:
|
| - return encode_basestring_ascii(o)
|
| - else:
|
| - return encode_basestring(o)
|
| - # This doesn't pass the iterator directly to ''.join() because the
|
| - # exceptions aren't as detailed. The list call should be roughly
|
| - # equivalent to the PySequence_Fast that ''.join() would do.
|
| - chunks = self.iterencode(o, _one_shot=True)
|
| - if not isinstance(chunks, (list, tuple)):
|
| - chunks = list(chunks)
|
| - if self.ensure_ascii:
|
| - return ''.join(chunks)
|
| - else:
|
| - return u''.join(chunks)
|
| -
|
| - def iterencode(self, o, _one_shot=False):
|
| - """Encode the given object and yield each string
|
| - representation as available.
|
| -
|
| - For example::
|
| -
|
| - for chunk in JSONEncoder().iterencode(bigobject):
|
| - mysocket.write(chunk)
|
| -
|
| - """
|
| - if self.check_circular:
|
| - markers = {}
|
| - else:
|
| - markers = None
|
| - if self.ensure_ascii:
|
| - _encoder = encode_basestring_ascii
|
| - else:
|
| - _encoder = encode_basestring
|
| - if self.encoding != 'utf-8':
|
| - def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
|
| - if isinstance(o, str):
|
| - o = o.decode(_encoding)
|
| - return _orig_encoder(o)
|
| -
|
| - def floatstr(o, allow_nan=self.allow_nan,
|
| - _repr=FLOAT_REPR, _inf=PosInf, _neginf=-PosInf):
|
| - # Check for specials. Note that this type of test is processor
|
| - # and/or platform-specific, so do tests which don't depend on
|
| - # the internals.
|
| -
|
| - if o != o:
|
| - text = 'NaN'
|
| - elif o == _inf:
|
| - text = 'Infinity'
|
| - elif o == _neginf:
|
| - text = '-Infinity'
|
| - else:
|
| - return _repr(o)
|
| -
|
| - if not allow_nan:
|
| - raise ValueError(
|
| - "Out of range float values are not JSON compliant: " +
|
| - repr(o))
|
| -
|
| - return text
|
| -
|
| -
|
| - key_memo = {}
|
| - if (_one_shot and c_make_encoder is not None
|
| - and self.indent is None and not self.sort_keys):
|
| - _iterencode = c_make_encoder(
|
| - markers, self.default, _encoder, self.indent,
|
| - self.key_separator, self.item_separator, self.sort_keys,
|
| - self.skipkeys, self.allow_nan, key_memo, self.use_decimal)
|
| - else:
|
| - _iterencode = _make_iterencode(
|
| - markers, self.default, _encoder, self.indent, floatstr,
|
| - self.key_separator, self.item_separator, self.sort_keys,
|
| - self.skipkeys, _one_shot, self.use_decimal)
|
| - try:
|
| - return _iterencode(o, 0)
|
| - finally:
|
| - key_memo.clear()
|
| -
|
| -
|
| -class JSONEncoderForHTML(JSONEncoder):
|
| - """An encoder that produces JSON safe to embed in HTML.
|
| -
|
| - To embed JSON content in, say, a script tag on a web page, the
|
| - characters &, < and > should be escaped. They cannot be escaped
|
| - with the usual entities (e.g. &) because they are not expanded
|
| - within <script> tags.
|
| - """
|
| -
|
| - def encode(self, o):
|
| - # Override JSONEncoder.encode because it has hacks for
|
| - # performance that make things more complicated.
|
| - chunks = self.iterencode(o, True)
|
| - if self.ensure_ascii:
|
| - return ''.join(chunks)
|
| - else:
|
| - return u''.join(chunks)
|
| -
|
| - def iterencode(self, o, _one_shot=False):
|
| - chunks = super(JSONEncoderForHTML, self).iterencode(o, _one_shot)
|
| - for chunk in chunks:
|
| - chunk = chunk.replace('&', '\\u0026')
|
| - chunk = chunk.replace('<', '\\u003c')
|
| - chunk = chunk.replace('>', '\\u003e')
|
| - yield chunk
|
| -
|
| -
|
| -def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
|
| - _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
|
| - _use_decimal,
|
| - ## HACK: hand-optimized bytecode; turn globals into locals
|
| - False=False,
|
| - True=True,
|
| - ValueError=ValueError,
|
| - basestring=basestring,
|
| - Decimal=Decimal,
|
| - dict=dict,
|
| - float=float,
|
| - id=id,
|
| - int=int,
|
| - isinstance=isinstance,
|
| - list=list,
|
| - long=long,
|
| - str=str,
|
| - tuple=tuple,
|
| - ):
|
| -
|
| - def _iterencode_list(lst, _current_indent_level):
|
| - if not lst:
|
| - yield '[]'
|
| - return
|
| - if markers is not None:
|
| - markerid = id(lst)
|
| - if markerid in markers:
|
| - raise ValueError("Circular reference detected")
|
| - markers[markerid] = lst
|
| - buf = '['
|
| - if _indent is not None:
|
| - _current_indent_level += 1
|
| - newline_indent = '\n' + (_indent * _current_indent_level)
|
| - separator = _item_separator + newline_indent
|
| - buf += newline_indent
|
| - else:
|
| - newline_indent = None
|
| - separator = _item_separator
|
| - first = True
|
| - for value in lst:
|
| - if first:
|
| - first = False
|
| - else:
|
| - buf = separator
|
| - if isinstance(value, basestring):
|
| - yield buf + _encoder(value)
|
| - elif value is None:
|
| - yield buf + 'null'
|
| - elif value is True:
|
| - yield buf + 'true'
|
| - elif value is False:
|
| - yield buf + 'false'
|
| - elif isinstance(value, (int, long)):
|
| - yield buf + str(value)
|
| - elif isinstance(value, float):
|
| - yield buf + _floatstr(value)
|
| - elif _use_decimal and isinstance(value, Decimal):
|
| - yield buf + str(value)
|
| - else:
|
| - yield buf
|
| - if isinstance(value, (list, tuple)):
|
| - chunks = _iterencode_list(value, _current_indent_level)
|
| - elif isinstance(value, dict):
|
| - chunks = _iterencode_dict(value, _current_indent_level)
|
| - else:
|
| - chunks = _iterencode(value, _current_indent_level)
|
| - for chunk in chunks:
|
| - yield chunk
|
| - if newline_indent is not None:
|
| - _current_indent_level -= 1
|
| - yield '\n' + (_indent * _current_indent_level)
|
| - yield ']'
|
| - if markers is not None:
|
| - del markers[markerid]
|
| -
|
| - def _iterencode_dict(dct, _current_indent_level):
|
| - if not dct:
|
| - yield '{}'
|
| - return
|
| - if markers is not None:
|
| - markerid = id(dct)
|
| - if markerid in markers:
|
| - raise ValueError("Circular reference detected")
|
| - markers[markerid] = dct
|
| - yield '{'
|
| - if _indent is not None:
|
| - _current_indent_level += 1
|
| - newline_indent = '\n' + (_indent * _current_indent_level)
|
| - item_separator = _item_separator + newline_indent
|
| - yield newline_indent
|
| - else:
|
| - newline_indent = None
|
| - item_separator = _item_separator
|
| - first = True
|
| - if _sort_keys:
|
| - items = dct.items()
|
| - items.sort(key=lambda kv: kv[0])
|
| - else:
|
| - items = dct.iteritems()
|
| - for key, value in items:
|
| - if isinstance(key, basestring):
|
| - pass
|
| - # JavaScript is weakly typed for these, so it makes sense to
|
| - # also allow them. Many encoders seem to do something like this.
|
| - elif isinstance(key, float):
|
| - key = _floatstr(key)
|
| - elif key is True:
|
| - key = 'true'
|
| - elif key is False:
|
| - key = 'false'
|
| - elif key is None:
|
| - key = 'null'
|
| - elif isinstance(key, (int, long)):
|
| - key = str(key)
|
| - elif _skipkeys:
|
| - continue
|
| - else:
|
| - raise TypeError("key " + repr(key) + " is not a string")
|
| - if first:
|
| - first = False
|
| - else:
|
| - yield item_separator
|
| - yield _encoder(key)
|
| - yield _key_separator
|
| - if isinstance(value, basestring):
|
| - yield _encoder(value)
|
| - elif value is None:
|
| - yield 'null'
|
| - elif value is True:
|
| - yield 'true'
|
| - elif value is False:
|
| - yield 'false'
|
| - elif isinstance(value, (int, long)):
|
| - yield str(value)
|
| - elif isinstance(value, float):
|
| - yield _floatstr(value)
|
| - elif _use_decimal and isinstance(value, Decimal):
|
| - yield str(value)
|
| - else:
|
| - if isinstance(value, (list, tuple)):
|
| - chunks = _iterencode_list(value, _current_indent_level)
|
| - elif isinstance(value, dict):
|
| - chunks = _iterencode_dict(value, _current_indent_level)
|
| - else:
|
| - chunks = _iterencode(value, _current_indent_level)
|
| - for chunk in chunks:
|
| - yield chunk
|
| - if newline_indent is not None:
|
| - _current_indent_level -= 1
|
| - yield '\n' + (_indent * _current_indent_level)
|
| - yield '}'
|
| - if markers is not None:
|
| - del markers[markerid]
|
| -
|
| - def _iterencode(o, _current_indent_level):
|
| - if isinstance(o, basestring):
|
| - yield _encoder(o)
|
| - elif o is None:
|
| - yield 'null'
|
| - elif o is True:
|
| - yield 'true'
|
| - elif o is False:
|
| - yield 'false'
|
| - elif isinstance(o, (int, long)):
|
| - yield str(o)
|
| - elif isinstance(o, float):
|
| - yield _floatstr(o)
|
| - elif isinstance(o, (list, tuple)):
|
| - for chunk in _iterencode_list(o, _current_indent_level):
|
| - yield chunk
|
| - elif isinstance(o, dict):
|
| - for chunk in _iterencode_dict(o, _current_indent_level):
|
| - yield chunk
|
| - elif _use_decimal and isinstance(o, Decimal):
|
| - yield str(o)
|
| - else:
|
| - if markers is not None:
|
| - markerid = id(o)
|
| - if markerid in markers:
|
| - raise ValueError("Circular reference detected")
|
| - markers[markerid] = o
|
| - o = _default(o)
|
| - for chunk in _iterencode(o, _current_indent_level):
|
| - yield chunk
|
| - if markers is not None:
|
| - del markers[markerid]
|
| -
|
| - return _iterencode
|
|
|