text: # 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(object):
      # 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(object):
      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))
  
      __hash__ = 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 __ne__(self, other):
          opposite = self.__eq__(other)
          if opposite is NotImplemented:
              return NotImplemented
          return not opposite
  
      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
  