##// END OF EJS Templates
add ext_json module
marcink -
r2173:775a7672 beta
parent child Browse files
Show More
@@ -0,0 +1,104 b''
1 import datetime
2 import functools
3 import decimal
4
5 __all__ = ['json', 'simplejson', 'stdjson']
6
7
8 def _is_aware(value):
9 """
10 Determines if a given datetime.time is aware.
11
12 The logic is described in Python's docs:
13 http://docs.python.org/library/datetime.html#datetime.tzinfo
14 """
15 return (value.tzinfo is not None
16 and value.tzinfo.utcoffset(value) is not None)
17
18
19 def _obj_dump(obj):
20 """
21 Custom function for dumping objects to JSON, if obj has __json__ attribute
22 or method defined it will be used for serialization
23
24 :param obj:
25 """
26
27 if isinstance(obj, complex):
28 return [obj.real, obj.imag]
29 # See "Date Time String Format" in the ECMA-262 specification.
30 # some code borrowed from django 1.4
31 elif isinstance(obj, datetime.datetime):
32 r = obj.isoformat()
33 if obj.microsecond:
34 r = r[:23] + r[26:]
35 if r.endswith('+00:00'):
36 r = r[:-6] + 'Z'
37 return r
38 elif isinstance(obj, datetime.date):
39 return obj.isoformat()
40 elif isinstance(obj, decimal.Decimal):
41 return str(obj)
42 elif isinstance(obj, datetime.time):
43 if _is_aware(obj):
44 raise ValueError("JSON can't represent timezone-aware times.")
45 r = obj.isoformat()
46 if obj.microsecond:
47 r = r[:12]
48 return r
49 elif isinstance(obj, set):
50 return list(obj)
51 elif hasattr(obj, '__json__'):
52 if callable(obj.__json__):
53 return obj.__json__()
54 else:
55 return obj.__json__
56 else:
57 raise NotImplementedError
58
59
60 # Import simplejson
61 try:
62 # import simplejson initially
63 import simplejson as _sj
64
65 def extended_encode(obj):
66 try:
67 return _obj_dump(obj)
68 except NotImplementedError:
69 pass
70 raise TypeError("%r is not JSON serializable" % (obj,))
71 # we handle decimals our own it makes unified behavior of json vs
72 # simplejson
73 _sj.dumps = functools.partial(_sj.dumps, default=extended_encode,
74 use_decimal=False)
75 _sj.dump = functools.partial(_sj.dump, default=extended_encode,
76 use_decimal=False)
77 simplejson = _sj
78
79 except ImportError:
80 # no simplejson set it to None
81 _sj = None
82
83
84 # simplejson not found try out regular json module
85 import json as _json
86
87
88 # extended JSON encoder for json
89 class ExtendedEncoder(_json.JSONEncoder):
90 def default(self, obj):
91 try:
92 return _obj_dump(obj)
93 except NotImplementedError:
94 pass
95 return _json.JSONEncoder.default(self, obj)
96 # monkey-patch JSON encoder to use extended version
97 _json.dumps = functools.partial(_json.dumps, cls=ExtendedEncoder)
98 _json.dump = functools.partial(_json.dump, cls=ExtendedEncoder)
99 stdlib = _json
100
101 # set all available json modules
102 simplejson = _sj
103 stdjson = _json
104 json = _sj if _sj else _json
@@ -1,476 +1,396 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.compat
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Python backward compatibility functions and common libs
7 7
8 8
9 9 :created_on: Oct 7, 2011
10 10 :author: marcink
11 11 :copyright: (C) 2010-2010 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import os
28 import datetime
29 import functools
30 import decimal
31 28 from rhodecode import __platform__, PLATFORM_WIN
32 29
33 30 #==============================================================================
34 31 # json
35 32 #==============================================================================
36
37
38 def _is_aware(value):
39 """
40 Determines if a given datetime.time is aware.
41
42 The logic is described in Python's docs:
43 http://docs.python.org/library/datetime.html#datetime.tzinfo
44 """
45 return (value.tzinfo is not None
46 and value.tzinfo.utcoffset(value) is not None)
47
48
49 def _obj_dump(obj):
50 """
51 Custom function for dumping objects to JSON, if obj has __json__ attribute
52 or method defined it will be used for serialization
53
54 :param obj:
55 """
56
57 if isinstance(obj, complex):
58 return [obj.real, obj.imag]
59 # See "Date Time String Format" in the ECMA-262 specification.
60 # some code borrowed from django 1.4
61 elif isinstance(obj, datetime.datetime):
62 r = obj.isoformat()
63 if obj.microsecond:
64 r = r[:23] + r[26:]
65 if r.endswith('+00:00'):
66 r = r[:-6] + 'Z'
67 return r
68 elif isinstance(obj, datetime.date):
69 return obj.isoformat()
70 elif isinstance(obj, decimal.Decimal):
71 return str(obj)
72 elif isinstance(obj, datetime.time):
73 if _is_aware(obj):
74 raise ValueError("JSON can't represent timezone-aware times.")
75 r = obj.isoformat()
76 if obj.microsecond:
77 r = r[:12]
78 return r
79 elif isinstance(obj, set):
80 return list(obj)
81 elif isinstance(obj, OrderedDict):
82 return obj.as_dict()
83 elif hasattr(obj, '__json__'):
84 if callable(obj.__json__):
85 return obj.__json__()
86 else:
87 return obj.__json__
88 else:
89 raise NotImplementedError
90
91 try:
92 import json
93
94 # extended JSON encoder for json
95 class ExtendedEncoder(json.JSONEncoder):
96 def default(self, obj):
97 try:
98 return _obj_dump(obj)
99 except NotImplementedError:
100 pass
101 return json.JSONEncoder.default(self, obj)
102 # monkey-patch JSON encoder to use extended version
103 json.dumps = functools.partial(json.dumps, cls=ExtendedEncoder)
104 except ImportError:
105 import simplejson as json
106
107 def extended_encode(obj):
108 try:
109 return _obj_dump(obj)
110 except NotImplementedError:
111 pass
112 raise TypeError("%r is not JSON serializable" % (obj,))
113 json.dumps = functools.partial(json.dumps, default=extended_encode)
33 from rhodecode.lib.ext_json import json
114 34
115 35
116 36 #==============================================================================
117 37 # izip_longest
118 38 #==============================================================================
119 39 try:
120 40 from itertools import izip_longest
121 41 except ImportError:
122 42 import itertools
123 43
124 44 def izip_longest(*args, **kwds):
125 45 fillvalue = kwds.get("fillvalue")
126 46
127 47 def sentinel(counter=([fillvalue] * (len(args) - 1)).pop):
128 48 yield counter() # yields the fillvalue, or raises IndexError
129 49
130 50 fillers = itertools.repeat(fillvalue)
131 51 iters = [itertools.chain(it, sentinel(), fillers)
132 52 for it in args]
133 53 try:
134 54 for tup in itertools.izip(*iters):
135 55 yield tup
136 56 except IndexError:
137 57 pass
138 58
139 59
140 60 #==============================================================================
141 61 # OrderedDict
142 62 #==============================================================================
143 63
144 64 # Python Software Foundation License
145 65
146 66 # XXX: it feels like using the class with "is" and "is not" instead of "==" and
147 67 # "!=" should be faster.
148 68 class _Nil(object):
149 69
150 70 def __repr__(self):
151 71 return "nil"
152 72
153 73 def __eq__(self, other):
154 74 if (isinstance(other, _Nil)):
155 75 return True
156 76 else:
157 77 return NotImplemented
158 78
159 79 def __ne__(self, other):
160 80 if (isinstance(other, _Nil)):
161 81 return False
162 82 else:
163 83 return NotImplemented
164 84
165 85 _nil = _Nil()
166 86
167 87
168 88 class _odict(object):
169 89 """Ordered dict data structure, with O(1) complexity for dict operations
170 90 that modify one element.
171 91
172 92 Overwriting values doesn't change their original sequential order.
173 93 """
174 94
175 95 def _dict_impl(self):
176 96 return None
177 97
178 98 def __init__(self, data=(), **kwds):
179 99 """This doesn't accept keyword initialization as normal dicts to avoid
180 100 a trap - inside a function or method the keyword args are accessible
181 101 only as a dict, without a defined order, so their original order is
182 102 lost.
183 103 """
184 104 if kwds:
185 105 raise TypeError("__init__() of ordered dict takes no keyword "
186 106 "arguments to avoid an ordering trap.")
187 107 self._dict_impl().__init__(self)
188 108 # If you give a normal dict, then the order of elements is undefined
189 109 if hasattr(data, "iteritems"):
190 110 for key, val in data.iteritems():
191 111 self[key] = val
192 112 else:
193 113 for key, val in data:
194 114 self[key] = val
195 115
196 116 # Double-linked list header
197 117 def _get_lh(self):
198 118 dict_impl = self._dict_impl()
199 119 if not hasattr(self, '_lh'):
200 120 dict_impl.__setattr__(self, '_lh', _nil)
201 121 return dict_impl.__getattribute__(self, '_lh')
202 122
203 123 def _set_lh(self, val):
204 124 self._dict_impl().__setattr__(self, '_lh', val)
205 125
206 126 lh = property(_get_lh, _set_lh)
207 127
208 128 # Double-linked list tail
209 129 def _get_lt(self):
210 130 dict_impl = self._dict_impl()
211 131 if not hasattr(self, '_lt'):
212 132 dict_impl.__setattr__(self, '_lt', _nil)
213 133 return dict_impl.__getattribute__(self, '_lt')
214 134
215 135 def _set_lt(self, val):
216 136 self._dict_impl().__setattr__(self, '_lt', val)
217 137
218 138 lt = property(_get_lt, _set_lt)
219 139
220 140 def __getitem__(self, key):
221 141 return self._dict_impl().__getitem__(self, key)[1]
222 142
223 143 def __setitem__(self, key, val):
224 144 dict_impl = self._dict_impl()
225 145 try:
226 146 dict_impl.__getitem__(self, key)[1] = val
227 147 except KeyError:
228 148 new = [dict_impl.__getattribute__(self, 'lt'), val, _nil]
229 149 dict_impl.__setitem__(self, key, new)
230 150 if dict_impl.__getattribute__(self, 'lt') == _nil:
231 151 dict_impl.__setattr__(self, 'lh', key)
232 152 else:
233 153 dict_impl.__getitem__(
234 154 self, dict_impl.__getattribute__(self, 'lt'))[2] = key
235 155 dict_impl.__setattr__(self, 'lt', key)
236 156
237 157 def __delitem__(self, key):
238 158 dict_impl = self._dict_impl()
239 159 pred, _, succ = self._dict_impl().__getitem__(self, key)
240 160 if pred == _nil:
241 161 dict_impl.__setattr__(self, 'lh', succ)
242 162 else:
243 163 dict_impl.__getitem__(self, pred)[2] = succ
244 164 if succ == _nil:
245 165 dict_impl.__setattr__(self, 'lt', pred)
246 166 else:
247 167 dict_impl.__getitem__(self, succ)[0] = pred
248 168 dict_impl.__delitem__(self, key)
249 169
250 170 def __contains__(self, key):
251 171 return key in self.keys()
252 172
253 173 def __len__(self):
254 174 return len(self.keys())
255 175
256 176 def __str__(self):
257 177 pairs = ("%r: %r" % (k, v) for k, v in self.iteritems())
258 178 return "{%s}" % ", ".join(pairs)
259 179
260 180 def __repr__(self):
261 181 if self:
262 182 pairs = ("(%r, %r)" % (k, v) for k, v in self.iteritems())
263 183 return "odict([%s])" % ", ".join(pairs)
264 184 else:
265 185 return "odict()"
266 186
267 187 def get(self, k, x=None):
268 188 if k in self:
269 189 return self._dict_impl().__getitem__(self, k)[1]
270 190 else:
271 191 return x
272 192
273 193 def __iter__(self):
274 194 dict_impl = self._dict_impl()
275 195 curr_key = dict_impl.__getattribute__(self, 'lh')
276 196 while curr_key != _nil:
277 197 yield curr_key
278 198 curr_key = dict_impl.__getitem__(self, curr_key)[2]
279 199
280 200 iterkeys = __iter__
281 201
282 202 def keys(self):
283 203 return list(self.iterkeys())
284 204
285 205 def itervalues(self):
286 206 dict_impl = self._dict_impl()
287 207 curr_key = dict_impl.__getattribute__(self, 'lh')
288 208 while curr_key != _nil:
289 209 _, val, curr_key = dict_impl.__getitem__(self, curr_key)
290 210 yield val
291 211
292 212 def values(self):
293 213 return list(self.itervalues())
294 214
295 215 def iteritems(self):
296 216 dict_impl = self._dict_impl()
297 217 curr_key = dict_impl.__getattribute__(self, 'lh')
298 218 while curr_key != _nil:
299 219 _, val, next_key = dict_impl.__getitem__(self, curr_key)
300 220 yield curr_key, val
301 221 curr_key = next_key
302 222
303 223 def items(self):
304 224 return list(self.iteritems())
305 225
306 226 def sort(self, cmp=None, key=None, reverse=False):
307 227 items = [(k, v) for k, v in self.items()]
308 228 if cmp is not None:
309 229 items = sorted(items, cmp=cmp)
310 230 elif key is not None:
311 231 items = sorted(items, key=key)
312 232 else:
313 233 items = sorted(items, key=lambda x: x[1])
314 234 if reverse:
315 235 items.reverse()
316 236 self.clear()
317 237 self.__init__(items)
318 238
319 239 def clear(self):
320 240 dict_impl = self._dict_impl()
321 241 dict_impl.clear(self)
322 242 dict_impl.__setattr__(self, 'lh', _nil)
323 243 dict_impl.__setattr__(self, 'lt', _nil)
324 244
325 245 def copy(self):
326 246 return self.__class__(self)
327 247
328 248 def update(self, data=(), **kwds):
329 249 if kwds:
330 250 raise TypeError("update() of ordered dict takes no keyword "
331 251 "arguments to avoid an ordering trap.")
332 252 if hasattr(data, "iteritems"):
333 253 data = data.iteritems()
334 254 for key, val in data:
335 255 self[key] = val
336 256
337 257 def setdefault(self, k, x=None):
338 258 try:
339 259 return self[k]
340 260 except KeyError:
341 261 self[k] = x
342 262 return x
343 263
344 264 def pop(self, k, x=_nil):
345 265 try:
346 266 val = self[k]
347 267 del self[k]
348 268 return val
349 269 except KeyError:
350 270 if x == _nil:
351 271 raise
352 272 return x
353 273
354 274 def popitem(self):
355 275 try:
356 276 dict_impl = self._dict_impl()
357 277 key = dict_impl.__getattribute__(self, 'lt')
358 278 return key, self.pop(key)
359 279 except KeyError:
360 280 raise KeyError("'popitem(): ordered dictionary is empty'")
361 281
362 282 def riterkeys(self):
363 283 """To iterate on keys in reversed order.
364 284 """
365 285 dict_impl = self._dict_impl()
366 286 curr_key = dict_impl.__getattribute__(self, 'lt')
367 287 while curr_key != _nil:
368 288 yield curr_key
369 289 curr_key = dict_impl.__getitem__(self, curr_key)[0]
370 290
371 291 __reversed__ = riterkeys
372 292
373 293 def rkeys(self):
374 294 """List of the keys in reversed order.
375 295 """
376 296 return list(self.riterkeys())
377 297
378 298 def ritervalues(self):
379 299 """To iterate on values in reversed order.
380 300 """
381 301 dict_impl = self._dict_impl()
382 302 curr_key = dict_impl.__getattribute__(self, 'lt')
383 303 while curr_key != _nil:
384 304 curr_key, val, _ = dict_impl.__getitem__(self, curr_key)
385 305 yield val
386 306
387 307 def rvalues(self):
388 308 """List of the values in reversed order.
389 309 """
390 310 return list(self.ritervalues())
391 311
392 312 def riteritems(self):
393 313 """To iterate on (key, value) in reversed order.
394 314 """
395 315 dict_impl = self._dict_impl()
396 316 curr_key = dict_impl.__getattribute__(self, 'lt')
397 317 while curr_key != _nil:
398 318 pred_key, val, _ = dict_impl.__getitem__(self, curr_key)
399 319 yield curr_key, val
400 320 curr_key = pred_key
401 321
402 322 def ritems(self):
403 323 """List of the (key, value) in reversed order.
404 324 """
405 325 return list(self.riteritems())
406 326
407 327 def firstkey(self):
408 328 if self:
409 329 return self._dict_impl().__getattribute__(self, 'lh')
410 330 else:
411 331 raise KeyError("'firstkey(): ordered dictionary is empty'")
412 332
413 333 def lastkey(self):
414 334 if self:
415 335 return self._dict_impl().__getattribute__(self, 'lt')
416 336 else:
417 337 raise KeyError("'lastkey(): ordered dictionary is empty'")
418 338
419 339 def as_dict(self):
420 340 return self._dict_impl()(self.items())
421 341
422 342 def _repr(self):
423 343 """_repr(): low level repr of the whole data contained in the odict.
424 344 Useful for debugging.
425 345 """
426 346 dict_impl = self._dict_impl()
427 347 form = "odict low level repr lh,lt,data: %r, %r, %s"
428 348 return form % (dict_impl.__getattribute__(self, 'lh'),
429 349 dict_impl.__getattribute__(self, 'lt'),
430 350 dict_impl.__repr__(self))
431 351
432 352
433 353 class OrderedDict(_odict, dict):
434 354
435 355 def _dict_impl(self):
436 356 return dict
437 357
438 358
439 359 #==============================================================================
440 360 # OrderedSet
441 361 #==============================================================================
442 362 from sqlalchemy.util import OrderedSet
443 363
444 364
445 365 #==============================================================================
446 366 # kill FUNCTIONS
447 367 #==============================================================================
448 368 if __platform__ in PLATFORM_WIN:
449 369 import ctypes
450 370
451 371 def kill(pid, sig):
452 372 """kill function for Win32"""
453 373 kernel32 = ctypes.windll.kernel32
454 374 handle = kernel32.OpenProcess(1, 0, pid)
455 375 return (0 != kernel32.TerminateProcess(handle, 0))
456 376
457 377 else:
458 378 kill = os.kill
459 379
460 380
461 381 #==============================================================================
462 382 # itertools.product
463 383 #==============================================================================
464 384
465 385 try:
466 386 from itertools import product
467 387 except ImportError:
468 388 def product(*args, **kwds):
469 389 # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
470 390 # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
471 391 pools = map(tuple, args) * kwds.get('repeat', 1)
472 392 result = [[]]
473 393 for pool in pools:
474 394 result = [x + [y] for x in result for y in pool]
475 395 for prod in result:
476 396 yield tuple(prod)
General Comments 0
You need to be logged in to leave comments. Login now