Format: text/x-python
⬇ Download File (1.6 KB)
   1  from __future__ import annotations
   2  
   3  import collections.abc as c
   4  import inspect
   5  import typing as t
   6  from weakref import ref
   7  from weakref import WeakMethod
   8  
   9  T = t.TypeVar("T")
  10  
  11  
  12  class Symbol:
  13      """A constant symbol, nicer than ``object()``. Repeated calls return the
  14      same instance.
  15  
  16      >>> Symbol('foo') is Symbol('foo')
  17      True
  18      >>> Symbol('foo')
  19      foo
  20      """
  21  
  22      symbols: t.ClassVar[dict[str, Symbol]] = {}
  23  
  24      def __new__(cls, name: str) -> Symbol:
  25          if name in cls.symbols:
  26              return cls.symbols[name]
  27  
  28          obj = super().__new__(cls)
  29          cls.symbols[name] = obj
  30          return obj
  31  
  32      def __init__(self, name: str) -> None:
  33          self.name = name
  34  
  35      def __repr__(self) -> str:
  36          return self.name
  37  
  38      def __getnewargs__(self) -> tuple[t.Any, ...]:
  39          return (self.name,)
  40  
  41  
  42  def make_id(obj: object) -> c.Hashable:
  43      """Get a stable identifier for a receiver or sender, to be used as a dict
  44      key or in a set.
  45      """
  46      if inspect.ismethod(obj):
  47          # The id of a bound method is not stable, but the id of the unbound
  48          # function and instance are.
  49          return id(obj.__func__), id(obj.__self__)
  50  
  51      if isinstance(obj, (str, int)):
  52          # Instances with the same value always compare equal and have the same
  53          # hash, even if the id may change.
  54          return obj
  55  
  56      # Assume other types are not hashable but will always be the same instance.
  57      return id(obj)
  58  
  59  
  60  def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]:
  61      if inspect.ismethod(obj):
  62          return WeakMethod(obj, callback)  # type: ignore[arg-type, return-value]
  63  
  64      return ref(obj, callback)
  65