changeset 2173:775a7672d363 beta

add ext_json module
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 28 Mar 2012 23:11:49 +0200
parents 28d9893d6a23
children 85a64b981c07
files rhodecode/lib/compat.py rhodecode/lib/ext_json.py
diffstat 2 files changed, 105 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/lib/compat.py	Wed Mar 28 22:53:51 2012 +0200
+++ b/rhodecode/lib/compat.py	Wed Mar 28 23:11:49 2012 +0200
@@ -25,92 +25,12 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import os
-import datetime
-import functools
-import decimal
 from rhodecode import __platform__, PLATFORM_WIN
 
 #==============================================================================
 # json
 #==============================================================================
-
-
-def _is_aware(value):
-    """
-    Determines if a given datetime.time is aware.
-
-    The logic is described in Python's docs:
-    http://docs.python.org/library/datetime.html#datetime.tzinfo
-    """
-    return (value.tzinfo is not None
-            and value.tzinfo.utcoffset(value) is not None)
-
-
-def _obj_dump(obj):
-    """
-    Custom function for dumping objects to JSON, if obj has __json__ attribute
-    or method defined it will be used for serialization
-
-    :param obj:
-    """
-
-    if isinstance(obj, complex):
-        return [obj.real, obj.imag]
-    # See "Date Time String Format" in the ECMA-262 specification.
-    # some code borrowed from django 1.4
-    elif isinstance(obj, datetime.datetime):
-        r = obj.isoformat()
-        if obj.microsecond:
-            r = r[:23] + r[26:]
-        if r.endswith('+00:00'):
-            r = r[:-6] + 'Z'
-        return r
-    elif isinstance(obj, datetime.date):
-        return obj.isoformat()
-    elif isinstance(obj, decimal.Decimal):
-        return str(obj)
-    elif isinstance(obj, datetime.time):
-        if _is_aware(obj):
-            raise ValueError("JSON can't represent timezone-aware times.")
-        r = obj.isoformat()
-        if obj.microsecond:
-            r = r[:12]
-        return r
-    elif isinstance(obj, set):
-        return list(obj)
-    elif isinstance(obj, OrderedDict):
-        return obj.as_dict()
-    elif hasattr(obj, '__json__'):
-        if callable(obj.__json__):
-            return obj.__json__()
-        else:
-            return obj.__json__
-    else:
-        raise NotImplementedError
-
-try:
-    import json
-
-    # extended JSON encoder for json
-    class ExtendedEncoder(json.JSONEncoder):
-        def default(self, obj):
-            try:
-                return _obj_dump(obj)
-            except NotImplementedError:
-                pass
-            return json.JSONEncoder.default(self, obj)
-    # monkey-patch JSON encoder to use extended version
-    json.dumps = functools.partial(json.dumps, cls=ExtendedEncoder)
-except ImportError:
-    import simplejson as json
-
-    def extended_encode(obj):
-        try:
-            return _obj_dump(obj)
-        except NotImplementedError:
-            pass
-        raise TypeError("%r is not JSON serializable" % (obj,))
-    json.dumps = functools.partial(json.dumps, default=extended_encode)
+from rhodecode.lib.ext_json import json
 
 
 #==============================================================================
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/lib/ext_json.py	Wed Mar 28 23:11:49 2012 +0200
@@ -0,0 +1,104 @@
+import datetime
+import functools
+import decimal
+
+__all__ = ['json', 'simplejson', 'stdjson']
+
+
+def _is_aware(value):
+    """
+    Determines if a given datetime.time is aware.
+
+    The logic is described in Python's docs:
+    http://docs.python.org/library/datetime.html#datetime.tzinfo
+    """
+    return (value.tzinfo is not None
+            and value.tzinfo.utcoffset(value) is not None)
+
+
+def _obj_dump(obj):
+    """
+    Custom function for dumping objects to JSON, if obj has __json__ attribute
+    or method defined it will be used for serialization
+
+    :param obj:
+    """
+
+    if isinstance(obj, complex):
+        return [obj.real, obj.imag]
+    # See "Date Time String Format" in the ECMA-262 specification.
+    # some code borrowed from django 1.4
+    elif isinstance(obj, datetime.datetime):
+        r = obj.isoformat()
+        if obj.microsecond:
+            r = r[:23] + r[26:]
+        if r.endswith('+00:00'):
+            r = r[:-6] + 'Z'
+        return r
+    elif isinstance(obj, datetime.date):
+        return obj.isoformat()
+    elif isinstance(obj, decimal.Decimal):
+        return str(obj)
+    elif isinstance(obj, datetime.time):
+        if _is_aware(obj):
+            raise ValueError("JSON can't represent timezone-aware times.")
+        r = obj.isoformat()
+        if obj.microsecond:
+            r = r[:12]
+        return r
+    elif isinstance(obj, set):
+        return list(obj)
+    elif hasattr(obj, '__json__'):
+        if callable(obj.__json__):
+            return obj.__json__()
+        else:
+            return obj.__json__
+    else:
+        raise NotImplementedError
+
+
+# Import simplejson
+try:
+    # import simplejson initially
+    import simplejson as _sj
+
+    def extended_encode(obj):
+        try:
+            return _obj_dump(obj)
+        except NotImplementedError:
+            pass
+        raise TypeError("%r is not JSON serializable" % (obj,))
+    # we handle decimals our own it makes unified behavior of json vs 
+    # simplejson
+    _sj.dumps = functools.partial(_sj.dumps, default=extended_encode,
+                                  use_decimal=False)
+    _sj.dump = functools.partial(_sj.dump, default=extended_encode,
+                                 use_decimal=False)
+    simplejson = _sj
+
+except ImportError:
+    # no simplejson set it to None
+    _sj = None
+
+
+# simplejson not found try out regular json module
+import json as _json
+
+
+# extended JSON encoder for json
+class ExtendedEncoder(_json.JSONEncoder):
+    def default(self, obj):
+        try:
+            return _obj_dump(obj)
+        except NotImplementedError:
+            pass
+        return _json.JSONEncoder.default(self, obj)
+# monkey-patch JSON encoder to use extended version
+_json.dumps = functools.partial(_json.dumps, cls=ExtendedEncoder)
+_json.dump = functools.partial(_json.dump, cls=ExtendedEncoder)
+stdlib = _json
+
+# set all available json modules
+simplejson = _sj
+stdjson = _json
+json = _sj if _sj else _json