nullpointer
[dumbwifi.git] / sdict.py
blob705df34ee1e082e6f1dd9c2e8794a623b0d6a4f6
1 #!/usr/bin/env python
3 # Author: Martin Matusiak <numerodix@gmail.com>
4 # Licensed under the GNU Public License, version 3.
6 import regex
9 class sdictlist:
10 def __init__(self, init_list=None, sort_key=None):
11 self.lst = []
12 self.sort_key = sort_key
14 if init_list:
15 for item in init_list:
16 self.append(item)
18 def isvalid(self, dict):
19 if type(dict) == sdict:
20 return True
22 def __str__(self):
23 return self.lst.__str__()
25 def __len__(self):
26 return len(self.lst)
28 def __iter__(self):
29 return iter(self.lst)
31 def clear(self):
32 self.lst = []
34 def append(self, dict):
35 if not self.isvalid(dict):
36 raise Exception, "argument type of %s: %s invalid %s" %\
37 (dict, type(dict), sdict)
38 self.lst.append(dict)
39 self = self.sort(lst=self.lst)
41 def remove(self, index):
42 try: del(self.lst[index])
43 except: pass
45 def extend(self, dl):
46 items = dl.get_all()
47 if items:
48 for item in items:
49 self.append(item)
51 def get_top(self, pred=None):
52 if pred: return filter(pred, self.lst)[0]
53 return self.lst[0]
55 def get_all(self, pred=None):
56 if pred: return filter(pred, self.lst)
57 return self.lst
59 def set_with(self, keyname, keyval, f):
60 f(filter(lambda dct: dct[keyname] == keyval, self.lst)[0])
62 def sort(self, lst=None, sort_key=None, reverse=False):
63 def compare(x, y):
64 # insulate against unset keys
65 if sort_key not in x and sort_key not in y: return 0
66 elif sort_key not in x: return 1
67 if sort_key not in y: return -1
69 # numeric sort if string begins with digits
70 m = regex.find1("(-?[0-9]*)", x[sort_key])
71 n = regex.find1("(-?[0-9]*)", y[sort_key])
72 if m and n:
73 return cmp(int(n), int(m)) # reverse order to get desc
75 return cmp(x[sort_key].lower(), y[sort_key].lower())
77 if not lst: lst = self.lst
78 if not sort_key: sort_key = self.sort_key
79 lst = sorted(lst, compare)
80 if reverse: lst.reverse()
82 l = sdictlist()
83 l.__dict__['lst'] = lst
84 return l
86 def ammend(self, old, new): # update old dict with new data
87 if not new: return old
88 for key in new.keys():
89 if not new[key] or new[key] == "":
90 new[key] = old[key]
91 for key in [x for x in old.keys() if x not in new.keys()]:
92 new[key] = old[key]
93 return new
95 # merge new_dict into dictlist
96 def merge1(self, new_dict, key):
97 dicts = self.lst
98 found = False
99 for (i, dict) in enumerate(dicts):
100 if dict[key] == new_dict[key]:
101 found = True
102 dicts[i] = self.ammend(dict, new_dict)
103 if not found:
104 dicts.append(new_dict)
105 return self.sort(lst=dicts)
107 # merge new dictlist into dictlist
108 def merge(self, new_dicts, key):
109 dicts = self
110 if not new_dicts: return dicts
111 for new_dict in new_dicts:
112 dicts.merge1(new_dict, key)
113 return self.sort(lst=dicts)
116 class sdict(dict):
117 def __init__(self, *args):
118 dict.__init__(self)
120 if args and len(args) == 1:
121 (init_dict,) = args
122 for (key, value) in init_dict.items():
123 self.__setattr__(key, value)
126 ## Helper methods
128 def ___value_is_null___(self, value):
130 # ignore null values and strings with only whitespace
131 if not value or (type(value) == str and value.strip() == ""):
132 return True
135 # Dictionary interface
137 def __setitem__(self, key, value):
138 self.__setattr__(key, value)
140 def __getitem__(self, key):
141 return self.__getattribute__(key)
143 def __delitem__(self, key):
144 self.__delattr__(key)
146 def clear(self):
147 for key in dict.keys(self):
148 self.__delitem__(key)
150 def fromkeys(self, keys, value=None):
151 if keys:
152 new_sdict = sdict()
153 for key in keys: new_sdict.__setitem__(key, value)
154 return new_sdict
156 def pop(self, key, default=None):
157 value = self.__getitem__(key)
158 self.__delitem__(key)
159 if not value: return default
160 return value
162 def popitem(self):
163 try:
164 key = self.keys()[0]
165 return (key, self.pop(key))
166 except IndexError: return None
168 def setdefault(self, key, value=None):
169 v = self.__getitem__(key)
170 if v: return v
171 self.__setitem__(key, value)
172 return value
174 def update(self, pairs):
175 for (key, value) in pairs:
176 self.__setattr__(key, value)
179 # Attribute interface
181 def __setattr__(self, key, value):
182 if not self.___value_is_null___(value):
183 if type(value) == int: value = str(value)
184 dict.__setattr__(self, key, value)
185 dict.__setitem__(self, key, value)
187 def __getattribute__(self, key):
188 try:
189 return dict.__getattribute__(self, key)
190 except AttributeError: return None
192 def __delattr__(self, key):
193 try:
194 dict.__delattr__(self, key)
195 dict.__delitem__(self, key)
196 except: pass
200 if __name__ == "__main__":
201 d = sdict({'a':"3"})
202 print "d.a:", d.a
203 print "d['a']:", d['a']
204 d['name'] = 'dd-wrt'
205 d['a'] = '3'
206 d.b = 1
207 del(d['c'])
208 d.__delattr__('c')
210 print d
211 d.clear()
212 print d
214 d2 = sdict()
215 d2.a = "aa"
216 d2.b = "ab"
217 d2.c = 2
219 d3 = sdict()
220 d3.p = "fa"
221 d3.b = "ce"
222 d3.c = 3
224 d4 = sdict()
225 d4.p = "we"
226 d4.z = "qw"
227 d4.c = 9
229 dl = sdictlist(sort_key="a")
230 print dl.isvalid(d2)
231 dl.append(d2)
232 dl.append(d4)
233 print dl
235 print dl.get_top()
236 print dl.get_top(pred=lambda x: x.a != None)
238 dl2 = sdictlist(sort_key="c")
239 dl2.append(d3)
240 print dl2
241 print dl.merge(dl2, "c")