]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/blinker/_utilities.py
1 from __future__
import annotations
7 from functools
import partial
8 from weakref
import ref
10 from blinker
._saferef
import BoundMethodWeakref
12 IdentityType
= t
.Union
[t
.Tuple
[int, int], str, int]
16 def __init__(self
, name
):
17 """Construct a new named symbol."""
18 self
.__name
__ = self
.name
= name
21 return symbol
, (self
.name
,)
27 _symbol
.__name
__ = "symbol"
33 >>> symbol('foo') is symbol('foo')
38 A slight refinement of the MAGICCOOKIE=object() pattern. The primary
39 advantage of symbol() is its repr(). They are also singletons.
41 Repeated calls of symbol('name') will all return the same instance.
45 symbols
= {} # type: ignore[var-annotated]
47 def __new__(cls
, name
):
49 return cls
.symbols
[name
]
51 return cls
.symbols
.setdefault(name
, _symbol(name
))
54 def hashable_identity(obj
: object) -> IdentityType
:
55 if hasattr(obj
, "__func__"):
56 return (id(obj
.__func
__), id(obj
.__self
__)) # type: ignore[attr-defined]
57 elif hasattr(obj
, "im_func"):
58 return (id(obj
.im_func
), id(obj
.im_self
)) # type: ignore[attr-defined]
59 elif isinstance(obj
, (int, str)):
65 WeakTypes
= (ref
, BoundMethodWeakref
)
68 class annotatable_weakref(ref
):
69 """A weakref.ref that supports custom instance attributes."""
71 receiver_id
: t
.Optional
[IdentityType
]
72 sender_id
: t
.Optional
[IdentityType
]
75 def reference( # type: ignore[no-untyped-def]
76 object, callback
=None, **annotations
77 ) -> annotatable_weakref
:
78 """Return an annotated weak ref."""
80 weak
= callable_reference(object, callback
)
82 weak
= annotatable_weakref(object, callback
)
83 for key
, value
in annotations
.items():
84 setattr(weak
, key
, value
)
85 return weak
# type: ignore[no-any-return]
88 def callable_reference(object, callback
=None):
89 """Return an annotated weak ref, supporting bound instance methods."""
90 if hasattr(object, "im_self") and object.im_self
is not None:
91 return BoundMethodWeakref(target
=object, on_delete
=callback
)
92 elif hasattr(object, "__self__") and object.__self
__ is not None:
93 return BoundMethodWeakref(target
=object, on_delete
=callback
)
94 return annotatable_weakref(object, callback
)
98 """A @property that is only evaluated once."""
100 def __init__(self
, deferred
):
101 self
._deferred
= deferred
102 self
.__doc
__ = deferred
.__doc
__
104 def __get__(self
, obj
, cls
):
107 value
= self
._deferred
(obj
)
108 setattr(obj
, self
._deferred
.__name
__, value
)
112 def is_coroutine_function(func
: t
.Any
) -> bool:
113 # Python < 3.8 does not correctly determine partially wrapped
114 # coroutine functions are coroutine functions, hence the need for
115 # this to exist. Code taken from CPython.
116 if sys
.version_info
>= (3, 8):
117 return asyncio
.iscoroutinefunction(func
)
119 # Note that there is something special about the AsyncMock
120 # such that it isn't determined as a coroutine function
121 # without an explicit check.
123 from unittest
.mock
import AsyncMock
# type: ignore[attr-defined]
125 if isinstance(func
, AsyncMock
):
128 # Not testing, no asynctest to import
131 while inspect
.ismethod(func
):
133 while isinstance(func
, partial
):
135 if not inspect
.isfunction(func
):
138 if func
.__code
__.co_flags
& inspect
.CO_COROUTINE
:
141 acic
= asyncio
.coroutines
._is
_coroutine
# type: ignore[attr-defined]
142 return getattr(func
, "_is_coroutine", None) is acic