annotate rhodecode/lib/ext_json.py @ 3013:83159d73b13b beta

merge ext_json with upstream
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 18 Nov 2012 20:07:45 +0100
parents 3ae42e10b665
children 685ebc84c2e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
1 import datetime
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
2 import functools
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
3 import decimal
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
4 import imp
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
5
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
6 __all__ = ['json', 'simplejson', 'stdlibjson']
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
7
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
8
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
9 def _is_aware(value):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
10 """
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
11 Determines if a given datetime.time is aware.
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
12
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
13 The logic is described in Python's docs:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
14 http://docs.python.org/library/datetime.html#datetime.tzinfo
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
15 """
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
16 return (value.tzinfo is not None
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
17 and value.tzinfo.utcoffset(value) is not None)
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
18
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
19
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
20 def _obj_dump(obj):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
21 """
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
22 Custom function for dumping objects to JSON, if obj has __json__ attribute
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
23 or method defined it will be used for serialization
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
24
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
25 :param obj:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
26 """
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
27
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
28 if isinstance(obj, complex):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
29 return [obj.real, obj.imag]
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
30 # See "Date Time String Format" in the ECMA-262 specification.
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
31 # some code borrowed from django 1.4
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
32 elif isinstance(obj, datetime.datetime):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
33 r = obj.isoformat()
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
34 if obj.microsecond:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
35 r = r[:23] + r[26:]
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
36 if r.endswith('+00:00'):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
37 r = r[:-6] + 'Z'
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
38 return r
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
39 elif isinstance(obj, datetime.date):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
40 return obj.isoformat()
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
41 elif isinstance(obj, decimal.Decimal):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
42 return str(obj)
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
43 elif isinstance(obj, datetime.time):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
44 if _is_aware(obj):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
45 raise ValueError("JSON can't represent timezone-aware times.")
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
46 r = obj.isoformat()
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
47 if obj.microsecond:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
48 r = r[:12]
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
49 return r
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
50 elif isinstance(obj, set):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
51 return list(obj)
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
52 elif hasattr(obj, '__json__'):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
53 if callable(obj.__json__):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
54 return obj.__json__()
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
55 else:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
56 return obj.__json__
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
57 else:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
58 raise NotImplementedError
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
59
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
60
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
61 # Import simplejson
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
62 try:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
63 # import simplejson initially
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
64 _sj = imp.load_module('_sj', *imp.find_module('simplejson'))
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
65
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
66 def extended_encode(obj):
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
67 try:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
68 return _obj_dump(obj)
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
69 except NotImplementedError:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
70 pass
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
71 raise TypeError("%r is not JSON serializable" % (obj,))
2174
85a64b981c07 ws cleanup, +changelog
Marcin Kuzminski <marcin@python-works.com>
parents: 2173
diff changeset
72 # we handle decimals our own it makes unified behavior of json vs
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
73 # simplejson
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
74 sj_version = [int(x) for x in _sj.__version__.split('.')]
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
75 major, minor = sj_version[0], sj_version[1]
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
76 if major < 2 or (major == 2 and minor < 1):
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
77 # simplejson < 2.1 doesnt support use_decimal
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
78 _sj.dumps = functools.partial(_sj.dumps,
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
79 default=extended_encode)
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
80 _sj.dump = functools.partial(_sj.dump,
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
81 default=extended_encode)
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
82 else:
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
83 _sj.dumps = functools.partial(_sj.dumps,
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
84 default=extended_encode,
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
85 use_decimal=False)
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
86 _sj.dump = functools.partial(_sj.dump,
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
87 default=extended_encode,
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
88 use_decimal=False)
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
89 simplejson = _sj
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
90
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
91 except ImportError:
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
92 # no simplejson set it to None
2528
5c8b1eaafe77 Simplified ext_json thing, for better scope resolution in pydev
Marcin Kuzminski <marcin@python-works.com>
parents: 2258
diff changeset
93 simplejson = None
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
94
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
95
2258
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
96 try:
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
97 # simplejson not found try out regular json module
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
98 _json = imp.load_module('_json', *imp.find_module('json'))
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
99
2258
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
100 # extended JSON encoder for json
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
101 class ExtendedEncoder(_json.JSONEncoder):
2258
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
102 def default(self, obj):
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
103 try:
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
104 return _obj_dump(obj)
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
105 except NotImplementedError:
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
106 pass
2817
3ae42e10b665 fix ext-json extension issue when exception is raised for non-serializable objects
Marcin Kuzminski <marcin@python-works.com>
parents: 2528
diff changeset
107 raise TypeError("%r is not JSON serializable" % (obj,))
2258
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
108 # monkey-patch JSON encoder to use extended version
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
109 _json.dumps = functools.partial(_json.dumps, cls=ExtendedEncoder)
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
110 _json.dump = functools.partial(_json.dump, cls=ExtendedEncoder)
2528
5c8b1eaafe77 Simplified ext_json thing, for better scope resolution in pydev
Marcin Kuzminski <marcin@python-works.com>
parents: 2258
diff changeset
111
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
112 stdlibjson = _json
2258
8a3a1a59a050 Fixed simplejson import on python 2.5
Marcin Kuzminski <marcin@python-works.com>
parents: 2174
diff changeset
113 except ImportError:
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
114 stdlibjson = None
2173
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
115
775a7672d363 add ext_json module
Marcin Kuzminski <marcin@python-works.com>
parents:
diff changeset
116 # set all available json modules
2528
5c8b1eaafe77 Simplified ext_json thing, for better scope resolution in pydev
Marcin Kuzminski <marcin@python-works.com>
parents: 2258
diff changeset
117 if simplejson:
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
118 json = _sj
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
119 elif stdlibjson:
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
120 json = _json
2528
5c8b1eaafe77 Simplified ext_json thing, for better scope resolution in pydev
Marcin Kuzminski <marcin@python-works.com>
parents: 2258
diff changeset
121 else:
3013
83159d73b13b merge ext_json with upstream
Marcin Kuzminski <marcin@python-works.com>
parents: 2817
diff changeset
122 raise ImportError('Could not find any json modules')