e62faef2cb136e0984e8dceb7a1bfdfe2c698611
[redakcja.git] / apps / compress / filters / csstidy_python / tools.py
1
2 class SortedDict(dict):
3     """
4     A dictionary that keeps its keys in the order in which they're inserted.
5     """
6     def __init__(self, data=None):
7         if data is None:
8             data = {}
9         super(SortedDict, self).__init__(data)
10         if isinstance(data, dict):
11             self.keyOrder = data.keys()
12         else:
13             self.keyOrder = []
14             for key, value in data:
15                 if key not in self.keyOrder:
16                     self.keyOrder.append(key)
17
18     def __deepcopy__(self, memo):
19         from copy import deepcopy
20         return self.__class__([(key, deepcopy(value, memo))
21                                for key, value in self.iteritems()])
22
23     def __setitem__(self, key, value):
24         super(SortedDict, self).__setitem__(key, value)
25         if key not in self.keyOrder:
26             self.keyOrder.append(key)
27
28     def __delitem__(self, key):
29         super(SortedDict, self).__delitem__(key)
30         self.keyOrder.remove(key)
31
32     def __iter__(self):
33         for k in self.keyOrder:
34             yield k
35
36     def pop(self, k, *args):
37         result = super(SortedDict, self).pop(k, *args)
38         try:
39             self.keyOrder.remove(k)
40         except ValueError:
41             # Key wasn't in the dictionary in the first place. No problem.
42             pass
43         return result
44
45     def popitem(self):
46         result = super(SortedDict, self).popitem()
47         self.keyOrder.remove(result[0])
48         return result
49
50     def items(self):
51         return zip(self.keyOrder, self.values())
52
53     def iteritems(self):
54         for key in self.keyOrder:
55             yield key, super(SortedDict, self).__getitem__(key)
56
57     def keys(self):
58         return self.keyOrder[:]
59
60     def iterkeys(self):
61         return iter(self.keyOrder)
62
63     def values(self):
64         return [super(SortedDict, self).__getitem__(k) for k in self.keyOrder]
65
66     def itervalues(self):
67         for key in self.keyOrder:
68             yield super(SortedDict, self).__getitem__(key)
69
70     def update(self, dict_):
71         for k, v in dict_.items():
72             self.__setitem__(k, v)
73
74     def setdefault(self, key, default):
75         if key not in self.keyOrder:
76             self.keyOrder.append(key)
77         return super(SortedDict, self).setdefault(key, default)
78
79     def value_for_index(self, index):
80         """Returns the value of the item at the given zero-based index."""
81         return self[self.keyOrder[index]]
82
83     def insert(self, index, key, value):
84         """Inserts the key, value pair before the item with the given index."""
85         if key in self.keyOrder:
86             n = self.keyOrder.index(key)
87             del self.keyOrder[n]
88             if n < index:
89                 index -= 1
90         self.keyOrder.insert(index, key)
91         super(SortedDict, self).__setitem__(key, value)
92
93     def copy(self):
94         """Returns a copy of this object."""
95         # This way of initializing the copy means it works for subclasses, too.
96         obj = self.__class__(self)
97         obj.keyOrder = self.keyOrder[:]
98         return obj
99
100     def __repr__(self):
101         """
102         Replaces the normal dict.__repr__ with a version that returns the keys
103         in their sorted order.
104         """
105         return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()])
106
107     def clear(self):
108         super(SortedDict, self).clear()
109         self.keyOrder = []