diff --git a/Lib/_weakrefset.py b/Lib/_weakrefset.py new file mode 100644 index 00000000000..e56ac048dd5 --- /dev/null +++ b/Lib/_weakrefset.py @@ -0,0 +1,111 @@ +# 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 WeakSet: + def __init__(self, data=None): + self.data = set() + def _remove(item, selfref=ref(self)): + self = selfref() + if self is not None: + self.data.discard(item) + self._remove = _remove + if data is not None: + self.update(data) + + def __iter__(self): + for itemref in self.data: + item = itemref() + if item is not None: + yield item + + def __contains__(self, item): + return ref(item) in self.data + + def __reduce__(self): + return (self.__class__, (list(self),), + getattr(self, '__dict__', None)) + + def add(self, item): + self.data.add(ref(item, self._remove)) + + def clear(self): + self.data.clear() + + def copy(self): + return self.__class__(self) + + def pop(self): + while True: + itemref = self.data.pop() + item = itemref() + if item is not None: + return item + + def remove(self, item): + self.data.remove(ref(item)) + + def discard(self, item): + self.data.discard(ref(item)) + + def update(self, other): + if isinstance(other, self.__class__): + self.data.update(other.data) + else: + for element in other: + self.add(element) + __ior__ = update + + # Helper functions for simple delegating methods. + def _apply(self, other, method): + if not isinstance(other, self.__class__): + other = self.__class__(other) + newdata = method(other.data) + newset = self.__class__() + newset.data = newdata + return newset + + def _apply_mutate(self, other, method): + if not isinstance(other, self.__class__): + other = self.__class__(other) + method(other) + + def difference(self, other): + return self._apply(other, self.data.difference) + __sub__ = difference + + def difference_update(self, other): + self._apply_mutate(self, self.data.difference_update) + __isub__ = difference_update + + def intersection(self, other): + return self._apply(other, self.data.intersection) + __and__ = intersection + + def intersection_update(self, other): + self._apply_mutate(self, self.data.intersection_update) + __iand__ = intersection_update + + def issubset(self, other): + return self.data.issubset(ref(item) for item in other) + __lt__ = issubset + + def issuperset(self, other): + return self.data.issuperset(ref(item) for item in other) + __gt__ = issuperset + + def symmetric_difference(self, other): + return self._apply(other, self.data.symmetric_difference) + __xor__ = symmetric_difference + + def symmetric_difference_update(self, other): + self._apply_mutate(other, self.data.symmetric_difference_update) + __ixor__ = symmetric_difference_update + + def union(self, other): + self._apply_mutate(other, self.data.union) + __or__ = union diff --git a/Lib/abc.py b/Lib/abc.py index 875115361d8..8fb61c603c0 100644 --- a/Lib/abc.py +++ b/Lib/abc.py @@ -3,7 +3,7 @@ """Abstract Base Classes (ABCs) according to PEP 3119.""" -from weakref import WeakSet +from _weakrefset import WeakSet def abstractmethod(funcobj): """A decorator indicating abstract methods. diff --git a/Lib/weakref.py b/Lib/weakref.py index c54a0729d49..a9c05d82d94 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -20,12 +20,14 @@ from _weakref import ( ProxyType, ReferenceType) +from _weakrefset import WeakSet ProxyTypes = (ProxyType, CallableProxyType) __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", "WeakKeyDictionary", "ReferenceType", "ProxyType", - "CallableProxyType", "ProxyTypes", "WeakValueDictionary"] + "CallableProxyType", "ProxyTypes", "WeakValueDictionary", + "WeakSet"] class WeakValueDictionary(UserDict.UserDict): @@ -337,108 +339,3 @@ class WeakKeyDictionary(UserDict.UserDict): d[ref(key, self._remove)] = value if len(kwargs): self.update(kwargs) - - -class WeakSet: - def __init__(self, data=None): - self.data = set() - def _remove(item, selfref=ref(self)): - self = selfref() - if self is not None: - self.data.discard(item) - self._remove = _remove - if data is not None: - self.update(data) - - def __iter__(self): - for itemref in self.data: - item = itemref() - if item is not None: - yield item - - def __contains__(self, item): - return ref(item) in self.data - - def __reduce__(self): - return (self.__class__, (list(self),), - getattr(self, '__dict__', None)) - - def add(self, item): - self.data.add(ref(item, self._remove)) - - def clear(self): - self.data.clear() - - def copy(self): - return self.__class__(self) - - def pop(self): - while True: - itemref = self.data.pop() - item = itemref() - if item is not None: - return item - - def remove(self, item): - self.data.remove(ref(item)) - - def discard(self, item): - self.data.discard(ref(item)) - - def update(self, other): - if isinstance(other, self.__class__): - self.data.update(other.data) - else: - for element in other: - self.add(element) - __ior__ = update - - # Helper functions for simple delegating methods. - def _apply(self, other, method): - if not isinstance(other, self.__class__): - other = self.__class__(other) - newdata = method(other.data) - newset = self.__class__() - newset.data = newdata - return newset - - def _apply_mutate(self, other, method): - if not isinstance(other, self.__class__): - other = self.__class__(other) - method(other) - - def difference(self, other): - return self._apply(other, self.data.difference) - __sub__ = difference - - def difference_update(self, other): - self._apply_mutate(self, self.data.difference_update) - __isub__ = difference_update - - def intersection(self, other): - return self._apply(other, self.data.intersection) - __and__ = intersection - - def intersection_update(self, other): - self._apply_mutate(self, self.data.intersection_update) - __iand__ = intersection_update - - def issubset(self, other): - return self.data.issubset(ref(item) for item in other) - __lt__ = issubset - - def issuperset(self, other): - return self.data.issuperset(ref(item) for item in other) - __gt__ = issuperset - - def symmetric_difference(self, other): - return self._apply(other, self.data.symmetric_difference) - __xor__ = symmetric_difference - - def symmetric_difference_update(self, other): - self._apply_mutate(other, self.data.symmetric_difference_update) - __ixor__ = symmetric_difference_update - - def union(self, other): - self._apply_mutate(other, self.data.union) - __or__ = union