summaryrefslogtreecommitdiffstats
path: root/bitbake-dev/lib/bb/COW.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake-dev/lib/bb/COW.py')
-rw-r--r--bitbake-dev/lib/bb/COW.py318
1 files changed, 0 insertions, 318 deletions
diff --git a/bitbake-dev/lib/bb/COW.py b/bitbake-dev/lib/bb/COW.py
deleted file mode 100644
index ca206cf4b4..0000000000
--- a/bitbake-dev/lib/bb/COW.py
+++ /dev/null
@@ -1,318 +0,0 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# This is a copy on write dictionary and set which abuses classes to try and be nice and fast.
5#
6# Copyright (C) 2006 Tim Amsell
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License version 2 as
10# published by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21#Please Note:
22# Be careful when using mutable types (ie Dict and Lists) - operations involving these are SLOW.
23# Assign a file to __warn__ to get warnings about slow operations.
24#
25
26import copy
27import types
28types.ImmutableTypes = tuple([ \
29 types.BooleanType, \
30 types.ComplexType, \
31 types.FloatType, \
32 types.IntType, \
33 types.LongType, \
34 types.NoneType, \
35 types.TupleType, \
36 frozenset] + \
37 list(types.StringTypes))
38
39MUTABLE = "__mutable__"
40
41class COWMeta(type):
42 pass
43
44class COWDictMeta(COWMeta):
45 __warn__ = False
46 __hasmutable__ = False
47 __marker__ = tuple()
48
49 def __str__(cls):
50 # FIXME: I have magic numbers!
51 return "<COWDict Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) - 3)
52 __repr__ = __str__
53
54 def cow(cls):
55 class C(cls):
56 __count__ = cls.__count__ + 1
57 return C
58 copy = cow
59 __call__ = cow
60
61 def __setitem__(cls, key, value):
62 if not isinstance(value, types.ImmutableTypes):
63 if not isinstance(value, COWMeta):
64 cls.__hasmutable__ = True
65 key += MUTABLE
66 setattr(cls, key, value)
67
68 def __getmutable__(cls, key, readonly=False):
69 nkey = key + MUTABLE
70 try:
71 return cls.__dict__[nkey]
72 except KeyError:
73 pass
74
75 value = getattr(cls, nkey)
76 if readonly:
77 return value
78
79 if not cls.__warn__ is False and not isinstance(value, COWMeta):
80 print >> cls.__warn__, "Warning: Doing a copy because %s is a mutable type." % key
81 try:
82 value = value.copy()
83 except AttributeError, e:
84 value = copy.copy(value)
85 setattr(cls, nkey, value)
86 return value
87
88 __getmarker__ = []
89 def __getreadonly__(cls, key, default=__getmarker__):
90 """\
91 Get a value (even if mutable) which you promise not to change.
92 """
93 return cls.__getitem__(key, default, True)
94
95 def __getitem__(cls, key, default=__getmarker__, readonly=False):
96 try:
97 try:
98 value = getattr(cls, key)
99 except AttributeError:
100 value = cls.__getmutable__(key, readonly)
101
102 # This is for values which have been deleted
103 if value is cls.__marker__:
104 raise AttributeError("key %s does not exist." % key)
105
106 return value
107 except AttributeError, e:
108 if not default is cls.__getmarker__:
109 return default
110
111 raise KeyError(str(e))
112
113 def __delitem__(cls, key):
114 cls.__setitem__(key, cls.__marker__)
115
116 def __revertitem__(cls, key):
117 if not cls.__dict__.has_key(key):
118 key += MUTABLE
119 delattr(cls, key)
120
121 def has_key(cls, key):
122 value = cls.__getreadonly__(key, cls.__marker__)
123 if value is cls.__marker__:
124 return False
125 return True
126
127 def iter(cls, type, readonly=False):
128 for key in dir(cls):
129 if key.startswith("__"):
130 continue
131
132 if key.endswith(MUTABLE):
133 key = key[:-len(MUTABLE)]
134
135 if type == "keys":
136 yield key
137
138 try:
139 if readonly:
140 value = cls.__getreadonly__(key)
141 else:
142 value = cls[key]
143 except KeyError:
144 continue
145
146 if type == "values":
147 yield value
148 if type == "items":
149 yield (key, value)
150 raise StopIteration()
151
152 def iterkeys(cls):
153 return cls.iter("keys")
154 def itervalues(cls, readonly=False):
155 if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
156 print >> cls.__warn__, "Warning: If you arn't going to change any of the values call with True."
157 return cls.iter("values", readonly)
158 def iteritems(cls, readonly=False):
159 if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
160 print >> cls.__warn__, "Warning: If you arn't going to change any of the values call with True."
161 return cls.iter("items", readonly)
162
163class COWSetMeta(COWDictMeta):
164 def __str__(cls):
165 # FIXME: I have magic numbers!
166 return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) -3)
167 __repr__ = __str__
168
169 def cow(cls):
170 class C(cls):
171 __count__ = cls.__count__ + 1
172 return C
173
174 def add(cls, value):
175 COWDictMeta.__setitem__(cls, repr(hash(value)), value)
176
177 def remove(cls, value):
178 COWDictMeta.__delitem__(cls, repr(hash(value)))
179
180 def __in__(cls, value):
181 return COWDictMeta.has_key(repr(hash(value)))
182
183 def iterkeys(cls):
184 raise TypeError("sets don't have keys")
185
186 def iteritems(cls):
187 raise TypeError("sets don't have 'items'")
188
189# These are the actual classes you use!
190class COWDictBase(object):
191 __metaclass__ = COWDictMeta
192 __count__ = 0
193
194class COWSetBase(object):
195 __metaclass__ = COWSetMeta
196 __count__ = 0
197
198if __name__ == "__main__":
199 import sys
200 COWDictBase.__warn__ = sys.stderr
201 a = COWDictBase()
202 print "a", a
203
204 a['a'] = 'a'
205 a['b'] = 'b'
206 a['dict'] = {}
207
208 b = a.copy()
209 print "b", b
210 b['c'] = 'b'
211
212 print
213
214 print "a", a
215 for x in a.iteritems():
216 print x
217 print "--"
218 print "b", b
219 for x in b.iteritems():
220 print x
221 print
222
223 b['dict']['a'] = 'b'
224 b['a'] = 'c'
225
226 print "a", a
227 for x in a.iteritems():
228 print x
229 print "--"
230 print "b", b
231 for x in b.iteritems():
232 print x
233 print
234
235 try:
236 b['dict2']
237 except KeyError, e:
238 print "Okay!"
239
240 a['set'] = COWSetBase()
241 a['set'].add("o1")
242 a['set'].add("o1")
243 a['set'].add("o2")
244
245 print "a", a
246 for x in a['set'].itervalues():
247 print x
248 print "--"
249 print "b", b
250 for x in b['set'].itervalues():
251 print x
252 print
253
254 b['set'].add('o3')
255
256 print "a", a
257 for x in a['set'].itervalues():
258 print x
259 print "--"
260 print "b", b
261 for x in b['set'].itervalues():
262 print x
263 print
264
265 a['set2'] = set()
266 a['set2'].add("o1")
267 a['set2'].add("o1")
268 a['set2'].add("o2")
269
270 print "a", a
271 for x in a.iteritems():
272 print x
273 print "--"
274 print "b", b
275 for x in b.iteritems(readonly=True):
276 print x
277 print
278
279 del b['b']
280 try:
281 print b['b']
282 except KeyError:
283 print "Yay! deleted key raises error"
284
285 if b.has_key('b'):
286 print "Boo!"
287 else:
288 print "Yay - has_key with delete works!"
289
290 print "a", a
291 for x in a.iteritems():
292 print x
293 print "--"
294 print "b", b
295 for x in b.iteritems(readonly=True):
296 print x
297 print
298
299 b.__revertitem__('b')
300
301 print "a", a
302 for x in a.iteritems():
303 print x
304 print "--"
305 print "b", b
306 for x in b.iteritems(readonly=True):
307 print x
308 print
309
310 b.__revertitem__('dict')
311 print "a", a
312 for x in a.iteritems():
313 print x
314 print "--"
315 print "b", b
316 for x in b.iteritems(readonly=True):
317 print x
318 print