blob: 4b2f727225216e25ecdf67794af720635793a0cb [file] [log] [blame]
Eli Benderskye0735d52011-09-08 20:12:44 +03001def recursion_lock(retval, lock_name = "__recursion_lock__"):
2 def decorator(func):
3 def wrapper(self, *args, **kw):
4 if getattr(self, lock_name, False):
5 return retval
6 setattr(self, lock_name, True)
7 try:
8 return func(self, *args, **kw)
9 finally:
10 setattr(self, lock_name, False)
11 wrapper.__name__ = func.__name__
12 return wrapper
13 return decorator
14
15class Container(object):
16 """
17 A generic container of attributes
18 """
19 __slots__ = ["__dict__", "__attrs__"]
20 def __init__(self, **kw):
21 self.__dict__.update(kw)
22 object.__setattr__(self, "__attrs__", kw.keys())
23
24 def __eq__(self, other):
25 try:
26 return self.__dict__ == other.__dict__
27 except AttributeError:
28 return False
29 def __ne__(self, other):
30 return not (self == other)
31
32 def __delattr__(self, name):
33 object.__delattr__(self, name)
34 self.__attrs__.remove(name)
35 def __setattr__(self, name, value):
36 d = self.__dict__
37 if name not in d:
38 self.__attrs__.append(name)
39 d[name] = value
40 def __getitem__(self, name):
41 return self.__dict__[name]
42 def __delitem__(self, name):
43 self.__delattr__(name)
44 def __setitem__(self, name, value):
45 self.__setattr__(name, value)
46 def __update__(self, obj):
47 for name in obj.__attrs__:
48 self[name] = obj[name]
49 def __copy__(self):
50 new = self.__class__()
51 new.__attrs__ = self.__attrs__[:]
52 new.__dict__ = self.__dict__.copy()
53 return new
54
55 @recursion_lock("<...>")
56 def __repr__(self):
57 attrs = sorted("%s = %r" % (k, v)
58 for k, v in self.__dict__.iteritems()
59 if not k.startswith("_"))
60 return "%s(%s)" % (self.__class__.__name__, ", ".join(attrs))
61 def __str__(self):
62 return self.__pretty_str__()
63 @recursion_lock("<...>")
64 def __pretty_str__(self, nesting = 1, indentation = " "):
65 attrs = []
66 ind = indentation * nesting
67 for k in self.__attrs__:
68 v = self.__dict__[k]
69 if not k.startswith("_"):
70 text = [ind, k, " = "]
71 if hasattr(v, "__pretty_str__"):
72 text.append(v.__pretty_str__(nesting + 1, indentation))
73 else:
74 text.append(repr(v))
75 attrs.append("".join(text))
76 if not attrs:
77 return "%s()" % (self.__class__.__name__,)
78 attrs.insert(0, self.__class__.__name__ + ":")
79 return "\n".join(attrs)
80
81class FlagsContainer(Container):
82 """
83 A container providing pretty-printing for flags. Only set flags are
84 displayed.
85 """
86 def __pretty_str__(self, nesting = 1, indentation = " "):
87 attrs = []
88 ind = indentation * nesting
89 for k in self.__attrs__:
90 v = self.__dict__[k]
91 if not k.startswith("_") and v:
92 attrs.append(ind + k)
93 if not attrs:
94 return "%s()" % (self.__class__.__name__,)
95 attrs.insert(0, self.__class__.__name__+ ":")
96 return "\n".join(attrs)
97
98class ListContainer(list):
99 """
100 A container for lists
101 """
102 __slots__ = ["__recursion_lock__"]
103 def __str__(self):
104 return self.__pretty_str__()
105 @recursion_lock("[...]")
106 def __pretty_str__(self, nesting = 1, indentation = " "):
107 if not self:
108 return "[]"
109 ind = indentation * nesting
110 lines = ["["]
111 for elem in self:
112 lines.append("\n")
113 lines.append(ind)
114 if hasattr(elem, "__pretty_str__"):
115 lines.append(elem.__pretty_str__(nesting + 1, indentation))
116 else:
117 lines.append(repr(elem))
118 lines.append("\n")
119 lines.append(indentation * (nesting - 1))
120 lines.append("]")
121 return "".join(lines)
122
123class AttrDict(object):
124 """
125 A dictionary that can be accessed both using indexing and attributes,
126 i.e.,
127 x = AttrDict()
128 x.foo = 5
129 print x["foo"]
130 """
131 __slots__ = ["__dict__"]
132 def __init__(self, **kw):
133 self.__dict__ = kw
134 def __contains__(self, key):
135 return key in self.__dict__
136 def __nonzero__(self):
137 return bool(self.__dict__)
138 def __repr__(self):
139 return repr(self.__dict__)
140 def __str__(self):
141 return self.__pretty_str__()
142 def __pretty_str__(self, nesting = 1, indentation = " "):
143 if not self:
144 return "{}"
145 text = ["{\n"]
146 ind = nesting * indentation
147 for k in sorted(self.__dict__.keys()):
148 v = self.__dict__[k]
149 text.append(ind)
150 text.append(repr(k))
151 text.append(" : ")
152 if hasattr(v, "__pretty_str__"):
153 try:
154 text.append(v.__pretty_str__(nesting+1, indentation))
155 except Exception:
156 text.append(repr(v))
157 else:
158 text.append(repr(v))
159 text.append("\n")
160 text.append((nesting-1) * indentation)
161 text.append("}")
162 return "".join(text)
163 def __delitem__(self, key):
164 del self.__dict__[key]
165 def __getitem__(self, key):
166 return self.__dict__[key]
167 def __setitem__(self, key, value):
168 self.__dict__[key] = value
169 def __copy__(self):
170 new = self.__class__()
171 new.__dict__ = self.__dict__.copy()
172 return new
173 def __update__(self, other):
174 if isinstance(other, dict):
175 self.__dict__.update(other)
176 else:
177 self.__dict__.update(other.__dict__)
178
179class LazyContainer(object):
180 __slots__ = ["subcon", "stream", "pos", "context", "_value"]
181 def __init__(self, subcon, stream, pos, context):
182 self.subcon = subcon
183 self.stream = stream
184 self.pos = pos
185 self.context = context
186 self._value = NotImplemented
187 def __eq__(self, other):
188 try:
189 return self._value == other._value
190 except AttributeError:
191 return False
192 def __ne__(self, other):
193 return not (self == other)
194 def __str__(self):
195 return self.__pretty_str__()
196 def __pretty_str__(self, nesting = 1, indentation = " "):
197 if self._value is NotImplemented:
198 text = "<unread>"
199 elif hasattr(self._value, "__pretty_str__"):
200 text = self._value.__pretty_str__(nesting, indentation)
201 else:
202 text = repr(self._value)
203 return "%s: %s" % (self.__class__.__name__, text)
204 def read(self):
205 self.stream.seek(self.pos)
206 return self.subcon._parse(self.stream, self.context)
207 def dispose(self):
208 self.subcon = None
209 self.stream = None
210 self.context = None
211 self.pos = None
212 def _get_value(self):
213 if self._value is NotImplemented:
214 self._value = self.read()
215 return self._value
216 value = property(_get_value)
217 has_value = property(lambda self: self._value is not NotImplemented)
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258