@@ -337,3 +337,108 @@ def update(self, dict=None, **kwargs):
337337 d [ref (key , self ._remove )] = value
338338 if len (kwargs ):
339339 self .update (kwargs )
340+
341+
342+ class WeakSet :
343+ def __init__ (self , data = None ):
344+ self .data = set ()
345+ def _remove (item , selfref = ref (self )):
346+ self = selfref ()
347+ if self is not None :
348+ self .data .discard (item )
349+ self ._remove = _remove
350+ if data is not None :
351+ self .update (data )
352+
353+ def __iter__ (self ):
354+ for itemref in self .data :
355+ item = itemref ()
356+ if item is not None :
357+ yield item
358+
359+ def __contains__ (self , item ):
360+ return ref (item ) in self .data
361+
362+ def __reduce__ (self ):
363+ return (self .__class__ , (list (self ),),
364+ getattr (self , '__dict__' , None ))
365+
366+ def add (self , item ):
367+ self .data .add (ref (item , self ._remove ))
368+
369+ def clear (self ):
370+ self .data .clear ()
371+
372+ def copy (self ):
373+ return self .__class__ (self )
374+
375+ def pop (self ):
376+ while True :
377+ itemref = self .data .pop ()
378+ item = itemref ()
379+ if item is not None :
380+ return item
381+
382+ def remove (self , item ):
383+ self .data .remove (ref (item ))
384+
385+ def discard (self , item ):
386+ self .data .discard (ref (item ))
387+
388+ def update (self , other ):
389+ if isinstance (other , self .__class__ ):
390+ self .data .update (other .data )
391+ else :
392+ for element in other :
393+ self .add (element )
394+ __ior__ = update
395+
396+ # Helper functions for simple delegating methods.
397+ def _apply (self , other , method ):
398+ if not isinstance (other , self .__class__ ):
399+ other = self .__class__ (other )
400+ newdata = method (other .data )
401+ newset = self .__class__ ()
402+ newset .data = newdata
403+ return newset
404+
405+ def _apply_mutate (self , other , method ):
406+ if not isinstance (other , self .__class__ ):
407+ other = self .__class__ (other )
408+ method (other )
409+
410+ def difference (self , other ):
411+ return self ._apply (other , self .data .difference )
412+ __sub__ = difference
413+
414+ def difference_update (self , other ):
415+ self ._apply_mutate (self , self .data .difference_update )
416+ __isub__ = difference_update
417+
418+ def intersection (self , other ):
419+ return self ._apply (other , self .data .intersection )
420+ __and__ = intersection
421+
422+ def intersection_update (self , other ):
423+ self ._apply_mutate (self , self .data .intersection_update )
424+ __iand__ = intersection_update
425+
426+ def issubset (self , other ):
427+ return self .data .issubset (ref (item ) for item in other )
428+ __lt__ = issubset
429+
430+ def issuperset (self , other ):
431+ return self .data .issuperset (ref (item ) for item in other )
432+ __gt__ = issuperset
433+
434+ def symmetric_difference (self , other ):
435+ return self ._apply (other , self .data .symmetric_difference )
436+ __xor__ = symmetric_difference
437+
438+ def symmetric_difference_update (self , other ):
439+ self ._apply_mutate (other , self .data .symmetric_difference_update )
440+ __ixor__ = symmetric_difference_update
441+
442+ def union (self , other ):
443+ self ._apply_mutate (other , self .data .union )
444+ __or__ = union
0 commit comments