Browse Source

Fixed #18023 -- Removed bundled simplejson.

And started the deprecation path for django.utils.simplejson.

Thanks Alex Ogier, Clueless, and other contributors for their
work on the patch.
Aymeric Augustin 13 years ago
parent
commit
cec6bd5a59

+ 0 - 1
MANIFEST.in

@@ -6,7 +6,6 @@ include MANIFEST.in
 include django/contrib/gis/gdal/LICENSE
 include django/contrib/gis/geos/LICENSE
 include django/dispatch/license.txt
-include django/utils/simplejson/LICENSE.txt
 recursive-include docs *
 recursive-include scripts *
 recursive-include extras *

+ 2 - 1
django/contrib/formtools/wizard/storage/cookie.py

@@ -1,6 +1,7 @@
+import json
+
 from django.core.exceptions import SuspiciousOperation
 from django.core.signing import BadSignature
-from django.utils import simplejson as json
 
 from django.contrib.formtools.wizard import storage
 

+ 2 - 2
django/contrib/gis/geometry/test_data.py

@@ -3,10 +3,10 @@ This module has the mock object definitions used to hold reference geometry
 for the GEOS and GDAL tests.
 """
 import gzip
+import json
 import os
 
 from django.contrib import gis
-from django.utils import simplejson
 
 
 # This global used to store reference geometry data.
@@ -100,6 +100,6 @@ class TestDataMixin(object):
         if GEOMETRIES is None:
             # Load up the test geometry data from fixture into global.
             gzf = gzip.GzipFile(os.path.join(TEST_DATA, 'geometries.json.gz'))
-            geometries = simplejson.loads(gzf.read())
+            geometries = json.loads(gzf.read())
             GEOMETRIES = TestGeomSet(**strconvert(geometries))
         return GEOMETRIES

+ 2 - 1
django/contrib/messages/storage/cookie.py

@@ -1,7 +1,8 @@
+import json
+
 from django.conf import settings
 from django.contrib.messages.storage.base import BaseStorage, Message
 from django.http import SimpleCookie
-from django.utils import simplejson as json
 from django.utils.crypto import salted_hmac, constant_time_compare
 
 

+ 2 - 1
django/contrib/messages/tests/cookie.py

@@ -1,10 +1,11 @@
+import json
+
 from django.contrib.messages import constants
 from django.contrib.messages.tests.base import BaseTest
 from django.contrib.messages.storage.cookie import (CookieStorage,
     MessageEncoder, MessageDecoder)
 from django.contrib.messages.storage.base import Message
 from django.test.utils import override_settings
-from django.utils import simplejson as json
 
 
 def set_cookie_data(storage, messages, invalid=False, encode_empty=False):

+ 8 - 5
django/core/serializers/json.py

@@ -2,14 +2,17 @@
 Serialize data to/from JSON
 """
 
+# Avoid shadowing the standard library json module
+from __future__ import absolute_import
+
 import datetime
 import decimal
+import json
 from StringIO import StringIO
 
 from django.core.serializers.base import DeserializationError
 from django.core.serializers.python import Serializer as PythonSerializer
 from django.core.serializers.python import Deserializer as PythonDeserializer
-from django.utils import simplejson
 from django.utils.timezone import is_aware
 
 class Serializer(PythonSerializer):
@@ -19,10 +22,10 @@ class Serializer(PythonSerializer):
     internal_use_only = False
 
     def end_serialization(self):
-        if simplejson.__version__.split('.') >= ['2', '1', '3']:
+        if json.__version__.split('.') >= ['2', '1', '3']:
             # Use JS strings to represent Python Decimal instances (ticket #16850)
             self.options.update({'use_decimal': False})
-        simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)
+        json.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)
 
     def getvalue(self):
         if callable(getattr(self.stream, 'getvalue', None)):
@@ -38,7 +41,7 @@ def Deserializer(stream_or_string, **options):
     else:
         stream = stream_or_string
     try:
-        for obj in PythonDeserializer(simplejson.load(stream), **options):
+        for obj in PythonDeserializer(json.load(stream), **options):
             yield obj
     except GeneratorExit:
         raise
@@ -47,7 +50,7 @@ def Deserializer(stream_or_string, **options):
         raise DeserializationError(e)
 
 
-class DjangoJSONEncoder(simplejson.JSONEncoder):
+class DjangoJSONEncoder(json.JSONEncoder):
     """
     JSONEncoder subclass that knows how to encode date/time and decimal types.
     """

+ 5 - 4
django/core/signing.py

@@ -33,12 +33,13 @@ There are 65 url-safe characters: the 64 used by url-safe base64 and the ':'.
 These functions make use of all of them.
 """
 import base64
+import json
 import time
 import zlib
 
 from django.conf import settings
 from django.core.exceptions import ImproperlyConfigured
-from django.utils import baseconv, simplejson
+from django.utils import baseconv
 from django.utils.crypto import constant_time_compare, salted_hmac
 from django.utils.encoding import force_unicode, smart_str
 from django.utils.importlib import import_module
@@ -89,14 +90,14 @@ def get_cookie_signer(salt='django.core.signing.get_cookie_signer'):
 
 class JSONSerializer(object):
     """
-    Simple wrapper around simplejson to be used in signing.dumps and
+    Simple wrapper around json to be used in signing.dumps and
     signing.loads.
     """
     def dumps(self, obj):
-        return simplejson.dumps(obj, separators=(',', ':'))
+        return json.dumps(obj, separators=(',', ':'))
 
     def loads(self, data):
-        return simplejson.loads(data)
+        return json.loads(data)
 
 
 def dumps(obj, key=None, salt='django.core.signing', serializer=JSONSerializer, compress=False):

+ 4 - 3
django/test/testcases.py

@@ -1,4 +1,5 @@
 import difflib
+import json
 import os
 import re
 import sys
@@ -33,7 +34,7 @@ from django.test.signals import template_rendered
 from django.test.utils import (get_warnings_state, restore_warnings_state,
     override_settings)
 from django.test.utils import ContextList
-from django.utils import simplejson, unittest as ut2
+from django.utils import unittest as ut2
 from django.utils.encoding import smart_str, force_unicode
 from django.utils.unittest.util import safe_repr
 from django.views.static import serve
@@ -189,8 +190,8 @@ class OutputChecker(doctest.OutputChecker):
         """
         want, got = self._strip_quotes(want, got)
         try:
-            want_json = simplejson.loads(want)
-            got_json = simplejson.loads(got)
+            want_json = json.loads(want)
+            got_json = json.loads(got)
         except Exception:
             return False
         return want_json == got_json

+ 31 - 0
django/utils/simplejson.py

@@ -0,0 +1,31 @@
+# Django 1.5 only supports Python >= 2.6, where the standard library includes
+# the json module. Previous version of Django shipped a copy for Python < 2.6.
+
+# For backwards compatibility, we're keeping an importable json module
+# at this location, with the same lookup sequence.
+
+# Avoid shadowing the simplejson module
+from __future__ import absolute_import
+
+import warnings
+warnings.warn("django.utils.simplejson is deprecated; use json instead.",
+              PendingDeprecationWarning)
+
+try:
+    import simplejson
+except ImportError:
+    use_simplejson = False
+else:
+    # The system-installed version has priority providing it is either not an
+    # earlier version or it contains the C speedups.
+    from json import __version__ as stdlib_json_version
+    use_simplejson = (hasattr(simplejson, '_speedups') or
+        simplejson.__version__.split('.') >= stdlib_json_version.split('.'))
+
+# Make sure we copy over the version. See #17071
+if use_simplejson:
+    from simplejson import *
+    from simplejson import __version__
+else:
+    from json import *
+    from json import __version__

+ 0 - 19
django/utils/simplejson/LICENSE.txt

@@ -1,19 +0,0 @@
-Copyright (c) 2006 Bob Ippolito
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 0 - 354
django/utils/simplejson/__init__.py

@@ -1,354 +0,0 @@
-r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of
-JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
-interchange format.
-
-:mod:`simplejson` exposes an API familiar to users of the standard library
-:mod:`marshal` and :mod:`pickle` modules. It is the externally maintained
-version of the :mod:`json` library contained in Python 2.6, but maintains
-compatibility with Python 2.4 and Python 2.5 and (currently) has
-significant performance advantages, even without using the optional C
-extension for speedups.
-
-Encoding basic Python object hierarchies::
-
-    >>> import simplejson as json
-    >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
-    '["foo", {"bar": ["baz", null, 1.0, 2]}]'
-    >>> print json.dumps("\"foo\bar")
-    "\"foo\bar"
-    >>> print json.dumps(u'\u1234')
-    "\u1234"
-    >>> print json.dumps('\\')
-    "\\"
-    >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
-    {"a": 0, "b": 0, "c": 0}
-    >>> from StringIO import StringIO
-    >>> io = StringIO()
-    >>> json.dump(['streaming API'], io)
-    >>> io.getvalue()
-    '["streaming API"]'
-
-Compact encoding::
-
-    >>> import simplejson as json
-    >>> json.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
-    '[1,2,3,{"4":5,"6":7}]'
-
-Pretty printing::
-
-    >>> import simplejson as json
-    >>> s = json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
-    >>> print '\n'.join([l.rstrip() for l in  s.splitlines()])
-    {
-        "4": 5,
-        "6": 7
-    }
-
-Decoding JSON::
-
-    >>> import simplejson as json
-    >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
-    >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj
-    True
-    >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar'
-    True
-    >>> from StringIO import StringIO
-    >>> io = StringIO('["streaming API"]')
-    >>> json.load(io)[0] == 'streaming API'
-    True
-
-Specializing JSON object decoding::
-
-    >>> import simplejson as json
-    >>> def as_complex(dct):
-    ...     if '__complex__' in dct:
-    ...         return complex(dct['real'], dct['imag'])
-    ...     return dct
-    ...
-    >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
-    ...     object_hook=as_complex)
-    (1+2j)
-    >>> import decimal
-    >>> json.loads('1.1', parse_float=decimal.Decimal) == decimal.Decimal('1.1')
-    True
-
-Specializing JSON object encoding::
-
-    >>> import simplejson as json
-    >>> def encode_complex(obj):
-    ...     if isinstance(obj, complex):
-    ...         return [obj.real, obj.imag]
-    ...     raise TypeError("%r is not JSON serializable" % (o,))
-    ...
-    >>> json.dumps(2 + 1j, default=encode_complex)
-    '[2.0, 1.0]'
-    >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
-    '[2.0, 1.0]'
-    >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
-    '[2.0, 1.0]'
-
-
-Using simplejson.tool from the shell to validate and pretty-print::
-
-    $ echo '{"json":"obj"}' | python -msimplejson.tool
-    {
-        "json": "obj"
-    }
-    $ echo '{ 1.2:3.4}' | python -msimplejson.tool
-    Expecting property name: line 1 column 2 (char 2)
-"""
-
-# Django modification: try to use the system version first, providing it's
-# either of a later version of has the C speedups in place. Otherwise, fall
-# back to our local copy.
-
-__version__ = '2.0.7'
-
-use_system_version = False
-try:
-    # The system-installed version has priority providing it is either not an
-    # earlier version or it contains the C speedups.
-    import simplejson
-    if (simplejson.__version__.split('.') >= __version__.split('.') or
-            hasattr(simplejson, '_speedups')):
-        from simplejson import *
-        use_system_version = True
-        # Make sure we copy over the version. See #17071
-        __version__ = simplejson.__version__
-except ImportError:
-    pass
-
-if not use_system_version:
-    try:
-        from json import *      # Python 2.6 preferred over local copy.
-
-        # There is a "json" package around that is not Python's "json", so we
-        # check for something that is only in the namespace of the version we
-        # want.
-        JSONDecoder
-
-        use_system_version = True
-        # Make sure we copy over the version. See #17071
-        from json import __version__ as json_version
-        __version__ = json_version
-    except (ImportError, NameError):
-        pass
-
-# If all else fails, we have a bundled version that can be used.
-if not use_system_version:
-    __all__ = [
-        'dump', 'dumps', 'load', 'loads',
-        'JSONDecoder', 'JSONEncoder',
-    ]
-
-    from django.utils.simplejson.decoder import JSONDecoder
-    from django.utils.simplejson.encoder import JSONEncoder
-
-    _default_encoder = JSONEncoder(
-        skipkeys=False,
-        ensure_ascii=True,
-        check_circular=True,
-        allow_nan=True,
-        indent=None,
-        separators=None,
-        encoding='utf-8',
-        default=None,
-    )
-
-    def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
-            allow_nan=True, cls=None, indent=None, separators=None,
-            encoding='utf-8', default=None, **kw):
-        """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
-        ``.write()``-supporting file-like object).
-
-        If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
-        (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
-        will be skipped instead of raising a ``TypeError``.
-
-        If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp``
-        may be ``unicode`` instances, subject to normal Python ``str`` to
-        ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
-        understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
-        to cause an error.
-
-        If ``check_circular`` is ``False``, then the circular reference check
-        for container types will be skipped and a circular reference will
-        result in an ``OverflowError`` (or worse).
-
-        If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
-        serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
-        in strict compliance of the JSON specification, instead of using the
-        JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
-        If ``indent`` is a non-negative integer, then JSON array elements and object
-        members will be pretty-printed with that indent level. An indent level
-        of 0 will only insert newlines. ``None`` is the most compact representation.
-
-        If ``separators`` is an ``(item_separator, dict_separator)`` tuple
-        then it will be used instead of the default ``(', ', ': ')`` separators.
-        ``(',', ':')`` is the most compact JSON representation.
-
-        ``encoding`` is the character encoding for str instances, default is UTF-8.
-
-        ``default(obj)`` is a function that should return a serializable version
-        of obj or raise TypeError. The default simply raises TypeError.
-
-        To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
-        ``.default()`` method to serialize additional types), specify it with
-        the ``cls`` kwarg.
-
-        """
-        # cached encoder
-        if (skipkeys is False and ensure_ascii is True and
-            check_circular is True and allow_nan is True and
-            cls is None and indent is None and separators is None and
-            encoding == 'utf-8' and default is None and not kw):
-            iterable = _default_encoder.iterencode(obj)
-        else:
-            if cls is None:
-                cls = JSONEncoder
-            iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
-                check_circular=check_circular, allow_nan=allow_nan, indent=indent,
-                separators=separators, encoding=encoding,
-                default=default, **kw).iterencode(obj)
-        # could accelerate with writelines in some versions of Python, at
-        # a debuggability cost
-        for chunk in iterable:
-            fp.write(chunk)
-
-
-    def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
-            allow_nan=True, cls=None, indent=None, separators=None,
-            encoding='utf-8', default=None, **kw):
-        """Serialize ``obj`` to a JSON formatted ``str``.
-
-        If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
-        (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
-        will be skipped instead of raising a ``TypeError``.
-
-        If ``ensure_ascii`` is ``False``, then the return value will be a
-        ``unicode`` instance subject to normal Python ``str`` to ``unicode``
-        coercion rules instead of being escaped to an ASCII ``str``.
-
-        If ``check_circular`` is ``False``, then the circular reference check
-        for container types will be skipped and a circular reference will
-        result in an ``OverflowError`` (or worse).
-
-        If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
-        serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
-        strict compliance of the JSON specification, instead of using the
-        JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
-        If ``indent`` is a non-negative integer, then JSON array elements and
-        object members will be pretty-printed with that indent level. An indent
-        level of 0 will only insert newlines. ``None`` is the most compact
-        representation.
-
-        If ``separators`` is an ``(item_separator, dict_separator)`` tuple
-        then it will be used instead of the default ``(', ', ': ')`` separators.
-        ``(',', ':')`` is the most compact JSON representation.
-
-        ``encoding`` is the character encoding for str instances, default is UTF-8.
-
-        ``default(obj)`` is a function that should return a serializable version
-        of obj or raise TypeError. The default simply raises TypeError.
-
-        To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
-        ``.default()`` method to serialize additional types), specify it with
-        the ``cls`` kwarg.
-
-        """
-        # cached encoder
-        if (skipkeys is False and ensure_ascii is True and
-            check_circular is True and allow_nan is True and
-            cls is None and indent is None and separators is None and
-            encoding == 'utf-8' and default is None and not kw):
-            return _default_encoder.encode(obj)
-        if cls is None:
-            cls = JSONEncoder
-        return cls(
-            skipkeys=skipkeys, ensure_ascii=ensure_ascii,
-            check_circular=check_circular, allow_nan=allow_nan, indent=indent,
-            separators=separators, encoding=encoding, default=default,
-            **kw).encode(obj)
-
-
-    _default_decoder = JSONDecoder(encoding=None, object_hook=None)
-
-
-    def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
-            parse_int=None, parse_constant=None, **kw):
-        """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
-        a JSON document) to a Python object.
-
-        If the contents of ``fp`` is encoded with an ASCII based encoding other
-        than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
-        be specified. Encodings that are not ASCII based (such as UCS-2) are
-        not allowed, and should be wrapped with
-        ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
-        object and passed to ``loads()``
-
-        ``object_hook`` is an optional function that will be called with the
-        result of any object literal decode (a ``dict``). The return value of
-        ``object_hook`` will be used instead of the ``dict``. This feature
-        can be used to implement custom decoders (e.g. JSON-RPC class hinting).
-
-        To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
-        kwarg.
-
-        """
-        return loads(fp.read(),
-            encoding=encoding, cls=cls, object_hook=object_hook,
-            parse_float=parse_float, parse_int=parse_int,
-            parse_constant=parse_constant, **kw)
-
-
-    def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
-            parse_int=None, parse_constant=None, **kw):
-        """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
-        document) to a Python object.
-
-        If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
-        other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
-        must be specified. Encodings that are not ASCII based (such as UCS-2)
-        are not allowed and should be decoded to ``unicode`` first.
-
-        ``object_hook`` is an optional function that will be called with the
-        result of any object literal decode (a ``dict``). The return value of
-        ``object_hook`` will be used instead of the ``dict``. This feature
-        can be used to implement custom decoders (e.g. JSON-RPC class hinting).
-
-        ``parse_float``, if specified, will be called with the string
-        of every JSON float to be decoded. By default this is equivalent to
-        float(num_str). This can be used to use another datatype or parser
-        for JSON floats (e.g. decimal.Decimal).
-
-        ``parse_int``, if specified, will be called with the string
-        of every JSON int to be decoded. By default this is equivalent to
-        int(num_str). This can be used to use another datatype or parser
-        for JSON integers (e.g. float).
-
-        ``parse_constant``, if specified, will be called with one of the
-        following strings: -Infinity, Infinity, NaN, null, true, false.
-        This can be used to raise an exception if invalid JSON numbers
-        are encountered.
-
-        To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
-        kwarg.
-
-        """
-        if (cls is None and encoding is None and object_hook is None and
-                parse_int is None and parse_float is None and
-                parse_constant is None and not kw):
-            return _default_decoder.decode(s)
-        if cls is None:
-            cls = JSONDecoder
-        if object_hook is not None:
-            kw['object_hook'] = object_hook
-        if parse_float is not None:
-            kw['parse_float'] = parse_float
-        if parse_int is not None:
-            kw['parse_int'] = parse_int
-        if parse_constant is not None:
-            kw['parse_constant'] = parse_constant
-        return cls(encoding=encoding, **kw).decode(s)

+ 0 - 345
django/utils/simplejson/decoder.py

@@ -1,345 +0,0 @@
-"""Implementation of JSONDecoder
-"""
-import re
-import sys
-import struct
-
-from django.utils.simplejson.scanner import make_scanner
-c_scanstring = None
-
-__all__ = ['JSONDecoder']
-
-FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
-
-def _floatconstants():
-    _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
-    if sys.byteorder != 'big':
-        _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
-    nan, inf = struct.unpack('dd', _BYTES)
-    return nan, inf, -inf
-
-NaN, PosInf, NegInf = _floatconstants()
-
-
-def linecol(doc, pos):
-    lineno = doc.count('\n', 0, pos) + 1
-    if lineno == 1:
-        colno = pos
-    else:
-        colno = pos - doc.rindex('\n', 0, pos)
-    return lineno, colno
-
-
-def errmsg(msg, doc, pos, end=None):
-    # Note that this function is called from _speedups
-    lineno, colno = linecol(doc, pos)
-    if end is None:
-        return '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
-    endlineno, endcolno = linecol(doc, end)
-    return '%s: line %d column %d - line %d column %d (char %d - %d)' % (
-        msg, lineno, colno, endlineno, endcolno, pos, end)
-
-
-_CONSTANTS = {
-    '-Infinity': NegInf,
-    'Infinity': PosInf,
-    'NaN': NaN,
-}
-
-STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
-BACKSLASH = {
-    '"': u'"', '\\': u'\\', '/': u'/',
-    'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
-}
-
-DEFAULT_ENCODING = "utf-8"
-
-def py_scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match):
-    """Scan the string s for a JSON string. End is the index of the
-    character in s after the quote that started the JSON string.
-    Unescapes all valid JSON string escape sequences and raises ValueError
-    on attempt to decode an invalid string. If strict is False then literal
-    control characters are allowed in the string.
-    
-    Returns a tuple of the decoded string and the index of the character in s
-    after the end quote."""
-    if encoding is None:
-        encoding = DEFAULT_ENCODING
-    chunks = []
-    _append = chunks.append
-    begin = end - 1
-    while 1:
-        chunk = _m(s, end)
-        if chunk is None:
-            raise ValueError(
-                errmsg("Unterminated string starting at", s, begin))
-        end = chunk.end()
-        content, terminator = chunk.groups()
-        # Content is contains zero or more unescaped string characters
-        if content:
-            if not isinstance(content, unicode):
-                content = unicode(content, encoding)
-            _append(content)
-        # Terminator is the end of string, a literal control character,
-        # or a backslash denoting that an escape sequence follows
-        if terminator == '"':
-            break
-        elif terminator != '\\':
-            if strict:
-                msg = "Invalid control character %r at" % (terminator,)
-                raise ValueError(msg, s, end)
-            else:
-                _append(terminator)
-                continue
-        try:
-            esc = s[end]
-        except IndexError:
-            raise ValueError(
-                errmsg("Unterminated string starting at", s, begin))
-        # If not a unicode escape sequence, must be in the lookup table
-        if esc != 'u':
-            try:
-                char = _b[esc]
-            except KeyError:
-                raise ValueError(
-                    errmsg("Invalid \\escape: %r" % (esc,), s, end))
-            end += 1
-        else:
-            # Unicode escape sequence
-            esc = s[end + 1:end + 5]
-            next_end = end + 5
-            if len(esc) != 4:
-                msg = "Invalid \\uXXXX escape"
-                raise ValueError(errmsg(msg, s, end))
-            uni = int(esc, 16)
-            # Check for surrogate pair on UCS-4 systems
-            if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535:
-                msg = "Invalid \\uXXXX\\uXXXX surrogate pair"
-                if not s[end + 5:end + 7] == '\\u':
-                    raise ValueError(errmsg(msg, s, end))
-                esc2 = s[end + 7:end + 11]
-                if len(esc2) != 4:
-                    raise ValueError(errmsg(msg, s, end))
-                uni2 = int(esc2, 16)
-                uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
-                next_end += 6
-            char = unichr(uni)
-            end = next_end
-        # Append the unescaped character
-        _append(char)
-    return u''.join(chunks), end
-
-
-# Use speedup if available
-scanstring = c_scanstring or py_scanstring
-
-WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)
-WHITESPACE_STR = ' \t\n\r'
-
-def JSONObject((s, end), encoding, strict, scan_once, object_hook, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
-    pairs = {}
-    # Use a slice to prevent IndexError from being raised, the following
-    # check will raise a more specific ValueError if the string is empty
-    nextchar = s[end:end + 1]
-    # Normally we expect nextchar == '"'
-    if nextchar != '"':
-        if nextchar in _ws:
-            end = _w(s, end).end()
-            nextchar = s[end:end + 1]
-        # Trivial empty object
-        if nextchar == '}':
-            return pairs, end + 1
-        elif nextchar != '"':
-            raise ValueError(errmsg("Expecting property name", s, end))
-    end += 1
-    while True:
-        key, end = scanstring(s, end, encoding, strict)
-
-        # To skip some function call overhead we optimize the fast paths where
-        # the JSON key separator is ": " or just ":".
-        if s[end:end + 1] != ':':
-            end = _w(s, end).end()
-            if s[end:end + 1] != ':':
-                raise ValueError(errmsg("Expecting : delimiter", s, end))
-
-        end += 1
-
-        try:
-            if s[end] in _ws:
-                end += 1
-                if s[end] in _ws:
-                    end = _w(s, end + 1).end()
-        except IndexError:
-            pass
-
-        try:
-            value, end = scan_once(s, end)
-        except StopIteration:
-            raise ValueError(errmsg("Expecting object", s, end))
-        pairs[key] = value
-
-        try:
-            nextchar = s[end]
-            if nextchar in _ws:
-                end = _w(s, end + 1).end()
-                nextchar = s[end]
-        except IndexError:
-            nextchar = ''
-        end += 1
-
-        if nextchar == '}':
-            break
-        elif nextchar != ',':
-            raise ValueError(errmsg("Expecting , delimiter", s, end - 1))
-
-        try:
-            nextchar = s[end]
-            if nextchar in _ws:
-                end += 1
-                nextchar = s[end]
-                if nextchar in _ws:
-                    end = _w(s, end + 1).end()
-                    nextchar = s[end]
-        except IndexError:
-            nextchar = ''
-
-        end += 1
-        if nextchar != '"':
-            raise ValueError(errmsg("Expecting property name", s, end - 1))
-
-    if object_hook is not None:
-        pairs = object_hook(pairs)
-    return pairs, end
-
-def JSONArray((s, end), scan_once, _w=WHITESPACE.match, _ws=WHITESPACE_STR):
-    values = []
-    nextchar = s[end:end + 1]
-    if nextchar in _ws:
-        end = _w(s, end + 1).end()
-        nextchar = s[end:end + 1]
-    # Look-ahead for trivial empty array
-    if nextchar == ']':
-        return values, end + 1
-    _append = values.append
-    while True:
-        try:
-            value, end = scan_once(s, end)
-        except StopIteration:
-            raise ValueError(errmsg("Expecting object", s, end))
-        _append(value)
-        nextchar = s[end:end + 1]
-        if nextchar in _ws:
-            end = _w(s, end + 1).end()
-            nextchar = s[end:end + 1]
-        end += 1
-        if nextchar == ']':
-            break
-        elif nextchar != ',':
-            raise ValueError(errmsg("Expecting , delimiter", s, end))
-
-        try:
-            if s[end] in _ws:
-                end += 1
-                if s[end] in _ws:
-                    end = _w(s, end + 1).end()
-        except IndexError:
-            pass
-
-    return values, end
-
-class JSONDecoder(object):
-    """Simple JSON <http://json.org> decoder
-
-    Performs the following translations in decoding by default:
-
-    +---------------+-------------------+
-    | JSON          | Python            |
-    +===============+===================+
-    | object        | dict              |
-    +---------------+-------------------+
-    | array         | list              |
-    +---------------+-------------------+
-    | string        | unicode           |
-    +---------------+-------------------+
-    | number (int)  | int, long         |
-    +---------------+-------------------+
-    | number (real) | float             |
-    +---------------+-------------------+
-    | true          | True              |
-    +---------------+-------------------+
-    | false         | False             |
-    +---------------+-------------------+
-    | null          | None              |
-    +---------------+-------------------+
-
-    It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
-    their corresponding ``float`` values, which is outside the JSON spec.
-
-    """
-
-    def __init__(self, encoding=None, object_hook=None, parse_float=None,
-            parse_int=None, parse_constant=None, strict=True):
-        """``encoding`` determines the encoding used to interpret any ``str``
-        objects decoded by this instance (utf-8 by default).  It has no
-        effect when decoding ``unicode`` objects.
-
-        Note that currently only encodings that are a superset of ASCII work,
-        strings of other encodings should be passed in as ``unicode``.
-
-        ``object_hook``, if specified, will be called with the result
-        of every JSON object decoded and its return value will be used in
-        place of the given ``dict``.  This can be used to provide custom
-        deserializations (e.g. to support JSON-RPC class hinting).
-
-        ``parse_float``, if specified, will be called with the string
-        of every JSON float to be decoded. By default this is equivalent to
-        float(num_str). This can be used to use another datatype or parser
-        for JSON floats (e.g. decimal.Decimal).
-
-        ``parse_int``, if specified, will be called with the string
-        of every JSON int to be decoded. By default this is equivalent to
-        int(num_str). This can be used to use another datatype or parser
-        for JSON integers (e.g. float).
-
-        ``parse_constant``, if specified, will be called with one of the
-        following strings: -Infinity, Infinity, NaN.
-        This can be used to raise an exception if invalid JSON numbers
-        are encountered.
-
-        """
-        self.encoding = encoding
-        self.object_hook = object_hook
-        self.parse_float = parse_float or float
-        self.parse_int = parse_int or int
-        self.parse_constant = parse_constant or _CONSTANTS.__getitem__
-        self.strict = strict
-        self.parse_object = JSONObject
-        self.parse_array = JSONArray
-        self.parse_string = scanstring
-        self.scan_once = make_scanner(self)
-
-    def decode(self, s, _w=WHITESPACE.match):
-        """Return the Python representation of ``s`` (a ``str`` or ``unicode``
-        instance containing a JSON document)
-
-        """
-        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
-        end = _w(s, end).end()
-        if end != len(s):
-            raise ValueError(errmsg("Extra data", s, end, len(s)))
-        return obj
-
-    def raw_decode(self, s, idx=0):
-        """Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
-        with a JSON document) and return a 2-tuple of the Python
-        representation and the index in ``s`` where the document ended.
-
-        This can be used to decode a JSON document from a string that may
-        have extraneous data at the end.
-
-        """
-        try:
-            obj, end = self.scan_once(s, idx)
-        except StopIteration:
-            raise ValueError("No JSON object could be decoded")
-        return obj, end

+ 0 - 430
django/utils/simplejson/encoder.py

@@ -1,430 +0,0 @@
-"""Implementation of JSONEncoder
-"""
-import re
-
-c_encode_basestring_ascii = None
-c_make_encoder = None
-
-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%04x' % (i,))
-
-# Assume this produces an infinity on all machines (probably not guaranteed)
-INFINITY = float('1e66666')
-FLOAT_REPR = repr
-
-def encode_basestring(s):
-    """Return a JSON representation of a Python string
-
-    """
-    def replace(match):
-        return ESCAPE_DCT[match.group(0)]
-    return '"' + ESCAPE.sub(replace, s) + '"'
-
-
-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%04x' % (n,)
-            else:
-                # surrogate pair
-                n -= 0x10000
-                s1 = 0xd800 | ((n >> 10) & 0x3ff)
-                s2 = 0xdc00 | (n & 0x3ff)
-                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):
-        """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 non-negative integer, then JSON array
-        elements and object members will be pretty-printed with that
-        indent level.  An indent level of 0 will only insert newlines.
-        None is the most compact representation.
-
-        If specified, separators should be a (item_separator, key_separator)
-        tuple.  The default is (', ', ': ').  To get the most compact JSON
-        representation you should specify (',', ':') to eliminate whitespace.
-
-        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.
-
-        """
-
-        self.skipkeys = skipkeys
-        self.ensure_ascii = ensure_ascii
-        self.check_circular = check_circular
-        self.allow_nan = allow_nan
-        self.sort_keys = sort_keys
-        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("%r is not JSON serializable" % (o,))
-
-    def encode(self, o):
-        """Return a JSON string representation of a Python data structure.
-
-        >>> 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)
-        return ''.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=INFINITY, _neginf=-INFINITY):
-            # 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: %r"
-                    % (o,))
-
-            return text
-
-
-        if _one_shot and c_make_encoder is not None and not self.indent 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)
-        else:
-            _iterencode = _make_iterencode(
-                markers, self.default, _encoder, self.indent, floatstr,
-                self.key_separator, self.item_separator, self.sort_keys,
-                self.skipkeys, _one_shot)
-        return _iterencode(o, 0)
-
-def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, _key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
-        ## HACK: hand-optimized bytecode; turn globals into locals
-        False=False,
-        True=True,
-        ValueError=ValueError,
-        basestring=basestring,
-        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)
-            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 isinstance(key, (int, long)):
-                key = str(key)
-            elif key is True:
-                key = 'true'
-            elif key is False:
-                key = 'false'
-            elif key is None:
-                key = 'null'
-            elif _skipkeys:
-                continue
-            else:
-                raise TypeError("key %r is not a string" % (key,))
-            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)
-            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
-        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

+ 0 - 65
django/utils/simplejson/scanner.py

@@ -1,65 +0,0 @@
-"""JSON token scanner
-"""
-import re
-try:
-    from simplejson._speedups import make_scanner as c_make_scanner
-except ImportError:
-    c_make_scanner = None
-
-__all__ = ['make_scanner']
-
-NUMBER_RE = re.compile(
-    r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
-    (re.VERBOSE | re.MULTILINE | re.DOTALL))
-
-def py_make_scanner(context):
-    parse_object = context.parse_object
-    parse_array = context.parse_array
-    parse_string = context.parse_string
-    match_number = NUMBER_RE.match
-    encoding = context.encoding
-    strict = context.strict
-    parse_float = context.parse_float
-    parse_int = context.parse_int
-    parse_constant = context.parse_constant
-    object_hook = context.object_hook
-
-    def _scan_once(string, idx):
-        try:
-            nextchar = string[idx]
-        except IndexError:
-            raise StopIteration
-
-        if nextchar == '"':
-            return parse_string(string, idx + 1, encoding, strict)
-        elif nextchar == '{':
-            return parse_object((string, idx + 1), encoding, strict, _scan_once, object_hook)
-        elif nextchar == '[':
-            return parse_array((string, idx + 1), _scan_once)
-        elif nextchar == 'n' and string[idx:idx + 4] == 'null':
-            return None, idx + 4
-        elif nextchar == 't' and string[idx:idx + 4] == 'true':
-            return True, idx + 4
-        elif nextchar == 'f' and string[idx:idx + 5] == 'false':
-            return False, idx + 5
-
-        m = match_number(string, idx)
-        if m is not None:
-            integer, frac, exp = m.groups()
-            if frac or exp:
-                res = parse_float(integer + (frac or '') + (exp or ''))
-            else:
-                res = parse_int(integer)
-            return res, m.end()
-        elif nextchar == 'N' and string[idx:idx + 3] == 'NaN':
-            return parse_constant('NaN'), idx + 3
-        elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity':
-            return parse_constant('Infinity'), idx + 8
-        elif nextchar == '-' and string[idx:idx + 9] == '-Infinity':
-            return parse_constant('-Infinity'), idx + 9
-        else:
-            raise StopIteration
-
-    return _scan_once
-
-make_scanner = c_make_scanner or py_make_scanner

+ 0 - 35
django/utils/simplejson/tool.py

@@ -1,35 +0,0 @@
-r"""Using simplejson from the shell to validate and
-pretty-print::
-
-    $ echo '{"json":"obj"}' | python -msimplejson.tool
-    {
-        "json": "obj"
-    }
-    $ echo '{ 1.2:3.4}' | python -msimplejson.tool
-    Expecting property name: line 1 column 2 (char 2)
-"""
-from django.utils import simplejson
-
-def main():
-    import sys
-    if len(sys.argv) == 1:
-        infile = sys.stdin
-        outfile = sys.stdout
-    elif len(sys.argv) == 2:
-        infile = open(sys.argv[1], 'rb')
-        outfile = sys.stdout
-    elif len(sys.argv) == 3:
-        infile = open(sys.argv[1], 'rb')
-        outfile = open(sys.argv[2], 'wb')
-    else:
-        raise SystemExit("%s [infile [outfile]]" % (sys.argv[0],))
-    try:
-        obj = simplejson.load(infile)
-    except ValueError, e:
-        raise SystemExit(e)
-    simplejson.dump(obj, outfile, sort_keys=True, indent=4)
-    outfile.write('\n')
-
-
-if __name__ == '__main__':
-    main()

+ 1 - 13
docs/_ext/djangodocs.py

@@ -1,20 +1,11 @@
 """
 Sphinx plugins for Django documentation.
 """
+import json
 import os
 import re
 
 from docutils import nodes, transforms
-try:
-    import json
-except ImportError:
-    try:
-        import simplejson as json
-    except ImportError:
-        try:
-            from django.utils import simplejson as json
-        except ImportError:
-            json = None
 
 from sphinx import addnodes, roles, __version__ as sphinx_ver
 from sphinx.builders.html import StandaloneHTMLBuilder
@@ -210,9 +201,6 @@ class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder):
 
     def finish(self):
         super(DjangoStandaloneHTMLBuilder, self).finish()
-        if json is None:
-            self.warn("cannot create templatebuiltins.js due to missing simplejson dependency")
-            return
         self.info(bold("writing templatebuiltins.js..."))
         xrefs = self.env.domaindata["std"]["objects"]
         templatebuiltins = {

+ 3 - 0
docs/internals/deprecation.txt

@@ -268,6 +268,9 @@ these changes.
 See the :doc:`Django 1.5 release notes</releases/1.5>` for more details on
 these changes.
 
+* The module ``django.utils.simplejson`` will be removed. The standard library
+provides :mod:`json` which should be used instead.
+
 * The function ``django.utils.itercompat.product`` will be removed. The Python
   builtin version should be used instead.
 

+ 11 - 2
docs/releases/1.5.txt

@@ -58,8 +58,17 @@ Backwards incompatible changes in 1.5
 Features deprecated in 1.5
 ==========================
 
-itercompat.product
-~~~~~~~~~~~~~~~~~~
+``django.utils.simplejson``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since Django 1.5 drops support for Python 2.5, all supported versions of
+Python provide the :mod:`json` module in their standard library. This module
+is actually a version of ``simplejson`` distributed by Python, so Django no
+longer needs to provide a copy. Any use of :mod:`django.utils.simplejson` can
+be safely changed to :mod:`json`.
+
+``itercompat.product``
+~~~~~~~~~~~~~~~~~~~~~~
 
 The :func:`~django.utils.itercompat.product` function has been deprecated. Use
 the builtin `itertools.product` instead.

+ 1 - 1
docs/topics/class-based-views.txt

@@ -501,8 +501,8 @@ different rendering behavior.
 
 For example, a simple JSON mixin might look something like this::
 
+    import json
     from django import http
-    from django.utils import simplejson as json
 
     class JSONResponseMixin(object):
         def render_to_response(self, context):

+ 7 - 16
docs/topics/serialization.txt

@@ -143,15 +143,13 @@ Identifier  Information
 ==========  ==============================================================
 ``xml``     Serializes to and from a simple XML dialect.
 
-``json``    Serializes to and from JSON_ (using a version of simplejson_
-            bundled with Django).
+``json``    Serializes to and from JSON_.
 
 ``yaml``    Serializes to YAML (YAML Ain't a Markup Language). This
             serializer is only available if PyYAML_ is installed.
 ==========  ==============================================================
 
 .. _json: http://json.org/
-.. _simplejson: http://undefined.org/python/#simplejson
 .. _PyYAML: http://www.pyyaml.org/
 
 Notes for specific serialization formats
@@ -169,28 +167,21 @@ For example::
     json_serializer = serializers.get_serializer("json")()
     json_serializer.serialize(queryset, ensure_ascii=False, stream=response)
 
-The Django source code includes the simplejson_ module. However, if you're
-using Python 2.6 or later (which includes a builtin version of the module), Django will
-use the builtin ``json`` module automatically. If you have a system installed
-version that includes the C-based speedup extension, or your system version is
-more recent than the version shipped with Django (currently, 2.0.7), the
-system version will be used instead of the version included with Django.
-
-Be aware that if you're serializing using that module directly, not all Django
-output can be passed unmodified to simplejson. In particular, :ref:`lazy
-translation objects <lazy-translations>` need a `special encoder`_ written for
-them. Something like this will work::
+Be aware that not all Django output can be passed unmodified to :mod:`json`.
+In particular, :ref:`lazy translation objects <lazy-translations>` need a
+`special encoder`_ written for them. Something like this will work::
 
+    import json
     from django.utils.functional import Promise
     from django.utils.encoding import force_unicode
 
-    class LazyEncoder(simplejson.JSONEncoder):
+    class LazyEncoder(json.JSONEncoder):
         def default(self, obj):
             if isinstance(obj, Promise):
                 return force_unicode(obj)
             return super(LazyEncoder, self).default(obj)
 
-.. _special encoder: http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.7/docs/index.html
+.. _special encoder: http://docs.python.org/library/json.html#encoders-and-decoders
 
 .. _topics-serialization-natural-keys:
 

+ 2 - 1
tests/modeltests/field_subclassing/fields.py

@@ -1,5 +1,6 @@
+import json
+
 from django.db import models
-from django.utils import simplejson as json
 from django.utils.encoding import force_unicode
 
 

+ 5 - 4
tests/modeltests/serializers/tests.py

@@ -1,6 +1,7 @@
 from __future__ import absolute_import
 
 # -*- coding: utf-8 -*-
+import json
 from datetime import datetime
 from xml.dom import minidom
 from StringIO import StringIO
@@ -9,7 +10,7 @@ from django.conf import settings
 from django.core import serializers
 from django.db import transaction, connection
 from django.test import TestCase, TransactionTestCase, Approximate
-from django.utils import simplejson, unittest
+from django.utils import unittest
 
 from .models import (Category, Author, Article, AuthorProfile, Actor, Movie,
     Score, Player, Team)
@@ -354,7 +355,7 @@ class JsonSerializerTestCase(SerializersTestBase, TestCase):
     @staticmethod
     def _validate_output(serial_str):
         try:
-            simplejson.loads(serial_str)
+            json.loads(serial_str)
         except Exception:
             return False
         else:
@@ -363,7 +364,7 @@ class JsonSerializerTestCase(SerializersTestBase, TestCase):
     @staticmethod
     def _get_pk_values(serial_str):
         ret_list = []
-        serial_list = simplejson.loads(serial_str)
+        serial_list = json.loads(serial_str)
         for obj_dict in serial_list:
             ret_list.append(obj_dict["pk"])
         return ret_list
@@ -371,7 +372,7 @@ class JsonSerializerTestCase(SerializersTestBase, TestCase):
     @staticmethod
     def _get_field_values(serial_str, field_name):
         ret_list = []
-        serial_list = simplejson.loads(serial_str)
+        serial_list = json.loads(serial_str)
         for obj_dict in serial_list:
             if field_name in obj_dict["fields"]:
                 ret_list.append(obj_dict["fields"][field_name])

+ 10 - 9
tests/regressiontests/file_uploads/tests.py

@@ -5,6 +5,7 @@ from __future__ import absolute_import
 import base64
 import errno
 import hashlib
+import json
 import os
 import shutil
 from StringIO import StringIO
@@ -13,7 +14,7 @@ from django.core.files import temp as tempfile
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.http.multipartparser import MultiPartParser
 from django.test import TestCase, client
-from django.utils import simplejson, unittest
+from django.utils import unittest
 
 from . import uploadhandler
 from .models import FileModel, temp_storage, UPLOAD_TO
@@ -78,7 +79,7 @@ class FileUploadTests(TestCase):
             'wsgi.input':     client.FakePayload(payload),
         }
         response = self.client.request(**r)
-        received = simplejson.loads(response.content)
+        received = json.loads(response.content)
 
         self.assertEqual(received['file'], test_string)
 
@@ -150,7 +151,7 @@ class FileUploadTests(TestCase):
         response = self.client.request(**r)
 
         # The filenames should have been sanitized by the time it got to the view.
-        recieved = simplejson.loads(response.content)
+        recieved = json.loads(response.content)
         for i, name in enumerate(scary_file_names):
             got = recieved["file%s" % i]
             self.assertEqual(got, "hax0rd.txt")
@@ -174,7 +175,7 @@ class FileUploadTests(TestCase):
             'REQUEST_METHOD': 'POST',
             'wsgi.input':     client.FakePayload(payload),
         }
-        got = simplejson.loads(self.client.request(**r).content)
+        got = json.loads(self.client.request(**r).content)
         self.assertTrue(len(got['file']) < 256, "Got a long file name (%s characters)." % len(got['file']))
 
     def test_truncated_multipart_handled_gracefully(self):
@@ -200,7 +201,7 @@ class FileUploadTests(TestCase):
             'REQUEST_METHOD': 'POST',
             'wsgi.input': client.FakePayload(payload),
         }
-        got = simplejson.loads(self.client.request(**r).content)
+        got = json.loads(self.client.request(**r).content)
         self.assertEquals(got, {})
 
     def test_empty_multipart_handled_gracefully(self):
@@ -215,7 +216,7 @@ class FileUploadTests(TestCase):
             'REQUEST_METHOD': 'POST',
             'wsgi.input': client.FakePayload(''),
         }
-        got = simplejson.loads(self.client.request(**r).content)
+        got = json.loads(self.client.request(**r).content)
         self.assertEquals(got, {})
 
     def test_custom_upload_handler(self):
@@ -231,12 +232,12 @@ class FileUploadTests(TestCase):
 
         # Small file posting should work.
         response = self.client.post('/file_uploads/quota/', {'f': smallfile})
-        got = simplejson.loads(response.content)
+        got = json.loads(response.content)
         self.assertTrue('f' in got)
 
         # Large files don't go through.
         response = self.client.post("/file_uploads/quota/", {'f': bigfile})
-        got = simplejson.loads(response.content)
+        got = json.loads(response.content)
         self.assertTrue('f' not in got)
 
     def test_broken_custom_upload_handler(self):
@@ -274,7 +275,7 @@ class FileUploadTests(TestCase):
             'field5': u'test7',
             'file2': (file2, file2a)
         })
-        got = simplejson.loads(response.content)
+        got = json.loads(response.content)
 
         self.assertEqual(got.get('file1'), 1)
         self.assertEqual(got.get('file2'), 2)

+ 4 - 4
tests/regressiontests/file_uploads/views.py

@@ -1,11 +1,11 @@
 from __future__ import absolute_import
 
 import hashlib
+import json
 import os
 
 from django.core.files.uploadedfile import UploadedFile
 from django.http import HttpResponse, HttpResponseServerError
-from django.utils import simplejson
 
 from .models import FileModel, UPLOAD_TO
 from .tests import UNICODE_FILENAME
@@ -88,14 +88,14 @@ def file_upload_echo(request):
     Simple view to echo back info about uploaded files for tests.
     """
     r = dict([(k, f.name) for k, f in request.FILES.items()])
-    return HttpResponse(simplejson.dumps(r))
+    return HttpResponse(json.dumps(r))
 
 def file_upload_echo_content(request):
     """
     Simple view to echo back the content of uploaded files for tests.
     """
     r = dict([(k, f.read()) for k, f in request.FILES.items()])
-    return HttpResponse(simplejson.dumps(r))
+    return HttpResponse(json.dumps(r))
 
 def file_upload_quota(request):
     """
@@ -120,7 +120,7 @@ def file_upload_getlist_count(request):
 
     for key in request.FILES.keys():
         file_counts[key] = len(request.FILES.getlist(key))
-    return HttpResponse(simplejson.dumps(file_counts))
+    return HttpResponse(json.dumps(file_counts))
 
 def file_upload_errors(request):
     request.upload_handlers.insert(0, ErroringUploadHandler())

+ 3 - 3
tests/regressiontests/test_client_regress/views.py

@@ -1,3 +1,4 @@
+import json
 import warnings
 
 from django.conf import settings
@@ -5,7 +6,6 @@ from django.contrib.auth.decorators import login_required
 from django.http import HttpResponse, HttpResponseRedirect
 from django.core.exceptions import SuspiciousOperation
 from django.shortcuts import render_to_response
-from django.utils import simplejson
 from django.utils.encoding import smart_str
 from django.core.serializers.json import DjangoJSONEncoder
 from django.test.client import CONTENT_TYPE_RE
@@ -81,8 +81,8 @@ def return_json_file(request):
         charset = settings.DEFAULT_CHARSET
 
     # This just checks that the uploaded data is JSON
-    obj_dict = simplejson.loads(request.body.decode(charset))
-    obj_json = simplejson.dumps(obj_dict, encoding=charset,
+    obj_dict = json.loads(request.body.decode(charset))
+    obj_json = json.dumps(obj_dict, encoding=charset,
                                 cls=DjangoJSONEncoder,
                                 ensure_ascii=False)
     response = HttpResponse(smart_str(obj_json, encoding=charset), status=200,

+ 2 - 2
tests/regressiontests/test_utils/tests.py

@@ -491,7 +491,7 @@ class AssertFieldOutputTests(SimpleTestCase):
 __test__ = {"API_TEST": r"""
 # Some checks of the doctest output normalizer.
 # Standard doctests do fairly
->>> from django.utils import simplejson
+>>> import json
 >>> from django.utils.xmlutils import SimplerXMLGenerator
 >>> from StringIO import StringIO
 
@@ -502,7 +502,7 @@ __test__ = {"API_TEST": r"""
 ...     return 42
 
 >>> def produce_json():
-...     return simplejson.dumps(['foo', {'bar': ('baz', None, 1.0, 2), 'whiz': 42}])
+...     return json.dumps(['foo', {'bar': ('baz', None, 1.0, 2), 'whiz': 42}])
 
 >>> def produce_xml():
 ...     stream = StringIO()