diff options
Diffstat (limited to 'parts/django/django/utils/datastructures.py')
-rw-r--r-- | parts/django/django/utils/datastructures.py | 473 |
1 files changed, 0 insertions, 473 deletions
diff --git a/parts/django/django/utils/datastructures.py b/parts/django/django/utils/datastructures.py deleted file mode 100644 index d73963f..0000000 --- a/parts/django/django/utils/datastructures.py +++ /dev/null @@ -1,473 +0,0 @@ -from types import GeneratorType - -from django.utils.copycompat import deepcopy - - -class MergeDict(object): - """ - A simple class for creating new "virtual" dictionaries that actually look - up values in more than one dictionary, passed in the constructor. - - If a key appears in more than one of the given dictionaries, only the - first occurrence will be used. - """ - def __init__(self, *dicts): - self.dicts = dicts - - def __getitem__(self, key): - for dict_ in self.dicts: - try: - return dict_[key] - except KeyError: - pass - raise KeyError - - def __copy__(self): - return self.__class__(*self.dicts) - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - - def getlist(self, key): - for dict_ in self.dicts: - if key in dict_.keys(): - return dict_.getlist(key) - return [] - - def iteritems(self): - seen = set() - for dict_ in self.dicts: - for item in dict_.iteritems(): - k, v = item - if k in seen: - continue - seen.add(k) - yield item - - def iterkeys(self): - for k, v in self.iteritems(): - yield k - - def itervalues(self): - for k, v in self.iteritems(): - yield v - - def items(self): - return list(self.iteritems()) - - def keys(self): - return list(self.iterkeys()) - - def values(self): - return list(self.itervalues()) - - def has_key(self, key): - for dict_ in self.dicts: - if key in dict_: - return True - return False - - __contains__ = has_key - __iter__ = iterkeys - - def copy(self): - """Returns a copy of this object.""" - return self.__copy__() - -class SortedDict(dict): - """ - A dictionary that keeps its keys in the order in which they're inserted. - """ - def __new__(cls, *args, **kwargs): - instance = super(SortedDict, cls).__new__(cls, *args, **kwargs) - instance.keyOrder = [] - return instance - - def __init__(self, data=None): - if data is None: - data = {} - elif isinstance(data, GeneratorType): - # Unfortunately we need to be able to read a generator twice. Once - # to get the data into self with our super().__init__ call and a - # second time to setup keyOrder correctly - data = list(data) - super(SortedDict, self).__init__(data) - if isinstance(data, dict): - self.keyOrder = data.keys() - else: - self.keyOrder = [] - seen = set() - for key, value in data: - if key not in seen: - self.keyOrder.append(key) - seen.add(key) - - def __deepcopy__(self, memo): - return self.__class__([(key, deepcopy(value, memo)) - for key, value in self.iteritems()]) - - def __setitem__(self, key, value): - if key not in self: - self.keyOrder.append(key) - super(SortedDict, self).__setitem__(key, value) - - def __delitem__(self, key): - super(SortedDict, self).__delitem__(key) - self.keyOrder.remove(key) - - def __iter__(self): - return iter(self.keyOrder) - - def pop(self, k, *args): - result = super(SortedDict, self).pop(k, *args) - try: - self.keyOrder.remove(k) - except ValueError: - # Key wasn't in the dictionary in the first place. No problem. - pass - return result - - def popitem(self): - result = super(SortedDict, self).popitem() - self.keyOrder.remove(result[0]) - return result - - def items(self): - return zip(self.keyOrder, self.values()) - - def iteritems(self): - for key in self.keyOrder: - yield key, self[key] - - def keys(self): - return self.keyOrder[:] - - def iterkeys(self): - return iter(self.keyOrder) - - def values(self): - return map(self.__getitem__, self.keyOrder) - - def itervalues(self): - for key in self.keyOrder: - yield self[key] - - def update(self, dict_): - for k, v in dict_.iteritems(): - self[k] = v - - def setdefault(self, key, default): - if key not in self: - self.keyOrder.append(key) - return super(SortedDict, self).setdefault(key, default) - - def value_for_index(self, index): - """Returns the value of the item at the given zero-based index.""" - return self[self.keyOrder[index]] - - def insert(self, index, key, value): - """Inserts the key, value pair before the item with the given index.""" - if key in self.keyOrder: - n = self.keyOrder.index(key) - del self.keyOrder[n] - if n < index: - index -= 1 - self.keyOrder.insert(index, key) - super(SortedDict, self).__setitem__(key, value) - - def copy(self): - """Returns a copy of this object.""" - # This way of initializing the copy means it works for subclasses, too. - obj = self.__class__(self) - obj.keyOrder = self.keyOrder[:] - return obj - - def __repr__(self): - """ - Replaces the normal dict.__repr__ with a version that returns the keys - in their sorted order. - """ - return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()]) - - def clear(self): - super(SortedDict, self).clear() - self.keyOrder = [] - -class MultiValueDictKeyError(KeyError): - pass - -class MultiValueDict(dict): - """ - A subclass of dictionary customized to handle multiple values for the - same key. - - >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) - >>> d['name'] - 'Simon' - >>> d.getlist('name') - ['Adrian', 'Simon'] - >>> d.get('lastname', 'nonexistent') - 'nonexistent' - >>> d.setlist('lastname', ['Holovaty', 'Willison']) - - This class exists to solve the irritating problem raised by cgi.parse_qs, - which returns a list for every key, even though most Web forms submit - single name-value pairs. - """ - def __init__(self, key_to_list_mapping=()): - super(MultiValueDict, self).__init__(key_to_list_mapping) - - def __repr__(self): - return "<%s: %s>" % (self.__class__.__name__, - super(MultiValueDict, self).__repr__()) - - def __getitem__(self, key): - """ - Returns the last data value for this key, or [] if it's an empty list; - raises KeyError if not found. - """ - try: - list_ = super(MultiValueDict, self).__getitem__(key) - except KeyError: - raise MultiValueDictKeyError("Key %r not found in %r" % (key, self)) - try: - return list_[-1] - except IndexError: - return [] - - def __setitem__(self, key, value): - super(MultiValueDict, self).__setitem__(key, [value]) - - def __copy__(self): - return self.__class__(super(MultiValueDict, self).items()) - - def __deepcopy__(self, memo=None): - import django.utils.copycompat as copy - if memo is None: - memo = {} - result = self.__class__() - memo[id(self)] = result - for key, value in dict.items(self): - dict.__setitem__(result, copy.deepcopy(key, memo), - copy.deepcopy(value, memo)) - return result - - def __getstate__(self): - obj_dict = self.__dict__.copy() - obj_dict['_data'] = dict([(k, self.getlist(k)) for k in self]) - return obj_dict - - def __setstate__(self, obj_dict): - data = obj_dict.pop('_data', {}) - for k, v in data.items(): - self.setlist(k, v) - self.__dict__.update(obj_dict) - - def get(self, key, default=None): - """ - Returns the last data value for the passed key. If key doesn't exist - or value is an empty list, then default is returned. - """ - try: - val = self[key] - except KeyError: - return default - if val == []: - return default - return val - - def getlist(self, key): - """ - Returns the list of values for the passed key. If key doesn't exist, - then an empty list is returned. - """ - try: - return super(MultiValueDict, self).__getitem__(key) - except KeyError: - return [] - - def setlist(self, key, list_): - super(MultiValueDict, self).__setitem__(key, list_) - - def setdefault(self, key, default=None): - if key not in self: - self[key] = default - return self[key] - - def setlistdefault(self, key, default_list=()): - if key not in self: - self.setlist(key, default_list) - return self.getlist(key) - - def appendlist(self, key, value): - """Appends an item to the internal list associated with key.""" - self.setlistdefault(key, []) - super(MultiValueDict, self).__setitem__(key, self.getlist(key) + [value]) - - def items(self): - """ - Returns a list of (key, value) pairs, where value is the last item in - the list associated with the key. - """ - return [(key, self[key]) for key in self.keys()] - - def iteritems(self): - """ - Yields (key, value) pairs, where value is the last item in the list - associated with the key. - """ - for key in self.keys(): - yield (key, self[key]) - - def lists(self): - """Returns a list of (key, list) pairs.""" - return super(MultiValueDict, self).items() - - def iterlists(self): - """Yields (key, list) pairs.""" - return super(MultiValueDict, self).iteritems() - - def values(self): - """Returns a list of the last value on every key list.""" - return [self[key] for key in self.keys()] - - def itervalues(self): - """Yield the last value on every key list.""" - for key in self.iterkeys(): - yield self[key] - - def copy(self): - """Returns a copy of this object.""" - return self.__deepcopy__() - - def update(self, *args, **kwargs): - """ - update() extends rather than replaces existing key lists. - Also accepts keyword args. - """ - if len(args) > 1: - raise TypeError("update expected at most 1 arguments, got %d" % len(args)) - if args: - other_dict = args[0] - if isinstance(other_dict, MultiValueDict): - for key, value_list in other_dict.lists(): - self.setlistdefault(key, []).extend(value_list) - else: - try: - for key, value in other_dict.items(): - self.setlistdefault(key, []).append(value) - except TypeError: - raise ValueError("MultiValueDict.update() takes either a MultiValueDict or dictionary") - for key, value in kwargs.iteritems(): - self.setlistdefault(key, []).append(value) - -class DotExpandedDict(dict): - """ - A special dictionary constructor that takes a dictionary in which the keys - may contain dots to specify inner dictionaries. It's confusing, but this - example should make sense. - - >>> d = DotExpandedDict({'person.1.firstname': ['Simon'], \ - 'person.1.lastname': ['Willison'], \ - 'person.2.firstname': ['Adrian'], \ - 'person.2.lastname': ['Holovaty']}) - >>> d - {'person': {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}}} - >>> d['person'] - {'1': {'lastname': ['Willison'], 'firstname': ['Simon']}, '2': {'lastname': ['Holovaty'], 'firstname': ['Adrian']}} - >>> d['person']['1'] - {'lastname': ['Willison'], 'firstname': ['Simon']} - - # Gotcha: Results are unpredictable if the dots are "uneven": - >>> DotExpandedDict({'c.1': 2, 'c.2': 3, 'c': 1}) - {'c': 1} - """ - def __init__(self, key_to_list_mapping): - for k, v in key_to_list_mapping.items(): - current = self - bits = k.split('.') - for bit in bits[:-1]: - current = current.setdefault(bit, {}) - # Now assign value to current position - try: - current[bits[-1]] = v - except TypeError: # Special-case if current isn't a dict. - current = {bits[-1]: v} - -class ImmutableList(tuple): - """ - A tuple-like object that raises useful errors when it is asked to mutate. - - Example:: - - >>> a = ImmutableList(range(5), warning="You cannot mutate this.") - >>> a[3] = '4' - Traceback (most recent call last): - ... - AttributeError: You cannot mutate this. - """ - - def __new__(cls, *args, **kwargs): - if 'warning' in kwargs: - warning = kwargs['warning'] - del kwargs['warning'] - else: - warning = 'ImmutableList object is immutable.' - self = tuple.__new__(cls, *args, **kwargs) - self.warning = warning - return self - - def complain(self, *wargs, **kwargs): - if isinstance(self.warning, Exception): - raise self.warning - else: - raise AttributeError(self.warning) - - # All list mutation functions complain. - __delitem__ = complain - __delslice__ = complain - __iadd__ = complain - __imul__ = complain - __setitem__ = complain - __setslice__ = complain - append = complain - extend = complain - insert = complain - pop = complain - remove = complain - sort = complain - reverse = complain - -class DictWrapper(dict): - """ - Wraps accesses to a dictionary so that certain values (those starting with - the specified prefix) are passed through a function before being returned. - The prefix is removed before looking up the real value. - - Used by the SQL construction code to ensure that values are correctly - quoted before being used. - """ - def __init__(self, data, func, prefix): - super(DictWrapper, self).__init__(data) - self.func = func - self.prefix = prefix - - def __getitem__(self, key): - """ - Retrieves the real value after stripping the prefix string (if - present). If the prefix is present, pass the value through self.func - before returning, otherwise return the raw value. - """ - if key.startswith(self.prefix): - use_func = True - key = key[len(self.prefix):] - else: - use_func = False - value = super(DictWrapper, self).__getitem__(key) - if use_func: - return self.func(value) - return value - |