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