52 |
52 |
53 class SortedDict(dict): |
53 class SortedDict(dict): |
54 """ |
54 """ |
55 A dictionary that keeps its keys in the order in which they're inserted. |
55 A dictionary that keeps its keys in the order in which they're inserted. |
56 """ |
56 """ |
|
57 def __new__(cls, *args, **kwargs): |
|
58 instance = super(SortedDict, cls).__new__(cls, *args, **kwargs) |
|
59 instance.keyOrder = [] |
|
60 return instance |
|
61 |
57 def __init__(self, data=None): |
62 def __init__(self, data=None): |
58 if data is None: |
63 if data is None: |
59 data = {} |
64 data = {} |
60 super(SortedDict, self).__init__(data) |
65 super(SortedDict, self).__init__(data) |
61 if isinstance(data, dict): |
66 if isinstance(data, dict): |
263 """ |
268 """ |
264 Returns a list of (key, value) pairs, where value is the last item in |
269 Returns a list of (key, value) pairs, where value is the last item in |
265 the list associated with the key. |
270 the list associated with the key. |
266 """ |
271 """ |
267 return [(key, self[key]) for key in self.keys()] |
272 return [(key, self[key]) for key in self.keys()] |
|
273 |
|
274 def iteritems(self): |
|
275 """ |
|
276 Yields (key, value) pairs, where value is the last item in the list |
|
277 associated with the key. |
|
278 """ |
|
279 for key in self.keys(): |
|
280 yield (key, self[key]) |
268 |
281 |
269 def lists(self): |
282 def lists(self): |
270 """Returns a list of (key, list) pairs.""" |
283 """Returns a list of (key, list) pairs.""" |
271 return super(MultiValueDict, self).items() |
284 return super(MultiValueDict, self).items() |
272 |
285 |
330 try: |
343 try: |
331 current[bits[-1]] = v |
344 current[bits[-1]] = v |
332 except TypeError: # Special-case if current isn't a dict. |
345 except TypeError: # Special-case if current isn't a dict. |
333 current = {bits[-1]: v} |
346 current = {bits[-1]: v} |
334 |
347 |
335 class FileDict(dict): |
348 class ImmutableList(tuple): |
336 """ |
349 """ |
337 A dictionary used to hold uploaded file contents. The only special feature |
350 A tuple-like object that raises useful errors when it is asked to mutate. |
338 here is that repr() of this object won't dump the entire contents of the |
351 |
339 file to the output. A handy safeguard for a large file upload. |
352 Example:: |
340 """ |
353 |
341 def __repr__(self): |
354 >>> a = ImmutableList(range(5), warning="You cannot mutate this.") |
342 if 'content' in self: |
355 >>> a[3] = '4' |
343 d = dict(self, content='<omitted>') |
356 Traceback (most recent call last): |
344 return dict.__repr__(d) |
357 ... |
345 return dict.__repr__(self) |
358 AttributeError: You cannot mutate this. |
|
359 """ |
|
360 |
|
361 def __new__(cls, *args, **kwargs): |
|
362 if 'warning' in kwargs: |
|
363 warning = kwargs['warning'] |
|
364 del kwargs['warning'] |
|
365 else: |
|
366 warning = 'ImmutableList object is immutable.' |
|
367 self = tuple.__new__(cls, *args, **kwargs) |
|
368 self.warning = warning |
|
369 return self |
|
370 |
|
371 def complain(self, *wargs, **kwargs): |
|
372 if isinstance(self.warning, Exception): |
|
373 raise self.warning |
|
374 else: |
|
375 raise AttributeError, self.warning |
|
376 |
|
377 # All list mutation functions complain. |
|
378 __delitem__ = complain |
|
379 __delslice__ = complain |
|
380 __iadd__ = complain |
|
381 __imul__ = complain |
|
382 __setitem__ = complain |
|
383 __setslice__ = complain |
|
384 append = complain |
|
385 extend = complain |
|
386 insert = complain |
|
387 pop = complain |
|
388 remove = complain |
|
389 sort = complain |
|
390 reverse = complain |
|
391 |
|
392 class DictWrapper(dict): |
|
393 """ |
|
394 Wraps accesses to a dictionary so that certain values (those starting with |
|
395 the specified prefix) are passed through a function before being returned. |
|
396 The prefix is removed before looking up the real value. |
|
397 |
|
398 Used by the SQL construction code to ensure that values are correctly |
|
399 quoted before being used. |
|
400 """ |
|
401 def __init__(self, data, func, prefix): |
|
402 super(DictWrapper, self).__init__(data) |
|
403 self.func = func |
|
404 self.prefix = prefix |
|
405 |
|
406 def __getitem__(self, key): |
|
407 """ |
|
408 Retrieves the real value after stripping the prefix string (if |
|
409 present). If the prefix is present, pass the value through self.func |
|
410 before returning, otherwise return the raw value. |
|
411 """ |
|
412 if key.startswith(self.prefix): |
|
413 use_func = True |
|
414 key = key[len(self.prefix):] |
|
415 else: |
|
416 use_func = False |
|
417 value = super(DictWrapper, self).__getitem__(key) |
|
418 if use_func: |
|
419 return self.func(value) |
|
420 return value |
|
421 |