Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/blinker/_utilities.py: 55%
55 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-22 06:29 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-22 06:29 +0000
1from __future__ import annotations
3import typing as t
4from weakref import ref
6from blinker._saferef import BoundMethodWeakref
8IdentityType = t.Union[t.Tuple[int, int], str, int]
11class _symbol:
12 def __init__(self, name):
13 """Construct a new named symbol."""
14 self.__name__ = self.name = name
16 def __reduce__(self):
17 return symbol, (self.name,)
19 def __repr__(self):
20 return self.name
23_symbol.__name__ = "symbol"
26class symbol:
27 """A constant symbol.
29 >>> symbol('foo') is symbol('foo')
30 True
31 >>> symbol('foo')
32 foo
34 A slight refinement of the MAGICCOOKIE=object() pattern. The primary
35 advantage of symbol() is its repr(). They are also singletons.
37 Repeated calls of symbol('name') will all return the same instance.
39 """
41 symbols = {} # type: ignore[var-annotated]
43 def __new__(cls, name):
44 try:
45 return cls.symbols[name]
46 except KeyError:
47 return cls.symbols.setdefault(name, _symbol(name))
50def hashable_identity(obj: object) -> IdentityType:
51 if hasattr(obj, "__func__"):
52 return (id(obj.__func__), id(obj.__self__)) # type: ignore[attr-defined]
53 elif hasattr(obj, "im_func"):
54 return (id(obj.im_func), id(obj.im_self)) # type: ignore[attr-defined]
55 elif isinstance(obj, (int, str)):
56 return obj
57 else:
58 return id(obj)
61WeakTypes = (ref, BoundMethodWeakref)
64class annotatable_weakref(ref):
65 """A weakref.ref that supports custom instance attributes."""
67 receiver_id: t.Optional[IdentityType]
68 sender_id: t.Optional[IdentityType]
71def reference( # type: ignore[no-untyped-def]
72 object, callback=None, **annotations
73) -> annotatable_weakref:
74 """Return an annotated weak ref."""
75 if callable(object):
76 weak = callable_reference(object, callback)
77 else:
78 weak = annotatable_weakref(object, callback)
79 for key, value in annotations.items():
80 setattr(weak, key, value)
81 return weak # type: ignore[no-any-return]
84def callable_reference(object, callback=None):
85 """Return an annotated weak ref, supporting bound instance methods."""
86 if hasattr(object, "im_self") and object.im_self is not None:
87 return BoundMethodWeakref(target=object, on_delete=callback)
88 elif hasattr(object, "__self__") and object.__self__ is not None:
89 return BoundMethodWeakref(target=object, on_delete=callback)
90 return annotatable_weakref(object, callback)
93class lazy_property:
94 """A @property that is only evaluated once."""
96 def __init__(self, deferred):
97 self._deferred = deferred
98 self.__doc__ = deferred.__doc__
100 def __get__(self, obj, cls):
101 if obj is None:
102 return self
103 value = self._deferred(obj)
104 setattr(obj, self._deferred.__name__, value)
105 return value