Skip to content
This repository
Browse code

addons: add simplejson to default install

It's needed for wunderground.
(cherry picked from commit 3617309)
  • Loading branch information...
commit 22ad8e4ddf844bb82fa2c467818d2d797ca36707 1 parent 6ce836a
authored December 22, 2011
14  addons/script.module.simplejson/addon.xml
... ...
@@ -0,0 +1,14 @@
  1
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2
+<addon id="script.module.simplejson"
  3
+       name="simplejson"
  4
+       version="2.0.10" 
  5
+       provider-name="code.google.com/simplejson">
  6
+  <requires>
  7
+    <import addon="xbmc.python" version="2.0"/>
  8
+  </requires>
  9
+  <extension point="xbmc.python.module"
  10
+             library="lib" />
  11
+  <extension point="xbmc.addon.metadata">
  12
+    <platform>all</platform>
  13
+  </extension>
  14
+</addon>
19  addons/script.module.simplejson/lib/LICENSE.txt
... ...
@@ -0,0 +1,19 @@
  1
+Copyright (c) 2006 Bob Ippolito
  2
+
  3
+Permission is hereby granted, free of charge, to any person obtaining a copy of
  4
+this software and associated documentation files (the "Software"), to deal in
  5
+the Software without restriction, including without limitation the rights to
  6
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  7
+of the Software, and to permit persons to whom the Software is furnished to do
  8
+so, subject to the following conditions:
  9
+
  10
+The above copyright notice and this permission notice shall be included in all
  11
+copies or substantial portions of the Software.
  12
+
  13
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19
+SOFTWARE.
318  addons/script.module.simplejson/lib/simplejson/__init__.py
... ...
@@ -0,0 +1,318 @@
  1
+r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of
  2
+JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
  3
+interchange format.
  4
+
  5
+:mod:`simplejson` exposes an API familiar to users of the standard library
  6
+:mod:`marshal` and :mod:`pickle` modules. It is the externally maintained
  7
+version of the :mod:`json` library contained in Python 2.6, but maintains
  8
+compatibility with Python 2.4 and Python 2.5 and (currently) has
  9
+significant performance advantages, even without using the optional C
  10
+extension for speedups.
  11
+
  12
+Encoding basic Python object hierarchies::
  13
+
  14
+    >>> import simplejson as json
  15
+    >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
  16
+    '["foo", {"bar": ["baz", null, 1.0, 2]}]'
  17
+    >>> print json.dumps("\"foo\bar")
  18
+    "\"foo\bar"
  19
+    >>> print json.dumps(u'\u1234')
  20
+    "\u1234"
  21
+    >>> print json.dumps('\\')
  22
+    "\\"
  23
+    >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
  24
+    {"a": 0, "b": 0, "c": 0}
  25
+    >>> from StringIO import StringIO
  26
+    >>> io = StringIO()
  27
+    >>> json.dump(['streaming API'], io)
  28
+    >>> io.getvalue()
  29
+    '["streaming API"]'
  30
+
  31
+Compact encoding::
  32
+
  33
+    >>> import simplejson as json
  34
+    >>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
  35
+    '[1,2,3,{"4":5,"6":7}]'
  36
+
  37
+Pretty printing::
  38
+
  39
+    >>> import simplejson as json
  40
+    >>> s = json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
  41
+    >>> print '\n'.join([l.rstrip() for l in  s.splitlines()])
  42
+    {
  43
+        "4": 5,
  44
+        "6": 7
  45
+    }
  46
+
  47
+Decoding JSON::
  48
+
  49
+    >>> import simplejson as json
  50
+    >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
  51
+    >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj
  52
+    True
  53
+    >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar'
  54
+    True
  55
+    >>> from StringIO import StringIO
  56
+    >>> io = StringIO('["streaming API"]')
  57
+    >>> json.load(io)[0] == 'streaming API'
  58
+    True
  59
+
  60
+Specializing JSON object decoding::
  61
+
  62
+    >>> import simplejson as json
  63
+    >>> def as_complex(dct):
  64
+    ...     if '__complex__' in dct:
  65
+    ...         return complex(dct['real'], dct['imag'])
  66
+    ...     return dct
  67
+    ...
  68
+    >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
  69
+    ...     object_hook=as_complex)
  70
+    (1+2j)
  71
+    >>> import decimal
  72
+    >>> json.loads('1.1', parse_float=decimal.Decimal) == decimal.Decimal('1.1')
  73
+    True
  74
+
  75
+Specializing JSON object encoding::
  76
+
  77
+    >>> import simplejson as json
  78
+    >>> def encode_complex(obj):
  79
+    ...     if isinstance(obj, complex):
  80
+    ...         return [obj.real, obj.imag]
  81
+    ...     raise TypeError(repr(o) + " is not JSON serializable")
  82
+    ...
  83
+    >>> json.dumps(2 + 1j, default=encode_complex)
  84
+    '[2.0, 1.0]'
  85
+    >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
  86
+    '[2.0, 1.0]'
  87
+    >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
  88
+    '[2.0, 1.0]'
  89
+
  90
+
  91
+Using simplejson.tool from the shell to validate and pretty-print::
  92
+
  93
+    $ echo '{"json":"obj"}' | python -m simplejson.tool
  94
+    {
  95
+        "json": "obj"
  96
+    }
  97
+    $ echo '{ 1.2:3.4}' | python -m simplejson.tool
  98
+    Expecting property name: line 1 column 2 (char 2)
  99
+"""
  100
+__version__ = '2.0.9'
  101
+__all__ = [
  102
+    'dump', 'dumps', 'load', 'loads',
  103
+    'JSONDecoder', 'JSONEncoder',
  104
+]
  105
+
  106
+__author__ = 'Bob Ippolito <bob@redivi.com>'
  107
+
  108
+from decoder import JSONDecoder
  109
+from encoder import JSONEncoder
  110
+
  111
+_default_encoder = JSONEncoder(
  112
+    skipkeys=False,
  113
+    ensure_ascii=True,
  114
+    check_circular=True,
  115
+    allow_nan=True,
  116
+    indent=None,
  117
+    separators=None,
  118
+    encoding='utf-8',
  119
+    default=None,
  120
+)
  121
+
  122
+def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
  123
+        allow_nan=True, cls=None, indent=None, separators=None,
  124
+        encoding='utf-8', default=None, **kw):
  125
+    """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
  126
+    ``.write()``-supporting file-like object).
  127
+
  128
+    If ``skipkeys`` is true then ``dict`` keys that are not basic types
  129
+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
  130
+    will be skipped instead of raising a ``TypeError``.
  131
+
  132
+    If ``ensure_ascii`` is false, then the some chunks written to ``fp``
  133
+    may be ``unicode`` instances, subject to normal Python ``str`` to
  134
+    ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
  135
+    understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
  136
+    to cause an error.
  137
+
  138
+    If ``check_circular`` is false, then the circular reference check
  139
+    for container types will be skipped and a circular reference will
  140
+    result in an ``OverflowError`` (or worse).
  141
+
  142
+    If ``allow_nan`` is false, then it will be a ``ValueError`` to
  143
+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
  144
+    in strict compliance of the JSON specification, instead of using the
  145
+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
  146
+
  147
+    If ``indent`` is a non-negative integer, then JSON array elements and object
  148
+    members will be pretty-printed with that indent level. An indent level
  149
+    of 0 will only insert newlines. ``None`` is the most compact representation.
  150
+
  151
+    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
  152
+    then it will be used instead of the default ``(', ', ': ')`` separators.
  153
+    ``(',', ':')`` is the most compact JSON representation.
  154
+
  155
+    ``encoding`` is the character encoding for str instances, default is UTF-8.
  156
+
  157
+    ``default(obj)`` is a function that should return a serializable version
  158
+    of obj or raise TypeError. The default simply raises TypeError.
  159
+
  160
+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
  161
+    ``.default()`` method to serialize additional types), specify it with
  162
+    the ``cls`` kwarg.
  163
+
  164
+    """
  165
+    # cached encoder
  166
+    if (not skipkeys and ensure_ascii and
  167
+        check_circular and allow_nan and
  168
+        cls is None and indent is None and separators is None and
  169
+        encoding == 'utf-8' and default is None and not kw):
  170
+        iterable = _default_encoder.iterencode(obj)
  171
+    else:
  172
+        if cls is None:
  173
+            cls = JSONEncoder
  174
+        iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
  175
+            check_circular=check_circular, allow_nan=allow_nan, indent=indent,
  176
+            separators=separators, encoding=encoding,
  177
+            default=default, **kw).iterencode(obj)
  178
+    # could accelerate with writelines in some versions of Python, at
  179
+    # a debuggability cost
  180
+    for chunk in iterable:
  181
+        fp.write(chunk)
  182
+
  183
+
  184
+def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
  185
+        allow_nan=True, cls=None, indent=None, separators=None,
  186
+        encoding='utf-8', default=None, **kw):
  187
+    """Serialize ``obj`` to a JSON formatted ``str``.
  188
+
  189
+    If ``skipkeys`` is false then ``dict`` keys that are not basic types
  190
+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
  191
+    will be skipped instead of raising a ``TypeError``.
  192
+
  193
+    If ``ensure_ascii`` is false, then the return value will be a
  194
+    ``unicode`` instance subject to normal Python ``str`` to ``unicode``
  195
+    coercion rules instead of being escaped to an ASCII ``str``.
  196
+
  197
+    If ``check_circular`` is false, then the circular reference check
  198
+    for container types will be skipped and a circular reference will
  199
+    result in an ``OverflowError`` (or worse).
  200
+
  201
+    If ``allow_nan`` is false, then it will be a ``ValueError`` to
  202
+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
  203
+    strict compliance of the JSON specification, instead of using the
  204
+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
  205
+
  206
+    If ``indent`` is a non-negative integer, then JSON array elements and
  207
+    object members will be pretty-printed with that indent level. An indent
  208
+    level of 0 will only insert newlines. ``None`` is the most compact
  209
+    representation.
  210
+
  211
+    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
  212
+    then it will be used instead of the default ``(', ', ': ')`` separators.
  213
+    ``(',', ':')`` is the most compact JSON representation.
  214
+
  215
+    ``encoding`` is the character encoding for str instances, default is UTF-8.
  216
+
  217
+    ``default(obj)`` is a function that should return a serializable version
  218
+    of obj or raise TypeError. The default simply raises TypeError.
  219
+
  220
+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
  221
+    ``.default()`` method to serialize additional types), specify it with
  222
+    the ``cls`` kwarg.
  223
+
  224
+    """
  225
+    # cached encoder
  226
+    if (not skipkeys and ensure_ascii and
  227
+        check_circular and allow_nan and
  228
+        cls is None and indent is None and separators is None and
  229
+        encoding == 'utf-8' and default is None and not kw):
  230
+        return _default_encoder.encode(obj)
  231
+    if cls is None:
  232
+        cls = JSONEncoder
  233
+    return cls(
  234
+        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
  235
+        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
  236
+        separators=separators, encoding=encoding, default=default,
  237
+        **kw).encode(obj)
  238
+
  239
+
  240
+_default_decoder = JSONDecoder(encoding=None, object_hook=None)
  241
+
  242
+
  243
+def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
  244
+        parse_int=None, parse_constant=None, **kw):
  245
+    """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
  246
+    a JSON document) to a Python object.
  247
+
  248
+    If the contents of ``fp`` is encoded with an ASCII based encoding other
  249
+    than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
  250
+    be specified. Encodings that are not ASCII based (such as UCS-2) are
  251
+    not allowed, and should be wrapped with
  252
+    ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
  253
+    object and passed to ``loads()``
  254
+
  255
+    ``object_hook`` is an optional function that will be called with the
  256
+    result of any object literal decode (a ``dict``). The return value of
  257
+    ``object_hook`` will be used instead of the ``dict``. This feature
  258
+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
  259
+
  260
+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
  261
+    kwarg.
  262
+
  263
+    """
  264
+    return loads(fp.read(),
  265
+        encoding=encoding, cls=cls, object_hook=object_hook,
  266
+        parse_float=parse_float, parse_int=parse_int,
  267
+        parse_constant=parse_constant, **kw)
  268
+
  269
+
  270
+def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
  271
+        parse_int=None, parse_constant=None, **kw):
  272
+    """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
  273
+    document) to a Python object.
  274
+
  275
+    If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
  276
+    other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
  277
+    must be specified. Encodings that are not ASCII based (such as UCS-2)
  278
+    are not allowed and should be decoded to ``unicode`` first.
  279
+
  280
+    ``object_hook`` is an optional function that will be called with the
  281
+    result of any object literal decode (a ``dict``). The return value of
  282
+    ``object_hook`` will be used instead of the ``dict``. This feature
  283
+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
  284
+
  285
+    ``parse_float``, if specified, will be called with the string
  286
+    of every JSON float to be decoded. By default this is equivalent to
  287
+    float(num_str). This can be used to use another datatype or parser
  288
+    for JSON floats (e.g. decimal.Decimal).
  289
+
  290
+    ``parse_int``, if specified, will be called with the string
  291
+    of every JSON int to be decoded. By default this is equivalent to
  292
+    int(num_str). This can be used to use another datatype or parser
  293
+    for JSON integers (e.g. float).
  294
+
  295
+    ``parse_constant``, if specified, will be called with one of the
  296
+    following strings: -Infinity, Infinity, NaN, null, true, false.
  297
+    This can be used to raise an exception if invalid JSON numbers
  298
+    are encountered.
  299
+
  300
+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
  301
+    kwarg.
  302
+
  303
+    """
  304
+    if (cls is None and encoding is None and object_hook is None and
  305
+            parse_int is None and parse_float is None and
  306
+            parse_constant is None and not kw):
  307
+        return _default_decoder.decode(s)
  308
+    if cls is None:
  309
+        cls = JSONDecoder
  310
+    if object_hook is not None:
  311
+        kw['object_hook'] = object_hook
  312
+    if parse_float is not None:
  313
+        kw['parse_float'] = parse_float
  314
+    if parse_int is not None:
  315
+        kw['parse_int'] = parse_int
  316
+    if parse_constant is not None:
  317
+        kw['parse_constant'] = parse_constant
  318
+    return cls(encoding=encoding, **kw).decode(s)
354  addons/script.module.simplejson/lib/simplejson/decoder.py
... ...
@@ -0,0 +1,354 @@
  1
+"""Implementation of JSONDecoder
  2
+"""
  3
+import re
  4
+import sys
  5
+import struct
  6
+
  7
+from simplejson.scanner import make_scanner
  8
+try:
  9
+    from simplejson._speedups import scanstring as c_scanstring
  10
+except ImportError:
  11
+    c_scanstring = None
  12
+
  13
+__all__ = ['JSONDecoder']
  14
+
  15
+FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
  16
+
  17
+def _floatconstants():
  18
+    _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
  19
+    if sys.byteorder != 'big':
  20
+        _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
  21
+    nan, inf = struct.unpack('dd', _BYTES)
  22
+    return nan, inf, -inf
  23
+
  24
+NaN, PosInf, NegInf = _floatconstants()
  25
+
  26
+
  27
+def linecol(doc, pos):
  28
+    lineno = doc.count('\n', 0, pos) + 1
  29
+    if lineno == 1:
  30
+        colno = pos
  31
+    else:
  32
+        colno = pos - doc.rindex('\n', 0, pos)
  33
+    return lineno, colno
  34
+
  35
+
  36
+def errmsg(msg, doc, pos, end=None):
  37
+    # Note that this function is called from _speedups
  38
+    lineno, colno = linecol(doc, pos)
  39
+    if end is None:
  40
+        #fmt = '{0}: line {1} column {2} (char {3})'
  41
+        #return fmt.format(msg, lineno, colno, pos)
  42
+        fmt = '%s: line %d column %d (char %d)'
  43
+        return fmt % (msg, lineno, colno, pos)
  44
+    endlineno, endcolno = linecol(doc, end)
  45
+    #fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})'
  46
+    #return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end)
  47
+    fmt = '%s: line %d column %d - line %d column %d (char %d - %d)'
  48
+    return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end)
  49
+
  50
+
  51
+_CONSTANTS = {
  52
+    '-Infinity': NegInf,
  53
+    'Infinity': PosInf,
  54
+    'NaN': NaN,
  55
+}
  56
+
  57
+STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
  58
+BACKSLASH = {
  59
+    '"': u'"', '\\': u'\\', '/': u'/',
  60
+    'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
  61
+}
  62
+
  63
+DEFAULT_ENCODING = "utf-8"
  64
+
  65
+def py_scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match):
  66
+    """Scan the string s for a JSON string. End is the index of the
  67
+    character in s after the quote that started the JSON string.
  68
+    Unescapes all valid JSON string escape sequences and raises ValueError
  69
+    on attempt to decode an invalid string. If strict is False then literal
  70
+    control characters are allowed in the string.
  71
+    
  72
+    Returns a tuple of the decoded string and the index of the character in s
  73
+    after the end quote."""
  74
+    if encoding is None:
  75
+        encoding = DEFAULT_ENCODING
  76
+    chunks = []
  77
+    _append = chunks.append
  78
+    begin = end - 1
  79
+    while 1:
  80
+        chunk = _m(s, end)
  81
+        if chunk is None:
  82
+            raise ValueError(
  83
+                errmsg("Unterminated string starting at", s, begin))
  84
+        end = chunk.end()
  85
+        content, terminator = chunk.groups()
  86
+        # Content is contains zero or more unescaped string characters
  87
+        if content:
  88
+            if not isinstance(content, unicode):
  89
+                content = unicode(content, encoding)
  90
+            _append(content)
  91
+        # Terminator is the end of string, a literal control character,
  92
+        # or a backslash denoting that an escape sequence follows
  93
+        if terminator == '"':
  94
+            break
  95
+        elif terminator != '\\':
  96
+            if strict:
  97
+                msg = "Invalid control character %r at" % (terminator,)
  98
+                #msg = "Invalid control character {0!r} at".format(terminator)
  99
+                raise ValueError(errmsg(msg, s, end))
  100
+            else:
  101
+                _append(terminator)
  102
+                continue
  103
+        try:
  104
+            esc = s[end]
  105
+        except IndexError:
  106
+            raise ValueError(
  107
+                errmsg("Unterminated string starting at", s, begin))
  108
+        # If not a unicode escape sequence, must be in the lookup table
  109
+        if esc != 'u':
  110
+            try:
  111
+                char = _b[esc]
  112
+            except KeyError:
  113
+                msg = "Invalid \\escape: " + repr(esc)
  114
+                raise ValueError(errmsg(msg, s, end))
  115
+            end += 1
  116
+        else:
  117
+            # Unicode escape sequence
  118
+            esc = s[end + 1:end + 5]
  119
+            next_end = end + 5
  120
+            if len(esc) != 4:
  121
+                msg = "Invalid \\uXXXX escape"
  122
+                raise ValueError(errmsg(msg, s, end))
  123
+            uni = int(esc, 16)
  124
+            # Check for surrogate pair on UCS-4 systems
  125
+            if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535:
  126
+                msg = "Invalid \\uXXXX\\uXXXX surrogate pair"
  127
+                if not s[end + 5:end + 7] == '\\u':
  128
+                    raise ValueError(errmsg(msg, s, end))
  129
+                esc2 = s[end + 7:end + 11]
  130
+                if len(esc2) != 4:
  131
+                    raise ValueError(errmsg(msg, s, end))
  132
+                uni2 = int(esc2, 16)
  133
+                uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
  134
+                next_end += 6
  135
+            char = unichr(uni)
  136
+            end = next_end
  137
+        # Append the unescaped character
  138
+        _append(char)
  139
+    return u''.join(chunks), end
  140
+
  141
+
  142
+# Use speedup if available
  143
+scanstring = c_scanstring or py_scanstring
  144
+
  145
+WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)
  146
+WHITESPACE_STR = ' \t\n\r'
  147
+
  148
+def JSONObject((s, end), encoding, strict, scan_once, object_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
  149
+    pairs = {}
  150
+    # Use a slice to prevent IndexError from being raised, the following
  151
+    # check will raise a more specific ValueError if the string is empty
  152
+    nextchar = s[end:end + 1]
  153
+    # Normally we expect nextchar == '"'
  154
+    if nextchar != '"':
  155
+        if nextchar in _ws:
  156
+            end = _w(s, end).end()
  157
+            nextchar = s[end:end + 1]
  158
+        # Trivial empty object
  159
+        if nextchar == '}':
  160
+            return pairs, end + 1
  161
+        elif nextchar != '"':
  162
+            raise ValueError(errmsg("Expecting property name", s, end))
  163
+    end += 1
  164
+    while True:
  165
+        key, end = scanstring(s, end, encoding, strict)
  166
+
  167
+        # To skip some function call overhead we optimize the fast paths where
  168
+        # the JSON key separator is ": " or just ":".
  169
+        if s[end:end + 1] != ':':
  170
+            end = _w(s, end).end()
  171
+            if s[end:end + 1] != ':':
  172
+                raise ValueError(errmsg("Expecting : delimiter", s, end))
  173
+
  174
+        end += 1
  175
+
  176
+        try:
  177
+            if s[end] in _ws:
  178
+                end += 1
  179
+                if s[end] in _ws:
  180
+                    end = _w(s, end + 1).end()
  181
+        except IndexError:
  182
+            pass
  183
+
  184
+        try:
  185
+            value, end = scan_once(s, end)
  186
+        except StopIteration:
  187
+            raise ValueError(errmsg("Expecting object", s, end))
  188
+        pairs[key] = value
  189
+
  190
+        try:
  191
+            nextchar = s[end]
  192
+            if nextchar in _ws:
  193
+                end = _w(s, end + 1).end()
  194
+                nextchar = s[end]
  195
+        except IndexError:
  196
+            nextchar = ''
  197
+        end += 1
  198
+
  199
+        if nextchar == '}':
  200
+            break
  201
+        elif nextchar != ',':
  202
+            raise ValueError(errmsg("Expecting , delimiter", s, end - 1))
  203
+
  204
+        try:
  205
+            nextchar = s[end]
  206
+            if nextchar in _ws:
  207
+                end += 1
  208
+                nextchar = s[end]
  209
+                if nextchar in _ws:
  210
+                    end = _w(s, end + 1).end()
  211
+                    nextchar = s[end]
  212
+        except IndexError:
  213
+            nextchar = ''
  214
+
  215
+        end += 1
  216
+        if nextchar != '"':
  217
+            raise ValueError(errmsg("Expecting property name", s, end - 1))
  218
+
  219
+    if object_hook is not None:
  220
+        pairs = object_hook(pairs)
  221
+    return pairs, end
  222
+
  223
+def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
  224
+    values = []
  225
+    nextchar = s[end:end + 1]
  226
+    if nextchar in _ws:
  227
+        end = _w(s, end + 1).end()
  228
+        nextchar = s[end:end + 1]
  229
+    # Look-ahead for trivial empty array
  230
+    if nextchar == ']':
  231
+        return values, end + 1
  232
+    _append = values.append
  233
+    while True:
  234
+        try:
  235
+            value, end = scan_once(s, end)
  236
+        except StopIteration:
  237
+            raise ValueError(errmsg("Expecting object", s, end))
  238
+        _append(value)
  239
+        nextchar = s[end:end + 1]
  240
+        if nextchar in _ws:
  241
+            end = _w(s, end + 1).end()
  242
+            nextchar = s[end:end + 1]
  243
+        end += 1
  244
+        if nextchar == ']':
  245
+            break
  246
+        elif nextchar != ',':
  247
+            raise ValueError(errmsg("Expecting , delimiter", s, end))
  248
+
  249
+        try:
  250
+            if s[end] in _ws:
  251
+                end += 1
  252
+                if s[end] in _ws:
  253
+                    end = _w(s, end + 1).end()
  254
+        except IndexError:
  255
+            pass
  256
+
  257
+    return values, end
  258
+
  259
+class JSONDecoder(object):
  260
+    """Simple JSON <http://json.org> decoder
  261
+
  262
+    Performs the following translations in decoding by default:
  263
+
  264
+    +---------------+-------------------+
  265
+    | JSON          | Python            |
  266
+    +===============+===================+
  267
+    | object        | dict              |
  268
+    +---------------+-------------------+
  269
+    | array         | list              |
  270
+    +---------------+-------------------+
  271
+    | string        | unicode           |
  272
+    +---------------+-------------------+
  273
+    | number (int)  | int, long         |
  274
+    +---------------+-------------------+
  275
+    | number (real) | float             |
  276
+    +---------------+-------------------+
  277
+    | true          | True              |
  278
+    +---------------+-------------------+
  279
+    | false         | False             |
  280
+    +---------------+-------------------+
  281
+    | null          | None              |
  282
+    +---------------+-------------------+
  283
+
  284
+    It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
  285
+    their corresponding ``float`` values, which is outside the JSON spec.
  286
+
  287
+    """
  288
+
  289
+    def __init__(self, encoding=None, object_hook=None, parse_float=None,
  290
+            parse_int=None, parse_constant=None, strict=True):
  291
+        """``encoding`` determines the encoding used to interpret any ``str``
  292
+        objects decoded by this instance (utf-8 by default).  It has no
  293
+        effect when decoding ``unicode`` objects.
  294
+
  295
+        Note that currently only encodings that are a superset of ASCII work,
  296
+        strings of other encodings should be passed in as ``unicode``.
  297
+
  298
+        ``object_hook``, if specified, will be called with the result
  299
+        of every JSON object decoded and its return value will be used in
  300
+        place of the given ``dict``.  This can be used to provide custom
  301
+        deserializations (e.g. to support JSON-RPC class hinting).
  302
+
  303
+        ``parse_float``, if specified, will be called with the string
  304
+        of every JSON float to be decoded. By default this is equivalent to
  305
+        float(num_str). This can be used to use another datatype or parser
  306
+        for JSON floats (e.g. decimal.Decimal).
  307
+
  308
+        ``parse_int``, if specified, will be called with the string
  309
+        of every JSON int to be decoded. By default this is equivalent to
  310
+        int(num_str). This can be used to use another datatype or parser
  311
+        for JSON integers (e.g. float).
  312
+
  313
+        ``parse_constant``, if specified, will be called with one of the
  314
+        following strings: -Infinity, Infinity, NaN.
  315
+        This can be used to raise an exception if invalid JSON numbers
  316
+        are encountered.
  317
+
  318
+        """
  319
+        self.encoding = encoding
  320
+        self.object_hook = object_hook
  321
+        self.parse_float = parse_float or float
  322
+        self.parse_int = parse_int or int
  323
+        self.parse_constant = parse_constant or _CONSTANTS.__getitem__
  324
+        self.strict = strict
  325
+        self.parse_object = JSONObject
  326
+        self.parse_array = JSONArray
  327
+        self.parse_string = scanstring
  328
+        self.scan_once = make_scanner(self)
  329
+
  330
+    def decode(self, s, _w=WHITESPACE.match):
  331
+        """Return the Python representation of ``s`` (a ``str`` or ``unicode``
  332
+        instance containing a JSON document)
  333
+
  334
+        """
  335
+        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  336
+        end = _w(s, end).end()
  337
+        if end != len(s):
  338
+            raise ValueError(errmsg("Extra data", s, end, len(s)))
  339
+        return obj
  340
+
  341
+    def raw_decode(self, s, idx=0):
  342
+        """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
  343
+        with a JSON document) and return a 2-tuple of the Python
  344
+        representation and the index in ``s`` where the document ended.
  345
+
  346
+        This can be used to decode a JSON document from a string that may
  347
+        have extraneous data at the end.
  348
+
  349
+        """
  350
+        try:
  351
+            obj, end = self.scan_once(s, idx)
  352
+        except StopIteration:
  353
+            raise ValueError("No JSON object could be decoded")
  354
+        return obj, end
440  addons/script.module.simplejson/lib/simplejson/encoder.py
... ...
@@ -0,0 +1,440 @@
  1
+"""Implementation of JSONEncoder
  2
+"""
  3
+import re
  4
+
  5
+try:
  6
+    from simplejson._speedups import encode_basestring_ascii as c_encode_basestring_ascii
  7
+except ImportError:
  8
+    c_encode_basestring_ascii = None
  9
+try:
  10
+    from simplejson._speedups import make_encoder as c_make_encoder
  11
+except ImportError:
  12
+    c_make_encoder = None
  13
+
  14
+ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
  15
+ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
  16
+HAS_UTF8 = re.compile(r'[\x80-\xff]')
  17
+ESCAPE_DCT = {
  18
+    '\\': '\\\\',
  19
+    '"': '\\"',
  20
+    '\b': '\\b',
  21
+    '\f': '\\f',
  22
+    '\n': '\\n',
  23
+    '\r': '\\r',
  24
+    '\t': '\\t',
  25
+}
  26
+for i in range(0x20):
  27
+    #ESCAPE_DCT.setdefault(chr(i), '\\u{0:04x}'.format(i))
  28
+    ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
  29
+
  30
+# Assume this produces an infinity on all machines (probably not guaranteed)
  31
+INFINITY = float('1e66666')
  32
+FLOAT_REPR = repr
  33
+
  34
+def encode_basestring(s):
  35
+    """Return a JSON representation of a Python string
  36
+
  37
+    """
  38
+    def replace(match):
  39
+        return ESCAPE_DCT[match.group(0)]
  40
+    return '"' + ESCAPE.sub(replace, s) + '"'
  41
+
  42
+
  43
+def py_encode_basestring_ascii(s):
  44
+    """Return an ASCII-only JSON representation of a Python string
  45
+
  46
+    """
  47
+    if isinstance(s, str) and HAS_UTF8.search(s) is not None:
  48
+        s = s.decode('utf-8')
  49
+    def replace(match):
  50
+        s = match.group(0)
  51
+        try:
  52
+            return ESCAPE_DCT[s]
  53
+        except KeyError:
  54
+            n = ord(s)
  55
+            if n < 0x10000:
  56
+                #return '\\u{0:04x}'.format(n)
  57
+                return '\\u%04x' % (n,)
  58
+            else:
  59
+                # surrogate pair
  60
+                n -= 0x10000
  61
+                s1 = 0xd800 | ((n >> 10) & 0x3ff)
  62
+                s2 = 0xdc00 | (n & 0x3ff)
  63
+                #return '\\u{0:04x}\\u{1:04x}'.format(s1, s2)
  64
+                return '\\u%04x\\u%04x' % (s1, s2)
  65
+    return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
  66
+
  67
+
  68
+encode_basestring_ascii = c_encode_basestring_ascii or py_encode_basestring_ascii
  69
+
  70
+class JSONEncoder(object):
  71
+    """Extensible JSON <http://json.org> encoder for Python data structures.
  72
+
  73
+    Supports the following objects and types by default:
  74
+
  75
+    +-------------------+---------------+
  76
+    | Python            | JSON          |
  77
+    +===================+===============+
  78
+    | dict              | object        |
  79
+    +-------------------+---------------+
  80
+    | list, tuple       | array         |
  81
+    +-------------------+---------------+
  82
+    | str, unicode      | string        |
  83
+    +-------------------+---------------+
  84
+    | int, long, float  | number        |
  85
+    +-------------------+---------------+
  86
+    | True              | true          |
  87
+    +-------------------+---------------+
  88
+    | False             | false         |
  89
+    +-------------------+---------------+
  90
+    | None              | null          |
  91
+    +-------------------+---------------+
  92
+
  93
+    To extend this to recognize other objects, subclass and implement a
  94
+    ``.default()`` method with another method that returns a serializable
  95
+    object for ``o`` if possible, otherwise it should call the superclass
  96
+    implementation (to raise ``TypeError``).
  97
+
  98
+    """
  99
+    item_separator = ', '
  100
+    key_separator = ': '
  101
+    def __init__(self, skipkeys=False, ensure_ascii=True,
  102
+            check_circular=True, allow_nan=True, sort_keys=False,
  103
+            indent=None, separators=None, encoding='utf-8', default=None):
  104
+        """Constructor for JSONEncoder, with sensible defaults.
  105
+
  106
+        If skipkeys is false, then it is a TypeError to attempt
  107
+        encoding of keys that are not str, int, long, float or None.  If
  108
+        skipkeys is True, such items are simply skipped.
  109
+
  110
+        If ensure_ascii is true, the output is guaranteed to be str
  111
+        objects with all incoming unicode characters escaped.  If
  112
+        ensure_ascii is false, the output will be unicode object.
  113
+
  114
+        If check_circular is true, then lists, dicts, and custom encoded
  115
+        objects will be checked for circular references during encoding to
  116
+        prevent an infinite recursion (which would cause an OverflowError).
  117
+        Otherwise, no such check takes place.
  118
+
  119
+        If allow_nan is true, then NaN, Infinity, and -Infinity will be
  120
+        encoded as such.  This behavior is not JSON specification compliant,
  121
+        but is consistent with most JavaScript based encoders and decoders.
  122
+        Otherwise, it will be a ValueError to encode such floats.
  123
+
  124
+        If sort_keys is true, then the output of dictionaries will be
  125
+        sorted by key; this is useful for regression tests to ensure
  126
+        that JSON serializations can be compared on a day-to-day basis.
  127
+
  128
+        If indent is a non-negative integer, then JSON array
  129
+        elements and object members will be pretty-printed with that
  130
+        indent level.  An indent level of 0 will only insert newlines.
  131
+        None is the most compact representation.
  132
+
  133
+        If specified, separators should be a (item_separator, key_separator)
  134
+        tuple.  The default is (', ', ': ').  To get the most compact JSON
  135
+        representation you should specify (',', ':') to eliminate whitespace.
  136
+
  137
+        If specified, default is a function that gets called for objects
  138
+        that can't otherwise be serialized.  It should return a JSON encodable
  139
+        version of the object or raise a ``TypeError``.
  140
+
  141
+        If encoding is not None, then all input strings will be
  142
+        transformed into unicode using that encoding prior to JSON-encoding.
  143
+        The default is UTF-8.
  144
+
  145
+        """
  146
+
  147
+        self.skipkeys = skipkeys
  148
+        self.ensure_ascii = ensure_ascii
  149
+        self.check_circular = check_circular
  150
+        self.allow_nan = allow_nan
  151
+        self.sort_keys = sort_keys
  152
+        self.indent = indent
  153
+        if separators is not None:
  154
+            self.item_separator, self.key_separator = separators
  155
+        if default is not None:
  156
+            self.default = default
  157
+        self.encoding = encoding
  158
+
  159
+    def default(self, o):
  160
+        """Implement this method in a subclass such that it returns
  161
+        a serializable object for ``o``, or calls the base implementation
  162
+        (to raise a ``TypeError``).
  163
+
  164
+        For example, to support arbitrary iterators, you could
  165
+        implement default like this::
  166
+
  167
+            def default(self, o):
  168
+                try:
  169
+                    iterable = iter(o)
  170
+                except TypeError:
  171
+                    pass
  172
+                else:
  173
+                    return list(iterable)
  174
+                return JSONEncoder.default(self, o)
  175
+
  176
+        """
  177
+        raise TypeError(repr(o) + " is not JSON serializable")
  178
+
  179
+    def encode(self, o):
  180
+        """Return a JSON string representation of a Python data structure.
  181
+
  182
+        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
  183
+        '{"foo": ["bar", "baz"]}'
  184
+
  185
+        """
  186
+        # This is for extremely simple cases and benchmarks.
  187
+        if isinstance(o, basestring):
  188
+            if isinstance(o, str):
  189
+                _encoding = self.encoding
  190
+                if (_encoding is not None
  191
+                        and not (_encoding == 'utf-8')):
  192
+                    o = o.decode(_encoding)
  193
+            if self.ensure_ascii:
  194
+                return encode_basestring_ascii(o)
  195
+            else:
  196
+                return encode_basestring(o)
  197
+        # This doesn't pass the iterator directly to ''.join() because the
  198
+        # exceptions aren't as detailed.  The list call should be roughly
  199
+        # equivalent to the PySequence_Fast that ''.join() would do.
  200
+        chunks = self.iterencode(o, _one_shot=True)
  201
+        if not isinstance(chunks, (list, tuple)):
  202
+            chunks = list(chunks)
  203
+        return ''.join(chunks)
  204
+
  205
+    def iterencode(self, o, _one_shot=False):
  206
+        """Encode the given object and yield each string
  207
+        representation as available.
  208
+
  209
+        For example::
  210
+
  211
+            for chunk in JSONEncoder().iterencode(bigobject):
  212
+                mysocket.write(chunk)
  213
+
  214
+        """
  215
+        if self.check_circular:
  216
+            markers = {}
  217
+        else:
  218
+            markers = None
  219
+        if self.ensure_ascii:
  220
+            _encoder = encode_basestring_ascii
  221
+        else:
  222
+            _encoder = encode_basestring
  223
+        if self.encoding != 'utf-8':
  224
+            def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
  225
+                if isinstance(o, str):
  226
+                    o = o.decode(_encoding)
  227
+                return _orig_encoder(o)
  228
+
  229
+        def floatstr(o, allow_nan=self.allow_nan, _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY):
  230
+            # Check for specials.  Note that this type of test is processor- and/or
  231
+            # platform-specific, so do tests which don't depend on the internals.
  232
+
  233
+            if o != o:
  234
+                text = 'NaN'
  235
+            elif o == _inf:
  236
+                text = 'Infinity'
  237
+            elif o == _neginf:
  238
+                text = '-Infinity'
  239
+            else:
  240
+                return _repr(o)
  241
+
  242
+            if not allow_nan:
  243
+                raise ValueError(
  244
+                    "Out of range float values are not JSON compliant: " +
  245
+                    repr(o))
  246
+
  247
+            return text
  248
+
  249
+
  250
+        if _one_shot and c_make_encoder is not None and not self.indent and not self.sort_keys:
  251
+            _iterencode = c_make_encoder(
  252
+                markers, self.default, _encoder, self.indent,
  253
+                self.key_separator, self.item_separator, self.sort_keys,
  254
+                self.skipkeys, self.allow_nan)
  255
+        else:
  256
+            _iterencode = _make_iterencode(
  257
+                markers, self.default, _encoder, self.indent, floatstr,
  258
+                self.key_separator, self.item_separator, self.sort_keys,
  259
+                self.skipkeys, _one_shot)
  260
+        return _iterencode(o, 0)
  261
+
  262
+def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
  263
+        ## HACK: hand-optimized bytecode; turn globals into locals
  264
+        False=False,
  265
+        True=True,
  266
+        ValueError=ValueError,
  267
+        basestring=basestring,
  268
+        dict=dict,
  269
+        float=float,
  270
+        id=id,
  271
+        int=int,
  272
+        isinstance=isinstance,
  273
+        list=list,
  274
+        long=long,
  275
+        str=str,
  276
+        tuple=tuple,
  277
+    ):
  278
+
  279
+    def _iterencode_list(lst, _current_indent_level):
  280
+        if not lst:
  281
+            yield '[]'
  282
+            return
  283
+        if markers is not None:
  284
+            markerid = id(lst)
  285
+            if markerid in markers:
  286
+                raise ValueError("Circular reference detected")
  287
+            markers[markerid] = lst
  288
+        buf = '['
  289
+        if _indent is not None:
  290
+            _current_indent_level += 1
  291
+            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
  292
+            separator = _item_separator + newline_indent
  293
+            buf += newline_indent
  294
+        else:
  295
+            newline_indent = None
  296
+            separator = _item_separator
  297
+        first = True
  298
+        for value in lst:
  299
+            if first:
  300
+                first = False
  301
+            else:
  302
+                buf = separator
  303
+            if isinstance(value, basestring):
  304
+                yield buf + _encoder(value)
  305
+            elif value is None:
  306
+                yield buf + 'null'
  307
+            elif value is True:
  308
+                yield buf + 'true'
  309
+            elif value is False:
  310
+                yield buf + 'false'
  311
+            elif isinstance(value, (int, long)):
  312
+                yield buf + str(value)
  313
+            elif isinstance(value, float):
  314
+                yield buf + _floatstr(value)
  315
+            else:
  316
+                yield buf
  317
+                if isinstance(value, (list, tuple)):
  318
+                    chunks = _iterencode_list(value, _current_indent_level)
  319
+                elif isinstance(value, dict):
  320
+                    chunks = _iterencode_dict(value, _current_indent_level)
  321
+                else:
  322
+                    chunks = _iterencode(value, _current_indent_level)
  323
+                for chunk in chunks:
  324
+                    yield chunk
  325
+        if newline_indent is not None:
  326
+            _current_indent_level -= 1
  327
+            yield '\n' + (' ' * (_indent * _current_indent_level))
  328
+        yield ']'
  329
+        if markers is not None:
  330
+            del markers[markerid]
  331
+
  332
+    def _iterencode_dict(dct, _current_indent_level):
  333
+        if not dct:
  334
+            yield '{}'
  335
+            return
  336
+        if markers is not None:
  337
+            markerid = id(dct)
  338
+            if markerid in markers:
  339
+                raise ValueError("Circular reference detected")
  340
+            markers[markerid] = dct
  341
+        yield '{'
  342
+        if _indent is not None:
  343
+            _current_indent_level += 1
  344
+            newline_indent = '\n' + (' ' * (_indent * _current_indent_level))
  345
+            item_separator = _item_separator + newline_indent
  346
+            yield newline_indent
  347