Package baxter_dataflow :: Module weakrefset
[hide private]
[frames] | no frames]

Source Code for Module baxter_dataflow.weakrefset

  1  # Copyright (C) 2010 Michael Foord 
  2  # E-mail: fuzzyman AT voidspace DOT org DOT uk 
  3   
  4  # This software is licensed under the terms of the BSD license. 
  5  # http://www.voidspace.org.uk/python/license.shtml 
  6  # https://pypi.python.org/pypi/weakrefset 
  7   
  8  from __future__ import with_statement 
  9   
 10  from _weakref import ref 
 11   
 12  __all__ = ['WeakSet'] 
 13   
 14  __version__ = '1.0.0' 
 15   
 16   
17 -class _IterationGuard(object):
18 # This context manager registers itself in the current iterators of the 19 # weak container, such as to delay all removals until the context manager 20 # exits. 21 # This technique should be relatively thread-safe (since sets are). 22
23 - def __init__(self, weakcontainer):
24 # Don't create cycles 25 self.weakcontainer = ref(weakcontainer)
26
27 - def __enter__(self):
28 w = self.weakcontainer() 29 if w is not None: 30 w._iterating.add(self) 31 return self
32
33 - def __exit__(self, e, t, b):
34 w = self.weakcontainer() 35 if w is not None: 36 s = w._iterating 37 s.remove(self) 38 if not s: 39 w._commit_removals()
40 41
42 -class WeakSet(object):
43 - def __init__(self, data=None):
44 self.data = set() 45 46 def _remove(item, selfref=ref(self)): 47 self = selfref() 48 if self is not None: 49 if self._iterating: 50 self._pending_removals.append(item) 51 else: 52 self.data.discard(item)
53 self._remove = _remove 54 # A list of keys to be removed 55 self._pending_removals = [] 56 self._iterating = set() 57 if data is not None: 58 self.update(data)
59
60 - def _commit_removals(self):
61 l = self._pending_removals 62 discard = self.data.discard 63 while l: 64 discard(l.pop())
65
66 - def __iter__(self):
67 with _IterationGuard(self): 68 for itemref in self.data: 69 item = itemref() 70 if item is not None: 71 yield item
72
73 - def __len__(self):
74 return sum(x() is not None for x in self.data)
75
76 - def __contains__(self, item):
77 return ref(item) in self.data
78
79 - def __reduce__(self):
80 return (self.__class__, (list(self),), 81 getattr(self, '__dict__', None))
82 83 __hash__ = None 84
85 - def add(self, item):
86 if self._pending_removals: 87 self._commit_removals() 88 self.data.add(ref(item, self._remove))
89
90 - def clear(self):
91 if self._pending_removals: 92 self._commit_removals() 93 self.data.clear()
94
95 - def copy(self):
96 return self.__class__(self)
97
98 - def pop(self):
99 if self._pending_removals: 100 self._commit_removals() 101 while True: 102 try: 103 itemref = self.data.pop() 104 except KeyError: 105 raise KeyError('pop from empty WeakSet') 106 item = itemref() 107 if item is not None: 108 return item
109
110 - def remove(self, item):
111 if self._pending_removals: 112 self._commit_removals() 113 self.data.remove(ref(item))
114
115 - def discard(self, item):
116 if self._pending_removals: 117 self._commit_removals() 118 self.data.discard(ref(item))
119
120 - def update(self, other):
121 if self._pending_removals: 122 self._commit_removals() 123 if isinstance(other, self.__class__): 124 self.data.update(other.data) 125 else: 126 for element in other: 127 self.add(element)
128
129 - def __ior__(self, other):
130 self.update(other) 131 return self
132 133 # Helper functions for simple delegating methods.
134 - def _apply(self, other, method):
135 if not isinstance(other, self.__class__): 136 other = self.__class__(other) 137 newdata = method(other.data) 138 newset = self.__class__() 139 newset.data = newdata 140 return newset
141
142 - def difference(self, other):
143 return self._apply(other, self.data.difference)
144 __sub__ = difference 145
146 - def difference_update(self, other):
147 if self._pending_removals: 148 self._commit_removals() 149 if self is other: 150 self.data.clear() 151 else: 152 self.data.difference_update(ref(item) for item in other)
153
154 - def __isub__(self, other):
155 if self._pending_removals: 156 self._commit_removals() 157 if self is other: 158 self.data.clear() 159 else: 160 self.data.difference_update(ref(item) for item in other) 161 return self
162
163 - def intersection(self, other):
164 return self._apply(other, self.data.intersection)
165 __and__ = intersection 166
167 - def intersection_update(self, other):
168 if self._pending_removals: 169 self._commit_removals() 170 self.data.intersection_update(ref(item) for item in other)
171
172 - def __iand__(self, other):
173 if self._pending_removals: 174 self._commit_removals() 175 self.data.intersection_update(ref(item) for item in other) 176 return self
177
178 - def issubset(self, other):
179 return self.data.issubset(ref(item) for item in other)
180 __lt__ = issubset 181
182 - def __le__(self, other):
183 return self.data <= set(ref(item) for item in other)
184
185 - def issuperset(self, other):
186 return self.data.issuperset(ref(item) for item in other)
187 __gt__ = issuperset 188
189 - def __ge__(self, other):
190 return self.data >= set(ref(item) for item in other)
191
192 - def __eq__(self, other):
193 if not isinstance(other, self.__class__): 194 return NotImplemented 195 return self.data == set(ref(item) for item in other)
196
197 - def symmetric_difference(self, other):
198 return self._apply(other, self.data.symmetric_difference)
199 __xor__ = symmetric_difference 200
201 - def symmetric_difference_update(self, other):
202 if self._pending_removals: 203 self._commit_removals() 204 if self is other: 205 self.data.clear() 206 else: 207 self.data.symmetric_difference_update(ref(item) for item in other)
208
209 - def __ixor__(self, other):
210 if self._pending_removals: 211 self._commit_removals() 212 if self is other: 213 self.data.clear() 214 else: 215 self.data.symmetric_difference_update(ref(item) for item in other) 216 return self
217
218 - def union(self, other):
219 return self._apply(other, self.data.union)
220 __or__ = union 221
222 - def isdisjoint(self, other):
223 return len(self.intersection(other)) == 0
224