Mercurial > repos > yating-l > jbrowsearchivecreator
comparison test/lib/python2.7/_weakrefset.py @ 3:7d1a9a91b989 draft
planemo upload for repository https://github.com/Yating-L/jbrowse-archive-creator.git commit d583ac16a6c6942730ea536eb59cc37941816030-dirty
| author | yating-l |
|---|---|
| date | Thu, 18 May 2017 18:37:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 2:3e2160197902 | 3:7d1a9a91b989 |
|---|---|
| 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 |
