Mercurial > repos > bcclaywell > argo_navis
comparison venv/lib/python2.7/_weakrefset.py @ 0:d67268158946 draft
planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author | bcclaywell |
---|---|
date | Mon, 12 Oct 2015 17:43:33 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d67268158946 |
---|---|
1 # Access WeakSet through the weakref module. | |
2 # This code is separated-out because it is needed | |
3 # by abc.py to load everything else at startup. | |
4 | |
5 from _weakref import ref | |
6 | |
7 __all__ = ['WeakSet'] | |
8 | |
9 | |
10 class _IterationGuard(object): | |
11 # This context manager registers itself in the current iterators of the | |
12 # weak container, such as to delay all removals until the context manager | |
13 # exits. | |
14 # This technique should be relatively thread-safe (since sets are). | |
15 | |
16 def __init__(self, weakcontainer): | |
17 # Don't create cycles | |
18 self.weakcontainer = ref(weakcontainer) | |
19 | |
20 def __enter__(self): | |
21 w = self.weakcontainer() | |
22 if w is not None: | |
23 w._iterating.add(self) | |
24 return self | |
25 | |
26 def __exit__(self, e, t, b): | |
27 w = self.weakcontainer() | |
28 if w is not None: | |
29 s = w._iterating | |
30 s.remove(self) | |
31 if not s: | |
32 w._commit_removals() | |
33 | |
34 | |
35 class WeakSet(object): | |
36 def __init__(self, data=None): | |
37 self.data = set() | |
38 def _remove(item, selfref=ref(self)): | |
39 self = selfref() | |
40 if self is not None: | |
41 if self._iterating: | |
42 self._pending_removals.append(item) | |
43 else: | |
44 self.data.discard(item) | |
45 self._remove = _remove | |
46 # A list of keys to be removed | |
47 self._pending_removals = [] | |
48 self._iterating = set() | |
49 if data is not None: | |
50 self.update(data) | |
51 | |
52 def _commit_removals(self): | |
53 l = self._pending_removals | |
54 discard = self.data.discard | |
55 while l: | |
56 discard(l.pop()) | |
57 | |
58 def __iter__(self): | |
59 with _IterationGuard(self): | |
60 for itemref in self.data: | |
61 item = itemref() | |
62 if item is not None: | |
63 # Caveat: the iterator will keep a strong reference to | |
64 # `item` until it is resumed or closed. | |
65 yield item | |
66 | |
67 def __len__(self): | |
68 return len(self.data) - len(self._pending_removals) | |
69 | |
70 def __contains__(self, item): | |
71 try: | |
72 wr = ref(item) | |
73 except TypeError: | |
74 return False | |
75 return wr in self.data | |
76 | |
77 def __reduce__(self): | |
78 return (self.__class__, (list(self),), | |
79 getattr(self, '__dict__', None)) | |
80 | |
81 __hash__ = None | |
82 | |
83 def add(self, item): | |
84 if self._pending_removals: | |
85 self._commit_removals() | |
86 self.data.add(ref(item, self._remove)) | |
87 | |
88 def clear(self): | |
89 if self._pending_removals: | |
90 self._commit_removals() | |
91 self.data.clear() | |
92 | |
93 def copy(self): | |
94 return self.__class__(self) | |
95 | |
96 def pop(self): | |
97 if self._pending_removals: | |
98 self._commit_removals() | |
99 while True: | |
100 try: | |
101 itemref = self.data.pop() | |
102 except KeyError: | |
103 raise KeyError('pop from empty WeakSet') | |
104 item = itemref() | |
105 if item is not None: | |
106 return item | |
107 | |
108 def remove(self, item): | |
109 if self._pending_removals: | |
110 self._commit_removals() | |
111 self.data.remove(ref(item)) | |
112 | |
113 def discard(self, item): | |
114 if self._pending_removals: | |
115 self._commit_removals() | |
116 self.data.discard(ref(item)) | |
117 | |
118 def update(self, other): | |
119 if self._pending_removals: | |
120 self._commit_removals() | |
121 for element in other: | |
122 self.add(element) | |
123 | |
124 def __ior__(self, other): | |
125 self.update(other) | |
126 return self | |
127 | |
128 def difference(self, other): | |
129 newset = self.copy() | |
130 newset.difference_update(other) | |
131 return newset | |
132 __sub__ = difference | |
133 | |
134 def difference_update(self, other): | |
135 self.__isub__(other) | |
136 def __isub__(self, other): | |
137 if self._pending_removals: | |
138 self._commit_removals() | |
139 if self is other: | |
140 self.data.clear() | |
141 else: | |
142 self.data.difference_update(ref(item) for item in other) | |
143 return self | |
144 | |
145 def intersection(self, other): | |
146 return self.__class__(item for item in other if item in self) | |
147 __and__ = intersection | |
148 | |
149 def intersection_update(self, other): | |
150 self.__iand__(other) | |
151 def __iand__(self, other): | |
152 if self._pending_removals: | |
153 self._commit_removals() | |
154 self.data.intersection_update(ref(item) for item in other) | |
155 return self | |
156 | |
157 def issubset(self, other): | |
158 return self.data.issubset(ref(item) for item in other) | |
159 __le__ = issubset | |
160 | |
161 def __lt__(self, other): | |
162 return self.data < set(ref(item) for item in other) | |
163 | |
164 def issuperset(self, other): | |
165 return self.data.issuperset(ref(item) for item in other) | |
166 __ge__ = issuperset | |
167 | |
168 def __gt__(self, other): | |
169 return self.data > set(ref(item) for item in other) | |
170 | |
171 def __eq__(self, other): | |
172 if not isinstance(other, self.__class__): | |
173 return NotImplemented | |
174 return self.data == set(ref(item) for item in other) | |
175 | |
176 def __ne__(self, other): | |
177 opposite = self.__eq__(other) | |
178 if opposite is NotImplemented: | |
179 return NotImplemented | |
180 return not opposite | |
181 | |
182 def symmetric_difference(self, other): | |
183 newset = self.copy() | |
184 newset.symmetric_difference_update(other) | |
185 return newset | |
186 __xor__ = symmetric_difference | |
187 | |
188 def symmetric_difference_update(self, other): | |
189 self.__ixor__(other) | |
190 def __ixor__(self, other): | |
191 if self._pending_removals: | |
192 self._commit_removals() | |
193 if self is other: | |
194 self.data.clear() | |
195 else: | |
196 self.data.symmetric_difference_update(ref(item, self._remove) for item in other) | |
197 return self | |
198 | |
199 def union(self, other): | |
200 return self.__class__(e for s in (self, other) for e in s) | |
201 __or__ = union | |
202 | |
203 def isdisjoint(self, other): | |
204 return len(self.intersection(other)) == 0 |