1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
import asyncio
import inspect
import sys
import typing as t
from functools import partial
from weakref import ref
from blinker._saferef import BoundMethodWeakref
IdentityType = t.Union[t.Tuple[int, int], str, int]
class _symbol:
def __init__(self, name):
"""Construct a new named symbol."""
self.__name__ = self.name = name
def __reduce__(self):
return symbol, (self.name,)
def __repr__(self):
return self.name
_symbol.__name__ = "symbol"
class symbol:
"""A constant symbol.
>>> symbol('foo') is symbol('foo')
True
>>> symbol('foo')
foo
A slight refinement of the MAGICCOOKIE=object() pattern. The primary
advantage of symbol() is its repr(). They are also singletons.
Repeated calls of symbol('name') will all return the same instance.
"""
symbols = {} # type: ignore
def __new__(cls, name):
try:
return cls.symbols[name]
except KeyError:
return cls.symbols.setdefault(name, _symbol(name))
def hashable_identity(obj: object) -> IdentityType:
if hasattr(obj, "__func__"):
return (id(obj.__func__), id(obj.__self__)) # type: ignore
elif hasattr(obj, "im_func"):
return (id(obj.im_func), id(obj.im_self)) # type: ignore
elif isinstance(obj, (int, str)):
return obj
else:
return id(obj)
WeakTypes = (ref, BoundMethodWeakref)
class annotatable_weakref(ref):
"""A weakref.ref that supports custom instance attributes."""
receiver_id: t.Optional[IdentityType]
sender_id: t.Optional[IdentityType]
def reference( # type: ignore
object, callback=None, **annotations
) -> annotatable_weakref:
"""Return an annotated weak ref."""
if callable(object):
weak = callable_reference(object, callback)
else:
weak = annotatable_weakref(object, callback)
for key, value in annotations.items():
setattr(weak, key, value)
return weak # type: ignore
def callable_reference(object, callback=None):
"""Return an annotated weak ref, supporting bound instance methods."""
if hasattr(object, "im_self") and object.im_self is not None:
return BoundMethodWeakref(target=object, on_delete=callback)
elif hasattr(object, "__self__") and object.__self__ is not None:
return BoundMethodWeakref(target=object, on_delete=callback)
return annotatable_weakref(object, callback)
class lazy_property:
"""A @property that is only evaluated once."""
def __init__(self, deferred):
self._deferred = deferred
self.__doc__ = deferred.__doc__
def __get__(self, obj, cls):
if obj is None:
return self
value = self._deferred(obj)
setattr(obj, self._deferred.__name__, value)
return value
def is_coroutine_function(func: t.Any) -> bool:
# Python < 3.8 does not correctly determine partially wrapped
# coroutine functions are coroutine functions, hence the need for
# this to exist. Code taken from CPython.
if sys.version_info >= (3, 8):
return asyncio.iscoroutinefunction(func)
else:
# Note that there is something special about the AsyncMock
# such that it isn't determined as a coroutine function
# without an explicit check.
try:
from unittest.mock import AsyncMock # type: ignore
if isinstance(func, AsyncMock):
return True
except ImportError:
# Not testing, no asynctest to import
pass
while inspect.ismethod(func):
func = func.__func__
while isinstance(func, partial):
func = func.func
if not inspect.isfunction(func):
return False
result = bool(func.__code__.co_flags & inspect.CO_COROUTINE)
return (
result
or getattr(func, "_is_coroutine", None) is asyncio.coroutines._is_coroutine # type: ignore # noqa: B950
)
|