ez-a-sync 0.33.4__cp313-cp313-musllinux_1_2_i686.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- a_sync/ENVIRONMENT_VARIABLES.py +42 -0
- a_sync/__init__.pxd +2 -0
- a_sync/__init__.py +145 -0
- a_sync/_smart.c +22830 -0
- a_sync/_smart.cpython-313-i386-linux-musl.so +0 -0
- a_sync/_smart.pxd +2 -0
- a_sync/_smart.pyi +202 -0
- a_sync/_smart.pyx +674 -0
- a_sync/_typing.py +258 -0
- a_sync/a_sync/__init__.py +60 -0
- a_sync/a_sync/_descriptor.c +20537 -0
- a_sync/a_sync/_descriptor.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/_descriptor.pyi +33 -0
- a_sync/a_sync/_descriptor.pyx +422 -0
- a_sync/a_sync/_flags.c +6082 -0
- a_sync/a_sync/_flags.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/_flags.pxd +3 -0
- a_sync/a_sync/_flags.pyx +92 -0
- a_sync/a_sync/_helpers.c +14529 -0
- a_sync/a_sync/_helpers.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/_helpers.pxd +3 -0
- a_sync/a_sync/_helpers.pyi +10 -0
- a_sync/a_sync/_helpers.pyx +167 -0
- a_sync/a_sync/_kwargs.c +12202 -0
- a_sync/a_sync/_kwargs.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/_kwargs.pxd +2 -0
- a_sync/a_sync/_kwargs.pyx +64 -0
- a_sync/a_sync/_meta.py +210 -0
- a_sync/a_sync/abstract.c +12420 -0
- a_sync/a_sync/abstract.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/abstract.pyi +141 -0
- a_sync/a_sync/abstract.pyx +221 -0
- a_sync/a_sync/base.c +14940 -0
- a_sync/a_sync/base.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/base.pyi +60 -0
- a_sync/a_sync/base.pyx +271 -0
- a_sync/a_sync/config.py +168 -0
- a_sync/a_sync/decorator.py +651 -0
- a_sync/a_sync/flags.c +5272 -0
- a_sync/a_sync/flags.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/flags.pxd +72 -0
- a_sync/a_sync/flags.pyi +74 -0
- a_sync/a_sync/flags.pyx +72 -0
- a_sync/a_sync/function.c +37856 -0
- a_sync/a_sync/function.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/function.pxd +28 -0
- a_sync/a_sync/function.pyi +571 -0
- a_sync/a_sync/function.pyx +1381 -0
- a_sync/a_sync/method.c +29662 -0
- a_sync/a_sync/method.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/method.pxd +9 -0
- a_sync/a_sync/method.pyi +523 -0
- a_sync/a_sync/method.pyx +1023 -0
- a_sync/a_sync/modifiers/__init__.pxd +1 -0
- a_sync/a_sync/modifiers/__init__.py +101 -0
- a_sync/a_sync/modifiers/cache/__init__.py +160 -0
- a_sync/a_sync/modifiers/cache/memory.py +165 -0
- a_sync/a_sync/modifiers/limiter.py +132 -0
- a_sync/a_sync/modifiers/manager.c +16157 -0
- a_sync/a_sync/modifiers/manager.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/modifiers/manager.pxd +5 -0
- a_sync/a_sync/modifiers/manager.pyi +219 -0
- a_sync/a_sync/modifiers/manager.pyx +299 -0
- a_sync/a_sync/modifiers/semaphores.py +173 -0
- a_sync/a_sync/property.c +27268 -0
- a_sync/a_sync/property.cpython-313-i386-linux-musl.so +0 -0
- a_sync/a_sync/property.pyi +376 -0
- a_sync/a_sync/property.pyx +819 -0
- a_sync/a_sync/singleton.py +63 -0
- a_sync/aliases.py +3 -0
- a_sync/async_property/__init__.pxd +1 -0
- a_sync/async_property/__init__.py +1 -0
- a_sync/async_property/cached.c +20397 -0
- a_sync/async_property/cached.cpython-313-i386-linux-musl.so +0 -0
- a_sync/async_property/cached.pxd +10 -0
- a_sync/async_property/cached.pyi +45 -0
- a_sync/async_property/cached.pyx +178 -0
- a_sync/async_property/proxy.c +34662 -0
- a_sync/async_property/proxy.cpython-313-i386-linux-musl.so +0 -0
- a_sync/async_property/proxy.pxd +2 -0
- a_sync/async_property/proxy.pyi +124 -0
- a_sync/async_property/proxy.pyx +474 -0
- a_sync/asyncio/__init__.pxd +6 -0
- a_sync/asyncio/__init__.py +164 -0
- a_sync/asyncio/as_completed.c +18849 -0
- a_sync/asyncio/as_completed.cpython-313-i386-linux-musl.so +0 -0
- a_sync/asyncio/as_completed.pxd +8 -0
- a_sync/asyncio/as_completed.pyi +109 -0
- a_sync/asyncio/as_completed.pyx +269 -0
- a_sync/asyncio/create_task.c +15912 -0
- a_sync/asyncio/create_task.cpython-313-i386-linux-musl.so +0 -0
- a_sync/asyncio/create_task.pxd +2 -0
- a_sync/asyncio/create_task.pyi +51 -0
- a_sync/asyncio/create_task.pyx +271 -0
- a_sync/asyncio/gather.c +16687 -0
- a_sync/asyncio/gather.cpython-313-i386-linux-musl.so +0 -0
- a_sync/asyncio/gather.pyi +107 -0
- a_sync/asyncio/gather.pyx +218 -0
- a_sync/asyncio/igather.c +13080 -0
- a_sync/asyncio/igather.cpython-313-i386-linux-musl.so +0 -0
- a_sync/asyncio/igather.pxd +1 -0
- a_sync/asyncio/igather.pyi +8 -0
- a_sync/asyncio/igather.pyx +183 -0
- a_sync/asyncio/sleep.c +9601 -0
- a_sync/asyncio/sleep.cpython-313-i386-linux-musl.so +0 -0
- a_sync/asyncio/sleep.pyi +14 -0
- a_sync/asyncio/sleep.pyx +49 -0
- a_sync/debugging.c +15370 -0
- a_sync/debugging.cpython-313-i386-linux-musl.so +0 -0
- a_sync/debugging.pyi +76 -0
- a_sync/debugging.pyx +107 -0
- a_sync/exceptions.c +13320 -0
- a_sync/exceptions.cpython-313-i386-linux-musl.so +0 -0
- a_sync/exceptions.pyi +376 -0
- a_sync/exceptions.pyx +446 -0
- a_sync/executor.py +619 -0
- a_sync/functools.c +12746 -0
- a_sync/functools.cpython-313-i386-linux-musl.so +0 -0
- a_sync/functools.pxd +7 -0
- a_sync/functools.pyi +33 -0
- a_sync/functools.pyx +139 -0
- a_sync/future.py +1497 -0
- a_sync/iter.c +37279 -0
- a_sync/iter.cpython-313-i386-linux-musl.so +0 -0
- a_sync/iter.pxd +11 -0
- a_sync/iter.pyi +370 -0
- a_sync/iter.pyx +981 -0
- a_sync/primitives/__init__.pxd +1 -0
- a_sync/primitives/__init__.py +53 -0
- a_sync/primitives/_debug.c +15765 -0
- a_sync/primitives/_debug.cpython-313-i386-linux-musl.so +0 -0
- a_sync/primitives/_debug.pxd +12 -0
- a_sync/primitives/_debug.pyi +52 -0
- a_sync/primitives/_debug.pyx +223 -0
- a_sync/primitives/_loggable.c +11538 -0
- a_sync/primitives/_loggable.cpython-313-i386-linux-musl.so +0 -0
- a_sync/primitives/_loggable.pxd +4 -0
- a_sync/primitives/_loggable.pyi +66 -0
- a_sync/primitives/_loggable.pyx +102 -0
- a_sync/primitives/locks/__init__.pxd +8 -0
- a_sync/primitives/locks/__init__.py +17 -0
- a_sync/primitives/locks/counter.c +17938 -0
- a_sync/primitives/locks/counter.cpython-313-i386-linux-musl.so +0 -0
- a_sync/primitives/locks/counter.pxd +12 -0
- a_sync/primitives/locks/counter.pyi +151 -0
- a_sync/primitives/locks/counter.pyx +267 -0
- a_sync/primitives/locks/event.c +17072 -0
- a_sync/primitives/locks/event.cpython-313-i386-linux-musl.so +0 -0
- a_sync/primitives/locks/event.pxd +22 -0
- a_sync/primitives/locks/event.pyi +43 -0
- a_sync/primitives/locks/event.pyx +185 -0
- a_sync/primitives/locks/prio_semaphore.c +25635 -0
- a_sync/primitives/locks/prio_semaphore.cpython-313-i386-linux-musl.so +0 -0
- a_sync/primitives/locks/prio_semaphore.pxd +25 -0
- a_sync/primitives/locks/prio_semaphore.pyi +217 -0
- a_sync/primitives/locks/prio_semaphore.pyx +597 -0
- a_sync/primitives/locks/semaphore.c +26553 -0
- a_sync/primitives/locks/semaphore.cpython-313-i386-linux-musl.so +0 -0
- a_sync/primitives/locks/semaphore.pxd +21 -0
- a_sync/primitives/locks/semaphore.pyi +197 -0
- a_sync/primitives/locks/semaphore.pyx +454 -0
- a_sync/primitives/queue.py +1026 -0
- a_sync/py.typed +0 -0
- a_sync/sphinx/__init__.py +3 -0
- a_sync/sphinx/ext.py +289 -0
- a_sync/task.py +934 -0
- a_sync/utils/__init__.py +105 -0
- a_sync/utils/iterators.py +297 -0
- a_sync/utils/repr.c +15866 -0
- a_sync/utils/repr.cpython-313-i386-linux-musl.so +0 -0
- a_sync/utils/repr.pyi +2 -0
- a_sync/utils/repr.pyx +73 -0
- ez_a_sync-0.33.4.dist-info/METADATA +368 -0
- ez_a_sync-0.33.4.dist-info/RECORD +177 -0
- ez_a_sync-0.33.4.dist-info/WHEEL +5 -0
- ez_a_sync-0.33.4.dist-info/licenses/LICENSE.txt +17 -0
- ez_a_sync-0.33.4.dist-info/top_level.txt +1 -0
|
Binary file
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module extends :func:`asyncio.create_task` to support any :class:`Awaitable`,
|
|
3
|
+
manage task lifecycle, and enhance error handling.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from a_sync._typing import *
|
|
7
|
+
import asyncio
|
|
8
|
+
|
|
9
|
+
__all__ = ["create_task"]
|
|
10
|
+
|
|
11
|
+
def create_task(
|
|
12
|
+
coro: Awaitable[T],
|
|
13
|
+
*,
|
|
14
|
+
name: Optional[str] = None,
|
|
15
|
+
skip_gc_until_done: bool = False,
|
|
16
|
+
log_destroy_pending: bool = True
|
|
17
|
+
) -> asyncio.Task[T]:
|
|
18
|
+
"""
|
|
19
|
+
Extends :func:`asyncio.create_task` to support any :class:`Awaitable`, manage task lifecycle, and enhance error handling.
|
|
20
|
+
|
|
21
|
+
This function accepts any :class:`Awaitable`, ensuring broader compatibility. If the Awaitable is not a coroutine,
|
|
22
|
+
it is awaited directly using a private helper function `__await`, which can handle non-coroutine Awaitable objects.
|
|
23
|
+
|
|
24
|
+
Note:
|
|
25
|
+
The `__await` function is designed to handle non-coroutine Awaitables by awaiting them directly.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
coro: An :class:`Awaitable` object from which to create the task.
|
|
29
|
+
name: Optional name for the task, aiding in debugging.
|
|
30
|
+
skip_gc_until_done: If True, the task is kept alive until it completes, preventing garbage collection.
|
|
31
|
+
Exceptions are wrapped in :class:`PersistedTaskException` for special handling within the
|
|
32
|
+
`__persisted_task_exc_wrap` function.
|
|
33
|
+
log_destroy_pending: If False, asyncio\'s default error log when a pending task is destroyed is suppressed.
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
Create a simple task with a coroutine:
|
|
37
|
+
|
|
38
|
+
>>> async def my_coroutine():
|
|
39
|
+
... return "Hello, World!"
|
|
40
|
+
>>> task = create_task(my_coroutine())
|
|
41
|
+
|
|
42
|
+
Create a task with a non-coroutine Awaitable:
|
|
43
|
+
|
|
44
|
+
>>> from concurrent.futures import Future
|
|
45
|
+
>>> future = Future()
|
|
46
|
+
>>> task = create_task(future)
|
|
47
|
+
|
|
48
|
+
See Also:
|
|
49
|
+
- :func:`asyncio.create_task`
|
|
50
|
+
- :class:`asyncio.Task`
|
|
51
|
+
"""
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module extends :func:`asyncio.create_task` to support any :class:`Awaitable`,
|
|
3
|
+
manage task lifecycle, and enhance error handling.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import asyncio
|
|
7
|
+
import asyncio.tasks as aiotasks
|
|
8
|
+
import logging
|
|
9
|
+
import typing
|
|
10
|
+
|
|
11
|
+
from cpython.unicode cimport PyUnicode_CompareWithASCIIString
|
|
12
|
+
from cpython.version cimport PY_VERSION_HEX
|
|
13
|
+
|
|
14
|
+
from a_sync import _smart, exceptions
|
|
15
|
+
from a_sync._typing import T
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# cdef asyncio
|
|
19
|
+
cdef object get_running_loop = asyncio.get_running_loop
|
|
20
|
+
cdef object iscoroutine = asyncio.iscoroutine
|
|
21
|
+
cdef object Future = asyncio.Future
|
|
22
|
+
cdef object CancelledError = asyncio.CancelledError
|
|
23
|
+
cdef object InvalidStateError = asyncio.InvalidStateError
|
|
24
|
+
cdef object Task = asyncio.Task
|
|
25
|
+
cdef object _GatheringFuture = aiotasks._GatheringFuture
|
|
26
|
+
del asyncio, aiotasks
|
|
27
|
+
|
|
28
|
+
# cdef logging
|
|
29
|
+
cdef public object logger = logging.getLogger(__name__)
|
|
30
|
+
del logging
|
|
31
|
+
|
|
32
|
+
# cdef typing
|
|
33
|
+
cdef object Awaitable = typing.Awaitable
|
|
34
|
+
cdef object Optional = typing.Optional
|
|
35
|
+
cdef object Tuple = typing.Tuple
|
|
36
|
+
cdef object Set = typing.Set
|
|
37
|
+
del typing
|
|
38
|
+
|
|
39
|
+
# cdef _smart
|
|
40
|
+
cdef object SmartTask = _smart.SmartTask
|
|
41
|
+
cdef object smart_task_factory = _smart.smart_task_factory
|
|
42
|
+
del _smart
|
|
43
|
+
|
|
44
|
+
# cdef exceptions
|
|
45
|
+
cdef object PersistedTaskException = exceptions.PersistedTaskException
|
|
46
|
+
del exceptions
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def create_task(
|
|
50
|
+
coro: Awaitable[T],
|
|
51
|
+
*,
|
|
52
|
+
name: str = "",
|
|
53
|
+
skip_gc_until_done: bint = False,
|
|
54
|
+
log_destroy_pending: bint = True,
|
|
55
|
+
) -> "Task[T]":
|
|
56
|
+
"""
|
|
57
|
+
Extends :func:`asyncio.create_task` to support any :class:`Awaitable`, manage task lifecycle, and enhance error handling.
|
|
58
|
+
|
|
59
|
+
This function accepts any :class:`Awaitable`, ensuring broader compatibility. If the Awaitable is not a coroutine,
|
|
60
|
+
it is awaited directly using a private helper function `__await`, which can handle non-coroutine Awaitable objects.
|
|
61
|
+
|
|
62
|
+
Note:
|
|
63
|
+
The `__await` function is designed to handle non-coroutine Awaitables by awaiting them directly.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
coro: An :class:`Awaitable` object from which to create the task.
|
|
67
|
+
name: Optional name for the task, aiding in debugging.
|
|
68
|
+
skip_gc_until_done: If True, the task is kept alive until it completes, preventing garbage collection.
|
|
69
|
+
Exceptions are wrapped in :class:`PersistedTaskException` for special handling within the
|
|
70
|
+
`__persisted_task_exc_wrap` function.
|
|
71
|
+
log_destroy_pending: If False, asyncio's default error log when a pending task is destroyed is suppressed.
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
Create a simple task with a coroutine:
|
|
75
|
+
|
|
76
|
+
>>> async def my_coroutine():
|
|
77
|
+
... return "Hello, World!"
|
|
78
|
+
>>> task = create_task(my_coroutine())
|
|
79
|
+
|
|
80
|
+
Create a task with a non-coroutine Awaitable:
|
|
81
|
+
|
|
82
|
+
>>> from concurrent.futures import Future
|
|
83
|
+
>>> future = Future()
|
|
84
|
+
>>> task = create_task(future)
|
|
85
|
+
|
|
86
|
+
See Also:
|
|
87
|
+
- :func:`asyncio.create_task`
|
|
88
|
+
- :class:`Task`
|
|
89
|
+
"""
|
|
90
|
+
return ccreate_task(coro, name, skip_gc_until_done, log_destroy_pending)
|
|
91
|
+
|
|
92
|
+
cdef object ccreate_task_simple(object coro):
|
|
93
|
+
return ccreate_task(coro, "", False, True)
|
|
94
|
+
|
|
95
|
+
cdef object ccreate_task(object coro, str name, bint skip_gc_until_done, bint log_destroy_pending):
|
|
96
|
+
cdef object loop = get_running_loop()
|
|
97
|
+
cdef object task_factory = loop._task_factory
|
|
98
|
+
cdef object task, persisted
|
|
99
|
+
|
|
100
|
+
if not iscoroutine(coro):
|
|
101
|
+
coro = __await(coro)
|
|
102
|
+
|
|
103
|
+
if task_factory is None:
|
|
104
|
+
task = Task(coro, loop=loop, name=name)
|
|
105
|
+
if task._source_traceback:
|
|
106
|
+
del task._source_traceback[-1]
|
|
107
|
+
elif task_factory is smart_task_factory:
|
|
108
|
+
task = SmartTask(coro, loop=loop, name=name)
|
|
109
|
+
if task._source_traceback:
|
|
110
|
+
del task._source_traceback[-1]
|
|
111
|
+
else:
|
|
112
|
+
task = task_factory(loop, coro)
|
|
113
|
+
if name:
|
|
114
|
+
__set_task_name(task, name)
|
|
115
|
+
|
|
116
|
+
if skip_gc_until_done:
|
|
117
|
+
persisted = __persisted_task_exc_wrap(task)
|
|
118
|
+
|
|
119
|
+
if task_factory is None:
|
|
120
|
+
persisted = Task(persisted, loop=loop, name=name)
|
|
121
|
+
if persisted._source_traceback:
|
|
122
|
+
del persisted._source_traceback[-1]
|
|
123
|
+
elif task_factory is smart_task_factory:
|
|
124
|
+
persisted = SmartTask(persisted, loop=loop, name=name)
|
|
125
|
+
if persisted._source_traceback:
|
|
126
|
+
del persisted._source_traceback[-1]
|
|
127
|
+
else:
|
|
128
|
+
persisted = task_factory(loop, persisted)
|
|
129
|
+
if name:
|
|
130
|
+
__set_task_name(persisted, name)
|
|
131
|
+
|
|
132
|
+
persisted.add_done_callback(_persisted_task_callback)
|
|
133
|
+
_persisted_tasks.add(persisted)
|
|
134
|
+
|
|
135
|
+
if log_destroy_pending is False:
|
|
136
|
+
task._log_destroy_pending = False
|
|
137
|
+
|
|
138
|
+
if _exceptions:
|
|
139
|
+
for task, exc in _exceptions:
|
|
140
|
+
__log_exception(exc)
|
|
141
|
+
raise exc.with_traceback(exc.__traceback__)
|
|
142
|
+
|
|
143
|
+
return task
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
cdef inline void __set_task_name(object task, str name):
|
|
147
|
+
if set_name := getattr(task, "set_name", None):
|
|
148
|
+
set_name(name)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _persisted_task_callback(task: Task[Any]) -> None:
|
|
152
|
+
"""Remove completed tasks from the set of persisted tasks.
|
|
153
|
+
|
|
154
|
+
This callback function checks each persisted task as it completes. If a task has a :class:`PersistedTaskException`,
|
|
155
|
+
it logs the exception before discarding the task. If it has any other type of Exception, it adds it to `_exceptions`
|
|
156
|
+
to be raised later.
|
|
157
|
+
|
|
158
|
+
See Also:
|
|
159
|
+
- :class:`PersistedTaskException`
|
|
160
|
+
"""
|
|
161
|
+
cdef dict context
|
|
162
|
+
if task.cancelled():
|
|
163
|
+
pass
|
|
164
|
+
elif exc := task.exception():
|
|
165
|
+
if isinstance(exc, PersistedTaskException):
|
|
166
|
+
# we have to manually log the traceback that asyncio would usually log
|
|
167
|
+
# since we already got the exception from the task and the usual handler will now not run
|
|
168
|
+
context = {
|
|
169
|
+
"message": f"{task.__class__.__name__} exception was never retrieved",
|
|
170
|
+
"exception": exc,
|
|
171
|
+
"future": task,
|
|
172
|
+
}
|
|
173
|
+
if task._source_traceback:
|
|
174
|
+
context["source_traceback"] = task._source_traceback
|
|
175
|
+
task._loop.call_exception_handler(context)
|
|
176
|
+
else:
|
|
177
|
+
# force exceptions related to this lib to bubble up
|
|
178
|
+
_exceptions.add((task, exc))
|
|
179
|
+
_persisted_tasks.discard(task)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
cdef public set[object] _persisted_tasks = set()
|
|
183
|
+
cdef public set[tuple[object, object]] _exceptions = set()
|
|
184
|
+
|
|
185
|
+
cdef object __await
|
|
186
|
+
|
|
187
|
+
async def __await(awaitable: Awaitable[T]) -> T:
|
|
188
|
+
"""Wait for the completion of a non-coroutine Awaitable.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
awaitable: The :class:`Awaitable` object to wait for.
|
|
192
|
+
|
|
193
|
+
Raises:
|
|
194
|
+
RuntimeError: If a RuntimeError occurs during the await, it is raised with additional context.
|
|
195
|
+
|
|
196
|
+
Examples:
|
|
197
|
+
Await a simple coroutine:
|
|
198
|
+
|
|
199
|
+
>>> async def my_coroutine():
|
|
200
|
+
... return "Hello, World!"
|
|
201
|
+
>>> result = await __await(my_coroutine())
|
|
202
|
+
|
|
203
|
+
See Also:
|
|
204
|
+
- :class:`Awaitable`
|
|
205
|
+
"""
|
|
206
|
+
try:
|
|
207
|
+
return await awaitable
|
|
208
|
+
except RuntimeError as e:
|
|
209
|
+
args = [e, awaitable]
|
|
210
|
+
if isinstance(awaitable, _GatheringFuture):
|
|
211
|
+
args.append(awaitable._children)
|
|
212
|
+
raise RuntimeError(*args) from None
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
cdef object __log_exception = logger.exception
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
cdef object _get_exception(fut: Future):
|
|
219
|
+
"""Return the exception that was set on this future.
|
|
220
|
+
|
|
221
|
+
The exception (or None if no exception was set) is returned only if
|
|
222
|
+
the future is done. If the future has been cancelled, raises
|
|
223
|
+
CancelledError. If the future isn't done yet, raises
|
|
224
|
+
InvalidStateError.
|
|
225
|
+
"""
|
|
226
|
+
cdef str state = fut._state
|
|
227
|
+
if PyUnicode_CompareWithASCIIString(state, b"FINISHED") == 0:
|
|
228
|
+
fut._Future__log_traceback = False
|
|
229
|
+
return fut._exception
|
|
230
|
+
if PyUnicode_CompareWithASCIIString(state, b"CANCELLED") == 0:
|
|
231
|
+
raise (
|
|
232
|
+
CancelledError()
|
|
233
|
+
if PY_VERSION_HEX < 0x03090000 # Python 3.9
|
|
234
|
+
else fut._make_cancelled_error()
|
|
235
|
+
)
|
|
236
|
+
raise InvalidStateError('Exception is not set.')
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
cdef inline bint _exc_exists(tup: Tuple[Future, Optional[Exception]]):
|
|
240
|
+
return tup[1] is not None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
cdef object __persisted_task_exc_wrap
|
|
244
|
+
|
|
245
|
+
async def __persisted_task_exc_wrap(task: "Task[T]") -> T:
|
|
246
|
+
"""
|
|
247
|
+
Wrap a task to handle its exception in a specialized manner.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
task: The :class:`Task` to wrap.
|
|
251
|
+
|
|
252
|
+
Raises:
|
|
253
|
+
PersistedTaskException: Wraps any exception raised by the task for special handling.
|
|
254
|
+
|
|
255
|
+
See Also:
|
|
256
|
+
- :class:`PersistedTaskException`
|
|
257
|
+
"""
|
|
258
|
+
try:
|
|
259
|
+
return await task
|
|
260
|
+
except Exception as e:
|
|
261
|
+
raise PersistedTaskException(e, task) from e
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
__all__ = ["create_task"]
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
# For testing purposes only
|
|
268
|
+
|
|
269
|
+
def _get_persisted_tasks() -> Set[Task]:
|
|
270
|
+
# we can't import this directly to the .py test file
|
|
271
|
+
return _persisted_tasks
|