Show More
Commit Description:
Merge pull request #17 from nattee/master...
Commit Description:
Merge pull request #17 from nattee/master
upgrade to current working snapshot
References:
File last commit:
Show/Diff file:
Action:
lib/assets/Lib/_weakrefset.py
| 194 lines
| 5.6 KiB
| text/x-python
| PythonLexer
|
r584 | # Access WeakSet through the weakref module. | |||
# This code is separated-out because it is needed | ||||
# by abc.py to load everything else at startup. | ||||
from _weakref import ref | ||||
__all__ = ['WeakSet'] | ||||
class _IterationGuard: | ||||
# This context manager registers itself in the current iterators of the | ||||
# weak container, such as to delay all removals until the context manager | ||||
# exits. | ||||
# This technique should be relatively thread-safe (since sets are). | ||||
def __init__(self, weakcontainer): | ||||
# Don't create cycles | ||||
self.weakcontainer = ref(weakcontainer) | ||||
def __enter__(self): | ||||
w = self.weakcontainer() | ||||
if w is not None: | ||||
w._iterating.add(self) | ||||
return self | ||||
def __exit__(self, e, t, b): | ||||
w = self.weakcontainer() | ||||
if w is not None: | ||||
s = w._iterating | ||||
s.remove(self) | ||||
if not s: | ||||
w._commit_removals() | ||||
class WeakSet: | ||||
def __init__(self, data=None): | ||||
self.data = set() | ||||
def _remove(item, selfref=ref(self)): | ||||
self = selfref() | ||||
if self is not None: | ||||
if self._iterating: | ||||
self._pending_removals.append(item) | ||||
else: | ||||
self.data.discard(item) | ||||
self._remove = _remove | ||||
# A list of keys to be removed | ||||
self._pending_removals = [] | ||||
self._iterating = set() | ||||
if data is not None: | ||||
self.update(data) | ||||
def _commit_removals(self): | ||||
l = self._pending_removals | ||||
discard = self.data.discard | ||||
while l: | ||||
discard(l.pop()) | ||||
def __iter__(self): | ||||
with _IterationGuard(self): | ||||
for itemref in self.data: | ||||
item = itemref() | ||||
if item is not None: | ||||
yield item | ||||
def __len__(self): | ||||
return len(self.data) - len(self._pending_removals) | ||||
def __contains__(self, item): | ||||
try: | ||||
wr = ref(item) | ||||
except TypeError: | ||||
return False | ||||
return wr in self.data | ||||
def __reduce__(self): | ||||
return (self.__class__, (list(self),), | ||||
getattr(self, '__dict__', None)) | ||||
def add(self, item): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
self.data.add(ref(item, self._remove)) | ||||
def clear(self): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
self.data.clear() | ||||
def copy(self): | ||||
return self.__class__(self) | ||||
def pop(self): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
while True: | ||||
try: | ||||
itemref = self.data.pop() | ||||
except KeyError: | ||||
raise KeyError('pop from empty WeakSet') | ||||
item = itemref() | ||||
if item is not None: | ||||
return item | ||||
def remove(self, item): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
self.data.remove(ref(item)) | ||||
def discard(self, item): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
self.data.discard(ref(item)) | ||||
def update(self, other): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
for element in other: | ||||
self.add(element) | ||||
def __ior__(self, other): | ||||
self.update(other) | ||||
return self | ||||
def difference(self, other): | ||||
newset = self.copy() | ||||
newset.difference_update(other) | ||||
return newset | ||||
__sub__ = difference | ||||
def difference_update(self, other): | ||||
self.__isub__(other) | ||||
def __isub__(self, other): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
if self is other: | ||||
self.data.clear() | ||||
else: | ||||
self.data.difference_update(ref(item) for item in other) | ||||
return self | ||||
def intersection(self, other): | ||||
return self.__class__(item for item in other if item in self) | ||||
__and__ = intersection | ||||
def intersection_update(self, other): | ||||
self.__iand__(other) | ||||
def __iand__(self, other): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
self.data.intersection_update(ref(item) for item in other) | ||||
return self | ||||
def issubset(self, other): | ||||
return self.data.issubset(ref(item) for item in other) | ||||
__le__ = issubset | ||||
def __lt__(self, other): | ||||
return self.data < set(ref(item) for item in other) | ||||
def issuperset(self, other): | ||||
return self.data.issuperset(ref(item) for item in other) | ||||
__ge__ = issuperset | ||||
def __gt__(self, other): | ||||
return self.data > set(ref(item) for item in other) | ||||
def __eq__(self, other): | ||||
if not isinstance(other, self.__class__): | ||||
return NotImplemented | ||||
return self.data == set(ref(item) for item in other) | ||||
def symmetric_difference(self, other): | ||||
newset = self.copy() | ||||
newset.symmetric_difference_update(other) | ||||
return newset | ||||
__xor__ = symmetric_difference | ||||
def symmetric_difference_update(self, other): | ||||
self.__ixor__(other) | ||||
def __ixor__(self, other): | ||||
if self._pending_removals: | ||||
self._commit_removals() | ||||
if self is other: | ||||
self.data.clear() | ||||
else: | ||||
self.data.symmetric_difference_update(ref(item, self._remove) for item in other) | ||||
return self | ||||
def union(self, other): | ||||
return self.__class__(e for s in (self, other) for e in s) | ||||
__or__ = union | ||||
def isdisjoint(self, other): | ||||
return len(self.intersection(other)) == 0 | ||||