Index: Lib/weakref.py =================================================================== --- Lib/weakref.py (revision 57721) +++ Lib/weakref.py (working copy) @@ -337,3 +337,101 @@ 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, other): + 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)) + + # Helper functions for delegating methods. + def _apply(self, other, method): + if not isinstance(other, __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, __class__): + other = self.__class__(other) + method(other.data) + + def update(self, other): + self._apply_mutate(other, self.data.update) + __ior__ = update + + 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) + + def issuperset(self, other): + return self.data.issuperset(ref(item) for item in other) + + 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 Index: Lib/abc.py =================================================================== --- Lib/abc.py (revision 57721) +++ Lib/abc.py (working copy) @@ -3,6 +3,7 @@ """Abstract Base Classes (ABCs) according to PEP 3119.""" +from weakref import WeakSet def abstractmethod(funcobj): """A decorator indicating abstract methods. @@ -132,9 +133,9 @@ abstracts.add(name) cls.__abstractmethods__ = abstracts # Set up inheritance registry - cls._abc_registry = set() - cls._abc_cache = set() - cls._abc_negative_cache = set() + cls._abc_registry = WeakSet() + cls._abc_cache = WeakSet() + cls._abc_negative_cache = WeakSet() cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter return cls @@ -174,7 +175,7 @@ # Check negative cache; may have to invalidate if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: # Invalidate the negative cache - cls._abc_negative_cache = set() + cls._abc_negative_cache = WeakSet() cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter elif subclass in cls._abc_negative_cache: return False Index: Modules/Setup.dist =================================================================== --- Modules/Setup.dist (revision 57721) +++ Modules/Setup.dist (working copy) @@ -116,6 +116,7 @@ _sre _sre.c # Fredrik Lundh's new regular expressions _codecs _codecsmodule.c # access to the builtin codecs and codec registry _fileio _fileio.c # Standard I/O baseline +_weakref _weakref.c # weak references # The zipimport module is always imported at startup. Having it as a # builtin module avoids some bootstrapping problems and reduces overhead.