1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 This is a copy on write dictionary which abuses classes to be nice and fast.
6 Please Note: Be careful when using mutable types (ie Dict and Lists). The copy on write stuff only kicks in on Assignment.
9 from inspect import getmro
13 types.ImmutableTypes = tuple([ \
21 sets.ImmutableSet] + \
22 list(types.StringTypes))
24 MUTABLE = "_mutable__"
26 class COWDictMeta(type):
28 return "<COWDict Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__))
33 __count__ = cls.__count__ + 1
36 def __setitem__(cls, key, value):
37 if not isinstance(value, types.ImmutableTypes):
39 setattr(cls, key, value)
41 def __getmutable__(cls, key):
43 This gets called when you do a "o.b" and b doesn't exist on o.
45 IE When the type is mutable.
48 # Do we already have a copy of this on us?
49 if nkey in cls.__dict__:
50 return cls.__dict__[nkey]
52 r = getattr(cls, nkey)
60 def __getitem__(cls, key):
63 return getattr(cls, key)
64 except AttributeError:
65 # Degrade to slow mode if type is not immutable,
66 # If the type is also a COW this will be cheap anyway
67 return cls.__getmutable__(key)
68 except AttributeError, e:
71 def has_key(cls, key):
72 return (hasattr(cls, key) or hasattr(cls, key + MUTABLE))
76 if key.startswith("__"):
79 if key.endswith(MUTABLE):
80 key = key[:-len(MUTABLE)]
91 return cls.iter("keys")
93 return cls.iter("values")
95 return cls.iter("items")
98 class COWSetMeta(COWDictMeta):
100 return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__))
105 __count__ = cls.__count__ + 1
108 def add(cls, key, value):
109 cls.__setitem__(hash(key), value)
111 class COWDictBase(object):
112 __metaclass__ = COWDictMeta
116 if __name__ == "__main__":
117 a = COWDictBase.copy()
130 for x in a.iteritems():
133 for x in b.iteritems():
140 for x in a.iteritems():
143 for x in b.iteritems():