Code

Ticket #3320: ticket-3320.diff

File ticket-3320.diff, 33.9 KB (added by mir@…, 7 years ago)

basically the same patches, but with full paths. Still doesn't work.

Line 
1--- a/django/utils/simplejson/LICENSE.txt
2+++ b/django/utils/simplejson/LICENSE.txt
3@@ -0,0 +1,19 @@
4+Copyright (c) 2006 Bob Ippolito
5+
6+Permission is hereby granted, free of charge, to any person obtaining a copy of
7+this software and associated documentation files (the "Software"), to deal in
8+the Software without restriction, including without limitation the rights to
9+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10+of the Software, and to permit persons to whom the Software is furnished to do
11+so, subject to the following conditions:
12+
13+The above copyright notice and this permission notice shall be included in all
14+copies or substantial portions of the Software.
15+
16+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+SOFTWARE.
23diff --git a/django/utils/simplejson/__init__.py b/django/utils/simplejson/__init__.py
24index f88329b..5c79ccf 100644
25--- a/django/utils/simplejson/__init__.py
26+++ b/django/utils/simplejson/__init__.py
27@@ -0,0 +1,252 @@
28+r"""
29+A simple, fast, extensible JSON encoder and decoder
30+
31+JSON (JavaScript Object Notation) <http://json.org> is a subset of
32+JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
33+interchange format.
34+
35+simplejson exposes an API familiar to uses of the standard library
36+marshal and pickle modules.
37+
38+Encoding basic Python object hierarchies::
39+   
40+    >>> import simplejson
41+    >>> simplejson.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
42+    '["foo", {"bar": ["baz", null, 1.0, 2]}]'
43+    >>> print simplejson.dumps("\"foo\bar")
44+    "\"foo\bar"
45+    >>> print simplejson.dumps(u'\u1234')
46+    "\u1234"
47+    >>> print simplejson.dumps('\\')
48+    "\\"
49+    >>> print simplejson.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
50+    {"a": 0, "b": 0, "c": 0}
51+    >>> from StringIO import StringIO
52+    >>> io = StringIO()
53+    >>> simplejson.dump(['streaming API'], io)
54+    >>> io.getvalue()
55+    '["streaming API"]'
56+
57+Compact encoding::
58+
59+    >>> import simplejson
60+    >>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
61+    '[1,2,3,{"4":5,"6":7}]'
62+
63+Pretty printing::
64+
65+    >>> import simplejson
66+    >>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
67+    {
68+        "4": 5,
69+        "6": 7
70+    }
71+
72+Decoding JSON::
73+   
74+    >>> import simplejson
75+    >>> simplejson.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
76+    [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
77+    >>> simplejson.loads('"\\"foo\\bar"')
78+    u'"foo\x08ar'
79+    >>> from StringIO import StringIO
80+    >>> io = StringIO('["streaming API"]')
81+    >>> simplejson.load(io)
82+    [u'streaming API']
83+
84+Specializing JSON object decoding::
85+
86+    >>> import simplejson
87+    >>> def as_complex(dct):
88+    ...     if '__complex__' in dct:
89+    ...         return complex(dct['real'], dct['imag'])
90+    ...     return dct
91+    ...
92+    >>> simplejson.loads('{"__complex__": true, "real": 1, "imag": 2}',
93+    ...     object_hook=as_complex)
94+    (1+2j)
95+
96+Extending JSONEncoder::
97+   
98+    >>> import simplejson
99+    >>> class ComplexEncoder(simplejson.JSONEncoder):
100+    ...     def default(self, obj):
101+    ...         if isinstance(obj, complex):
102+    ...             return [obj.real, obj.imag]
103+    ...         return simplejson.JSONEncoder.default(self, obj)
104+    ...
105+    >>> dumps(2 + 1j, cls=ComplexEncoder)
106+    '[2.0, 1.0]'
107+    >>> ComplexEncoder().encode(2 + 1j)
108+    '[2.0, 1.0]'
109+    >>> list(ComplexEncoder().iterencode(2 + 1j))
110+    ['[', '2.0', ', ', '1.0', ']']
111+   
112+
113+Note that the JSON produced by this module's default settings
114+is a subset of YAML, so it may be used as a serializer for that as well.
115+"""
116+__version__ = '1.5'
117+__all__ = [
118+    'dump', 'dumps', 'load', 'loads',
119+    'JSONDecoder', 'JSONEncoder',
120+]
121+
122+from decoder import JSONDecoder
123+from encoder import JSONEncoder
124+
125+def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
126+        allow_nan=True, cls=None, indent=None, **kw):
127+    """
128+    Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
129+    ``.write()``-supporting file-like object).
130+
131+    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
132+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
133+    will be skipped instead of raising a ``TypeError``.
134+
135+    If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp``
136+    may be ``unicode`` instances, subject to normal Python ``str`` to
137+    ``unicode`` coercion rules.  Unless ``fp.write()`` explicitly
138+    understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
139+    to cause an error.
140+
141+    If ``check_circular`` is ``False``, then the circular reference check
142+    for container types will be skipped and a circular reference will
143+    result in an ``OverflowError`` (or worse).
144+
145+    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
146+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
147+    in strict compliance of the JSON specification, instead of using the
148+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
149+
150+    If ``indent`` is a non-negative integer, then JSON array elements and object
151+    members will be pretty-printed with that indent level.  An indent level
152+    of 0 will only insert newlines.  ``None`` is the most compact representation.
153+
154+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
155+    ``.default()`` method to serialize additional types), specify it with
156+    the ``cls`` kwarg.
157+    """
158+    if cls is None:
159+        cls = JSONEncoder
160+    iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
161+        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
162+        **kw).iterencode(obj)
163+    # could accelerate with writelines in some versions of Python, at
164+    # a debuggability cost
165+    for chunk in iterable:
166+        fp.write(chunk)
167+
168+def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
169+        allow_nan=True, cls=None, indent=None, separators=None, **kw):
170+    """
171+    Serialize ``obj`` to a JSON formatted ``str``.
172+
173+    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
174+    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
175+    will be skipped instead of raising a ``TypeError``.
176+
177+    If ``ensure_ascii`` is ``False``, then the return value will be a
178+    ``unicode`` instance subject to normal Python ``str`` to ``unicode``
179+    coercion rules instead of being escaped to an ASCII ``str``.
180+
181+    If ``check_circular`` is ``False``, then the circular reference check
182+    for container types will be skipped and a circular reference will
183+    result in an ``OverflowError`` (or worse).
184+
185+    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
186+    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
187+    strict compliance of the JSON specification, instead of using the
188+    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
189+
190+    If ``indent`` is a non-negative integer, then JSON array elements and
191+    object members will be pretty-printed with that indent level.  An indent
192+    level of 0 will only insert newlines.  ``None`` is the most compact
193+    representation.
194+
195+    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
196+    then it will be used instead of the default ``(', ', ': ')`` separators.
197+    ``(',', ':')`` is the most compact JSON representation.
198+
199+    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
200+    ``.default()`` method to serialize additional types), specify it with
201+    the ``cls`` kwarg.
202+    """
203+    if cls is None:
204+        cls = JSONEncoder
205+    return cls(
206+        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
207+        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
208+        separators=separators,
209+        **kw).encode(obj)
210+
211+def load(fp, encoding=None, cls=None, object_hook=None, **kw):
212+    """
213+    Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
214+    a JSON document) to a Python object.
215+
216+    If the contents of ``fp`` is encoded with an ASCII based encoding other
217+    than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
218+    be specified.  Encodings that are not ASCII based (such as UCS-2) are
219+    not allowed, and should be wrapped with
220+    ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
221+    object and passed to ``loads()``
222+
223+    ``object_hook`` is an optional function that will be called with the
224+    result of any object literal decode (a ``dict``).  The return value of
225+    ``object_hook`` will be used instead of the ``dict``.  This feature
226+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
227+   
228+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
229+    kwarg.
230+    """
231+    if cls is None:
232+        cls = JSONDecoder
233+    if object_hook is not None:
234+        kw['object_hook'] = object_hook
235+    return cls(encoding=encoding, **kw).decode(fp.read())
236+
237+def loads(s, encoding=None, cls=None, object_hook=None, **kw):
238+    """
239+    Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
240+    document) to a Python object.
241+
242+    If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
243+    other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
244+    must be specified.  Encodings that are not ASCII based (such as UCS-2)
245+    are not allowed and should be decoded to ``unicode`` first.
246+
247+    ``object_hook`` is an optional function that will be called with the
248+    result of any object literal decode (a ``dict``).  The return value of
249+    ``object_hook`` will be used instead of the ``dict``.  This feature
250+    can be used to implement custom decoders (e.g. JSON-RPC class hinting).
251+
252+    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
253+    kwarg.
254+    """
255+    if cls is None:
256+        cls = JSONDecoder
257+    if object_hook is not None:
258+        kw['object_hook'] = object_hook
259+    return cls(encoding=encoding, **kw).decode(s)
260+
261+def read(s):
262+    """
263+    json-py API compatibility hook.  Use loads(s) instead.
264+    """
265+    import warnings
266+    warnings.warn("simplejson.loads(s) should be used instead of read(s)",
267+        DeprecationWarning)
268+    return loads(s)
269+
270+def write(obj):
271+    """
272+    json-py API compatibility hook.  Use dumps(s) instead.
273+    """
274+    import warnings
275+    warnings.warn("simplejson.dumps(s) should be used instead of write(s)",
276+        DeprecationWarning)
277+    return dumps(obj)
278+
279+
280diff --git a/django/utils/simplejson/decoder.py b/django/utils/simplejson/decoder.py
281index 684af8c..a1b53b2 100644
282--- a/django/utils/simplejson/decoder.py
283+++ b/django/utils/simplejson/decoder.py
284@@ -0,0 +1,273 @@
285+"""
286+Implementation of JSONDecoder
287+"""
288+import re
289+
290+from simplejson.scanner import Scanner, pattern
291+
292+FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
293+
294+def _floatconstants():
295+    import struct
296+    import sys
297+    _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
298+    if sys.byteorder != 'big':
299+        _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
300+    nan, inf = struct.unpack('dd', _BYTES)
301+    return nan, inf, -inf
302+
303+NaN, PosInf, NegInf = _floatconstants()
304+
305+def linecol(doc, pos):
306+    lineno = doc.count('\n', 0, pos) + 1
307+    if lineno == 1:
308+        colno = pos
309+    else:
310+        colno = pos - doc.rindex('\n', 0, pos)
311+    return lineno, colno
312+
313+def errmsg(msg, doc, pos, end=None):
314+    lineno, colno = linecol(doc, pos)
315+    if end is None:
316+        return '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
317+    endlineno, endcolno = linecol(doc, end)
318+    return '%s: line %d column %d - line %d column %d (char %d - %d)' % (
319+        msg, lineno, colno, endlineno, endcolno, pos, end)
320+
321+_CONSTANTS = {
322+    '-Infinity': NegInf,
323+    'Infinity': PosInf,
324+    'NaN': NaN,
325+    'true': True,
326+    'false': False,
327+    'null': None,
328+}
329+
330+def JSONConstant(match, context, c=_CONSTANTS):
331+    return c[match.group(0)], None
332+pattern('(-?Infinity|NaN|true|false|null)')(JSONConstant)
333+
334+def JSONNumber(match, context):
335+    match = JSONNumber.regex.match(match.string, *match.span())
336+    integer, frac, exp = match.groups()
337+    if frac or exp:
338+        res = float(integer + (frac or '') + (exp or ''))
339+    else:
340+        res = int(integer)
341+    return res, None
342+pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber)
343+
344+STRINGCHUNK = re.compile(r'(.*?)(["\\])', FLAGS)
345+BACKSLASH = {
346+    '"': u'"', '\\': u'\\', '/': u'/',
347+    'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
348+}
349+
350+DEFAULT_ENCODING = "utf-8"
351+
352+def scanstring(s, end, encoding=None, _b=BACKSLASH, _m=STRINGCHUNK.match):
353+    if encoding is None:
354+        encoding = DEFAULT_ENCODING
355+    chunks = []
356+    _append = chunks.append
357+    begin = end - 1
358+    while 1:
359+        chunk = _m(s, end)
360+        if chunk is None:
361+            raise ValueError(
362+                errmsg("Unterminated string starting at", s, begin))
363+        end = chunk.end()
364+        content, terminator = chunk.groups()
365+        if content:
366+            if not isinstance(content, unicode):
367+                content = unicode(content, encoding)
368+            _append(content)
369+        if terminator == '"':
370+            break
371+        try:
372+            esc = s[end]
373+        except IndexError:
374+            raise ValueError(
375+                errmsg("Unterminated string starting at", s, begin))
376+        if esc != 'u':
377+            try:
378+                m = _b[esc]
379+            except KeyError:
380+                raise ValueError(
381+                    errmsg("Invalid \\escape: %r" % (esc,), s, end))
382+            end += 1
383+        else:
384+            esc = s[end + 1:end + 5]
385+            try:
386+                m = unichr(int(esc, 16))
387+                if len(esc) != 4 or not esc.isalnum():
388+                    raise ValueError
389+            except ValueError:
390+                raise ValueError(errmsg("Invalid \\uXXXX escape", s, end))
391+            end += 5
392+        _append(m)
393+    return u''.join(chunks), end
394+
395+def JSONString(match, context):
396+    encoding = getattr(context, 'encoding', None)
397+    return scanstring(match.string, match.end(), encoding)
398+pattern(r'"')(JSONString)
399+
400+WHITESPACE = re.compile(r'\s*', FLAGS)
401+
402+def JSONObject(match, context, _w=WHITESPACE.match):
403+    pairs = {}
404+    s = match.string
405+    end = _w(s, match.end()).end()
406+    nextchar = s[end:end + 1]
407+    # trivial empty object
408+    if nextchar == '}':
409+        return pairs, end + 1
410+    if nextchar != '"':
411+        raise ValueError(errmsg("Expecting property name", s, end))
412+    end += 1
413+    encoding = getattr(context, 'encoding', None)
414+    iterscan = JSONScanner.iterscan
415+    while True:
416+        key, end = scanstring(s, end, encoding)
417+        end = _w(s, end).end()
418+        if s[end:end + 1] != ':':
419+            raise ValueError(errmsg("Expecting : delimiter", s, end))
420+        end = _w(s, end + 1).end()
421+        try:
422+            value, end = iterscan(s, idx=end, context=context).next()
423+        except StopIteration:
424+            raise ValueError(errmsg("Expecting object", s, end))
425+        pairs[key] = value
426+        end = _w(s, end).end()
427+        nextchar = s[end:end + 1]
428+        end += 1
429+        if nextchar == '}':
430+            break
431+        if nextchar != ',':
432+            raise ValueError(errmsg("Expecting , delimiter", s, end - 1))
433+        end = _w(s, end).end()
434+        nextchar = s[end:end + 1]
435+        end += 1
436+        if nextchar != '"':
437+            raise ValueError(errmsg("Expecting property name", s, end - 1))
438+    object_hook = getattr(context, 'object_hook', None)
439+    if object_hook is not None:
440+        pairs = object_hook(pairs)
441+    return pairs, end
442+pattern(r'{')(JSONObject)
443+           
444+def JSONArray(match, context, _w=WHITESPACE.match):
445+    values = []
446+    s = match.string
447+    end = _w(s, match.end()).end()
448+    # look-ahead for trivial empty array
449+    nextchar = s[end:end + 1]
450+    if nextchar == ']':
451+        return values, end + 1
452+    iterscan = JSONScanner.iterscan
453+    while True:
454+        try:
455+            value, end = iterscan(s, idx=end, context=context).next()
456+        except StopIteration:
457+            raise ValueError(errmsg("Expecting object", s, end))
458+        values.append(value)
459+        end = _w(s, end).end()
460+        nextchar = s[end:end + 1]
461+        end += 1
462+        if nextchar == ']':
463+            break
464+        if nextchar != ',':
465+            raise ValueError(errmsg("Expecting , delimiter", s, end))
466+        end = _w(s, end).end()
467+    return values, end
468+pattern(r'\[')(JSONArray)
469+
470+ANYTHING = [
471+    JSONObject,
472+    JSONArray,
473+    JSONString,
474+    JSONConstant,
475+    JSONNumber,
476+]
477+
478+JSONScanner = Scanner(ANYTHING)
479+
480+class JSONDecoder(object):
481+    """
482+    Simple JSON <http://json.org> decoder
483+
484+    Performs the following translations in decoding:
485+   
486+    +---------------+-------------------+
487+    | JSON          | Python            |
488+    +===============+===================+
489+    | object        | dict              |
490+    +---------------+-------------------+
491+    | array         | list              |
492+    +---------------+-------------------+
493+    | string        | unicode           |
494+    +---------------+-------------------+
495+    | number (int)  | int, long         |
496+    +---------------+-------------------+
497+    | number (real) | float             |
498+    +---------------+-------------------+
499+    | true          | True              |
500+    +---------------+-------------------+
501+    | false         | False             |
502+    +---------------+-------------------+
503+    | null          | None              |
504+    +---------------+-------------------+
505+
506+    It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
507+    their corresponding ``float`` values, which is outside the JSON spec.
508+    """
509+
510+    _scanner = Scanner(ANYTHING)
511+    __all__ = ['__init__', 'decode', 'raw_decode']
512+
513+    def __init__(self, encoding=None, object_hook=None):
514+        """
515+        ``encoding`` determines the encoding used to interpret any ``str``
516+        objects decoded by this instance (utf-8 by default).  It has no
517+        effect when decoding ``unicode`` objects.
518+       
519+        Note that currently only encodings that are a superset of ASCII work,
520+        strings of other encodings should be passed in as ``unicode``.
521+
522+        ``object_hook``, if specified, will be called with the result
523+        of every JSON object decoded and its return value will be used in
524+        place of the given ``dict``.  This can be used to provide custom
525+        deserializations (e.g. to support JSON-RPC class hinting).
526+        """
527+        self.encoding = encoding
528+        self.object_hook = object_hook
529+
530+    def decode(self, s, _w=WHITESPACE.match):
531+        """
532+        Return the Python representation of ``s`` (a ``str`` or ``unicode``
533+        instance containing a JSON document)
534+        """
535+        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
536+        end = _w(s, end).end()
537+        if end != len(s):
538+            raise ValueError(errmsg("Extra data", s, end, len(s)))
539+        return obj
540+
541+    def raw_decode(self, s, **kw):
542+        """
543+        Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
544+        with a JSON document) and return a 2-tuple of the Python
545+        representation and the index in ``s`` where the document ended.
546+
547+        This can be used to decode a JSON document from a string that may
548+        have extraneous data at the end.
549+        """
550+        kw.setdefault('context', self)
551+        try:
552+            obj, end = self._scanner.iterscan(s, **kw).next()
553+        except StopIteration:
554+            raise ValueError("No JSON object could be decoded")
555+        return obj, end
556+
557+__all__ = ['JSONDecoder']
558diff --git a/django/utils/simplejson/encoder.py b/django/utils/simplejson/encoder.py
559index bb1aba0..c83c687 100644
560--- a/django/utils/simplejson/encoder.py
561+++ b/django/utils/simplejson/encoder.py
562@@ -0,0 +1,331 @@
563+"""
564+Implementation of JSONEncoder
565+"""
566+import re
567+
568+ESCAPE = re.compile(r'[\x00-\x19\\"\b\f\n\r\t]')
569+ESCAPE_ASCII = re.compile(r'([\\"/]|[^\ -~])')
570+ESCAPE_DCT = {
571+    # escape all forward slashes to prevent </script> attack
572+    '/': '\\/',
573+    '\\': '\\\\',
574+    '"': '\\"',
575+    '\b': '\\b',
576+    '\f': '\\f',
577+    '\n': '\\n',
578+    '\r': '\\r',
579+    '\t': '\\t',
580+}
581+for i in range(0x20):
582+    ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
583+
584+# assume this produces an infinity on all machines (probably not guaranteed)
585+INFINITY = float('1e66666')
586+
587+def floatstr(o, allow_nan=True):
588+    # Check for specials.  Note that this type of test is processor- and/or
589+    # platform-specific, so do tests which don't depend on the internals.
590+
591+    if o != o:
592+        text = 'NaN'
593+    elif o == INFINITY:
594+        text = 'Infinity'
595+    elif o == -INFINITY:
596+        text = '-Infinity'
597+    else:
598+        return str(o)
599+
600+    if not allow_nan:
601+        raise ValueError("Out of range float values are not JSON compliant: %r"
602+            % (o,))
603+
604+    return text
605+
606+
607+def encode_basestring(s):
608+    """
609+    Return a JSON representation of a Python string
610+    """
611+    def replace(match):
612+        return ESCAPE_DCT[match.group(0)]
613+    return '"' + ESCAPE.sub(replace, s) + '"'
614+
615+def encode_basestring_ascii(s):
616+    def replace(match):
617+        s = match.group(0)
618+        try:
619+            return ESCAPE_DCT[s]
620+        except KeyError:
621+            return '\\u%04x' % (ord(s),)
622+    return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
623+       
624+
625+class JSONEncoder(object):
626+    """
627+    Extensible JSON <http://json.org> encoder for Python data structures.
628+
629+    Supports the following objects and types by default:
630+   
631+    +-------------------+---------------+
632+    | Python            | JSON          |
633+    +===================+===============+
634+    | dict              | object        |
635+    +-------------------+---------------+
636+    | list, tuple       | array         |
637+    +-------------------+---------------+
638+    | str, unicode      | string        |
639+    +-------------------+---------------+
640+    | int, long, float  | number        |
641+    +-------------------+---------------+
642+    | True              | true          |
643+    +-------------------+---------------+
644+    | False             | false         |
645+    +-------------------+---------------+
646+    | None              | null          |
647+    +-------------------+---------------+
648+
649+    To extend this to recognize other objects, subclass and implement a
650+    ``.default()`` method with another method that returns a serializable
651+    object for ``o`` if possible, otherwise it should call the superclass
652+    implementation (to raise ``TypeError``).
653+    """
654+    __all__ = ['__init__', 'default', 'encode', 'iterencode']
655+    item_separator = ', '
656+    key_separator = ': '
657+    def __init__(self, skipkeys=False, ensure_ascii=True,
658+            check_circular=True, allow_nan=True, sort_keys=False,
659+            indent=None, separators=None):
660+        """
661+        Constructor for JSONEncoder, with sensible defaults.
662+
663+        If skipkeys is False, then it is a TypeError to attempt
664+        encoding of keys that are not str, int, long, float or None.  If
665+        skipkeys is True, such items are simply skipped.
666+
667+        If ensure_ascii is True, the output is guaranteed to be str
668+        objects with all incoming unicode characters escaped.  If
669+        ensure_ascii is false, the output will be unicode object.
670+
671+        If check_circular is True, then lists, dicts, and custom encoded
672+        objects will be checked for circular references during encoding to
673+        prevent an infinite recursion (which would cause an OverflowError).
674+        Otherwise, no such check takes place.
675+
676+        If allow_nan is True, then NaN, Infinity, and -Infinity will be
677+        encoded as such.  This behavior is not JSON specification compliant,
678+        but is consistent with most JavaScript based encoders and decoders.
679+        Otherwise, it will be a ValueError to encode such floats.
680+
681+        If sort_keys is True, then the output of dictionaries will be
682+        sorted by key; this is useful for regression tests to ensure
683+        that JSON serializations can be compared on a day-to-day basis.
684+
685+        If indent is a non-negative integer, then JSON array
686+        elements and object members will be pretty-printed with that
687+        indent level.  An indent level of 0 will only insert newlines.
688+        None is the most compact representation.
689+
690+        If specified, separators should be a (item_separator, key_separator)
691+        tuple. The default is (', ', ': '). To get the most compact JSON
692+        representation you should specify (',', ':') to eliminate whitespace.
693+        """
694+
695+        self.skipkeys = skipkeys
696+        self.ensure_ascii = ensure_ascii
697+        self.check_circular = check_circular
698+        self.allow_nan = allow_nan
699+        self.sort_keys = sort_keys
700+        self.indent = indent
701+        self.current_indent_level = 0
702+        if separators is not None:
703+            self.item_separator, self.key_separator = separators
704+
705+    def _newline_indent(self):
706+        return '\n' + (' ' * (self.indent * self.current_indent_level))
707+
708+    def _iterencode_list(self, lst, markers=None):
709+        if not lst:
710+            yield '[]'
711+            return
712+        if markers is not None:
713+            markerid = id(lst)
714+            if markerid in markers:
715+                raise ValueError("Circular reference detected")
716+            markers[markerid] = lst
717+        yield '['
718+        if self.indent is not None:
719+            self.current_indent_level += 1
720+            newline_indent = self._newline_indent()
721+            separator = self.item_separator + newline_indent
722+            yield newline_indent
723+        else:
724+            newline_indent = None
725+            separator = self.item_separator
726+        first = True
727+        for value in lst:
728+            if first:
729+                first = False
730+            else:
731+                yield separator
732+            for chunk in self._iterencode(value, markers):
733+                yield chunk
734+        if newline_indent is not None:
735+            self.current_indent_level -= 1
736+            yield self._newline_indent()
737+        yield ']'
738+        if markers is not None:
739+            del markers[markerid]
740+
741+    def _iterencode_dict(self, dct, markers=None):
742+        if not dct:
743+            yield '{}'
744+            return
745+        if markers is not None:
746+            markerid = id(dct)
747+            if markerid in markers:
748+                raise ValueError("Circular reference detected")
749+            markers[markerid] = dct
750+        yield '{'
751+        key_separator = self.key_separator
752+        if self.indent is not None:
753+            self.current_indent_level += 1
754+            newline_indent = self._newline_indent()
755+            item_separator = self.item_separator + newline_indent
756+            yield newline_indent
757+        else:
758+            newline_indent = None
759+            item_separator = self.item_separator
760+        first = True
761+        if self.ensure_ascii:
762+            encoder = encode_basestring_ascii
763+        else:
764+            encoder = encode_basestring
765+        allow_nan = self.allow_nan
766+        if self.sort_keys:
767+            keys = dct.keys()
768+            keys.sort()
769+            items = [(k, dct[k]) for k in keys]
770+        else:
771+            items = dct.iteritems()
772+        for key, value in items:
773+            if isinstance(key, basestring):
774+                pass
775+            # JavaScript is weakly typed for these, so it makes sense to
776+            # also allow them.  Many encoders seem to do something like this.
777+            elif isinstance(key, float):
778+                key = floatstr(key, allow_nan)
779+            elif isinstance(key, (int, long)):
780+                key = str(key)
781+            elif key is True:
782+                key = 'true'
783+            elif key is False:
784+                key = 'false'
785+            elif key is None:
786+                key = 'null'
787+            elif self.skipkeys:
788+                continue
789+            else:
790+                raise TypeError("key %r is not a string" % (key,))
791+            if first:
792+                first = False
793+            else:
794+                yield item_separator
795+            yield encoder(key)
796+            yield key_separator
797+            for chunk in self._iterencode(value, markers):
798+                yield chunk
799+        if newline_indent is not None:
800+            self.current_indent_level -= 1
801+            yield self._newline_indent()
802+        yield '}'
803+        if markers is not None:
804+            del markers[markerid]
805+
806+    def _iterencode(self, o, markers=None):
807+        if isinstance(o, basestring):
808+            if self.ensure_ascii:
809+                encoder = encode_basestring_ascii
810+            else:
811+                encoder = encode_basestring
812+            yield encoder(o)
813+        elif o is None:
814+            yield 'null'
815+        elif o is True:
816+            yield 'true'
817+        elif o is False:
818+            yield 'false'
819+        elif isinstance(o, (int, long)):
820+            yield str(o)
821+        elif isinstance(o, float):
822+            yield floatstr(o, self.allow_nan)
823+        elif isinstance(o, (list, tuple)):
824+            for chunk in self._iterencode_list(o, markers):
825+                yield chunk
826+        elif isinstance(o, dict):
827+            for chunk in self._iterencode_dict(o, markers):
828+                yield chunk
829+        else:
830+            if markers is not None:
831+                markerid = id(o)
832+                if markerid in markers:
833+                    raise ValueError("Circular reference detected")
834+                markers[markerid] = o
835+            for chunk in self._iterencode_default(o, markers):
836+                yield chunk
837+            if markers is not None:
838+                del markers[markerid]
839+
840+    def _iterencode_default(self, o, markers=None):
841+        newobj = self.default(o)
842+        return self._iterencode(newobj, markers)
843+
844+    def default(self, o):
845+        """
846+        Implement this method in a subclass such that it returns
847+        a serializable object for ``o``, or calls the base implementation
848+        (to raise a ``TypeError``).
849+
850+        For example, to support arbitrary iterators, you could
851+        implement default like this::
852+           
853+            def default(self, o):
854+                try:
855+                    iterable = iter(o)
856+                except TypeError:
857+                    pass
858+                else:
859+                    return list(iterable)
860+                return JSONEncoder.default(self, o)
861+        """
862+        raise TypeError("%r is not JSON serializable" % (o,))
863+
864+    def encode(self, o):
865+        """
866+        Return a JSON string representation of a Python data structure.
867+
868+        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
869+        '{"foo":["bar", "baz"]}'
870+        """
871+        # This doesn't pass the iterator directly to ''.join() because it
872+        # sucks at reporting exceptions.  It's going to do this internally
873+        # anyway because it uses PySequence_Fast or similar.
874+        chunks = list(self.iterencode(o))
875+        return ''.join(chunks)
876+
877+    def iterencode(self, o):
878+        """
879+        Encode the given object and yield each string
880+        representation as available.
881+       
882+        For example::
883+           
884+            for chunk in JSONEncoder().iterencode(bigobject):
885+                mysocket.write(chunk)
886+        """
887+        if self.check_circular:
888+            markers = {}
889+        else:
890+            markers = None
891+        return self._iterencode(o, markers)
892+
893+__all__ = ['JSONEncoder']
894diff --git a/django/utils/simplejson/scanner.py b/django/utils/simplejson/scanner.py
895index b9244cf..64f4999 100644
896--- a/django/utils/simplejson/scanner.py
897+++ b/django/utils/simplejson/scanner.py
898@@ -0,0 +1,63 @@
899+"""
900+Iterator based sre token scanner
901+"""
902+import sre_parse, sre_compile, sre_constants
903+from sre_constants import BRANCH, SUBPATTERN
904+from re import VERBOSE, MULTILINE, DOTALL
905+import re
906+
907+__all__ = ['Scanner', 'pattern']
908+
909+FLAGS = (VERBOSE | MULTILINE | DOTALL)
910+class Scanner(object):
911+    def __init__(self, lexicon, flags=FLAGS):
912+        self.actions = [None]
913+        # combine phrases into a compound pattern
914+        s = sre_parse.Pattern()
915+        s.flags = flags
916+        p = []
917+        for idx, token in enumerate(lexicon):
918+            phrase = token.pattern
919+            try:
920+                subpattern = sre_parse.SubPattern(s,
921+                    [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))])
922+            except sre_constants.error:
923+                raise
924+            p.append(subpattern)
925+            self.actions.append(token)
926+
927+        p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
928+        self.scanner = sre_compile.compile(p)
929+
930+
931+    def iterscan(self, string, idx=0, context=None):
932+        """
933+        Yield match, end_idx for each match
934+        """
935+        match = self.scanner.scanner(string, idx).match
936+        actions = self.actions
937+        lastend = idx
938+        end = len(string)
939+        while True:
940+            m = match()
941+            if m is None:
942+                break
943+            matchbegin, matchend = m.span()
944+            if lastend == matchend:
945+                break
946+            action = actions[m.lastindex]
947+            if action is not None:
948+                rval, next_pos = action(m, context)
949+                if next_pos is not None and next_pos != matchend:
950+                    # "fast forward" the scanner
951+                    matchend = next_pos
952+                    match = self.scanner.scanner(string, matchend).match
953+                yield rval, matchend
954+            lastend = matchend
955+           
956+def pattern(pattern, flags=FLAGS):
957+    def decorator(fn):
958+        fn.pattern = pattern
959+        fn.regex = re.compile(pattern, flags)
960+        return fn
961+    return decorator