Package dics :: Module opdict
[hide private]
[frames] | no frames]

Source Code for Module dics.opdict

1 -class opdict(dict):
2 """ 3 Minimal order preserving dictionary. Uses a list of keys in addition 4 to an internal dictionary to keep track of the order in which entries are 5 added to the dictionary. Calls to keys(), values(), items(), iterkeys(), 6 itervalues() and iteritems() and popitem() will return data in the order 7 that it was added to the dictionary. 8 9 This class is intended as a drop in replacement for the builtin dict type 10 and replicates all its methods. While the internal representation would 11 enable the addition of mutable sequence methods such as slices these have 12 not (yet) been implemented. 13 14 The motivation for creating this class was to stop the standard library 15 ConfigParser module randomising the order of sections and options when 16 saving modified configs back to a file. 17 18 Anthony Horton 19 horton@ast.cam.ac.uk 20 20050216 21 """ 22
23 - def __init__(self, arg={}, **kwargs):
24 25 # Dictionarys can be initialised with a mapping, an iterator object, 26 # a sequence or (since Python 2.3) keyword arguments. Most of these 27 # methods of initialising don't provide or allow for any preferred 28 # ordering, but if given a sequence type (or corresponding iterator) 29 # we should retain the ordering. 30 31 if kwargs and not arg: 32 # Keyword initialisation 33 dict.__init__(self, kwargs) 34 self.__keylist = dict.keys(self) 35 else: 36 # Have a positional argument which is either a mapping, a sequence, 37 # some other sort of iterable container, or an iterator. 38 39 if hasattr(arg, 'keys'): 40 # Argument is almost certainly some sort of mapping. 41 dict.__init__(self, arg) 42 # Store the keys 43 self.__keylist = arg.keys() 44 45 else: 46 self.__keylist = [] 47 dict.__init__({}) 48 # Argument is either a sequence, some other sort of iterable 49 # container, or an iterator. For all of these should iterate 50 # through in order, added them to the dictionary and keylist. 51 for item in arg: 52 self.__setitem__(*item) 53 54 # May also have some keyword arguments. 55 if kwargs: 56 self.update(kwargs) 57 self.__keylist.extend(kwargs.keys())
58
59 - def __delitem__(self, key):
60 dict.__delitem__(self, key) 61 self.__keylist.remove(key)
62
63 - def __setitem__(self, key, value):
64 has_key = self.has_key(key) 65 dict.__setitem__(self, key, value) 66 if not has_key: 67 self.__keylist.append(key)
68
69 - def __iter__(self):
70 return self.iterkeys()
71
72 - def __str__(self):
73 return '{' + ', '.join(\ 74 [': '.join((repr(key), repr(self[key]))) for key in self.keys()]\ 75 ) + '}'
76
77 - def __repr__(self):
78 return self.__str__()
79
80 - def keys(self):
81 return self.__keylist[:]
82
83 - def values(self):
84 return [self[key] for key in self.keys()]
85
86 - def items(self):
87 return [(key, self[key]) for key in self.keys()]
88
89 - def iterkeys(self):
90 return iter(self.keys())
91
92 - def itervalues(self):
93 return iter(self.values())
94
95 - def iteritems(self):
96 return iter(self.items())
97
98 - def update(self, opd):
99 for key in opd: 100 self[key] = opd[key]
101
102 - def pop(self, key, default=None):
103 if self.has_key(key): 104 value = self[key] 105 del self[key] 106 return value 107 else: 108 if default: 109 return default 110 else: 111 raise KeyError(key)
112
113 - def popitem(self):
114 if not self.__keylist: 115 raise KeyError 116 key = self.__keylist[-1] 117 item = (key, self[key]) 118 del self[key] 119 return item
120
121 - def copy(self):
122 return opdict(self.items())
123
124 - def clear(self):
125 dict.clear(self) 126 self.__keylist = []
127
128 - def fromkeys(keys, value=None):
129 opd = opdict() 130 for key in keys: 131 opd[key] = value 132 return opd
133
134 - def setdefault(self, key, default=None):
135 try: 136 return self[key] 137 except KeyError: 138 self[key] = default 139 return default
140