codekingpro/portable-devtools
114k
1# Access WeakSet through the weakref module.2# This code is separated-out because it is needed3# by abc.py to load everything else at startup.4 5from _weakref import ref6from types import GenericAlias7 8__all__ = ['WeakSet']9 10 11class WeakSet:12 def __init__(self, data=None):13 self.data = set()14 15 def _remove(item, selfref=ref(self)):16 self = selfref()17 if self is not None:18 self.data.discard(item)19 20 self._remove = _remove21 if data is not None:22 self.update(data)23 24 def __iter__(self):25 for itemref in self.data.copy():26 item = itemref()27 if item is not None:28 # Caveat: the iterator will keep a strong reference to29 # `item` until it is resumed or closed.30 yield item31 32 def __len__(self):33 return len(self.data)34 35 def __contains__(self, item):36 try:37 wr = ref(item)38 except TypeError:39 return False40 return wr in self.data41 42 def __reduce__(self):43 return self.__class__, (list(self),), self.__getstate__()44 45 def add(self, item):46 self.data.add(ref(item, self._remove))47 48 def clear(self):49 self.data.clear()50 51 def copy(self):52 return self.__class__(self)53 54 def pop(self):55 while True:56 try:57 itemref = self.data.pop()58 except KeyError:59 raise KeyError('pop from empty WeakSet') from None60 item = itemref()61 if item is not None:62 return item63 64 def remove(self, item):65 self.data.remove(ref(item))66 67 def discard(self, item):68 self.data.discard(ref(item))69 70 def update(self, other):71 for element in other:72 self.add(element)73 74 def __ior__(self, other):75 self.update(other)76 return self77 78 def difference(self, other):79 newset = self.copy()80 newset.difference_update(other)81 return newset82 __sub__ = difference83 84 def difference_update(self, other):85 self.__isub__(other)86 def __isub__(self, other):87 if self is other:88 self.data.clear()89 else:90 self.data.difference_update(ref(item) for item in other)91 return self92 93 def intersection(self, other):94 return self.__class__(item for item in other if item in self)95 __and__ = intersection96 97 def intersection_update(self, other):98 self.__iand__(other)99 def __iand__(self, other):100 self.data.intersection_update(ref(item) for item in other)101 return self102 103 def issubset(self, other):104 return self.data.issubset(ref(item) for item in other)105 __le__ = issubset106 107 def __lt__(self, other):108 return self.data < set(map(ref, other))109 110 def issuperset(self, other):111 return self.data.issuperset(ref(item) for item in other)112 __ge__ = issuperset113 114 def __gt__(self, other):115 return self.data > set(map(ref, other))116 117 def __eq__(self, other):118 if not isinstance(other, self.__class__):119 return NotImplemented120 return self.data == set(map(ref, other))121 122 def symmetric_difference(self, other):123 newset = self.copy()124 newset.symmetric_difference_update(other)125 return newset126 __xor__ = symmetric_difference127 128 def symmetric_difference_update(self, other):129 self.__ixor__(other)130 def __ixor__(self, other):131 if self is other:132 self.data.clear()133 else:134 self.data.symmetric_difference_update(ref(item, self._remove) for item in other)135 return self136 137 def union(self, other):138 return self.__class__(e for s in (self, other) for e in s)139 __or__ = union140 141 def isdisjoint(self, other):142 return len(self.intersection(other)) == 0143 144 def __repr__(self):145 return repr(self.data)146 147 __class_getitem__ = classmethod(GenericAlias)148 