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