ez-a-sync 0.22.14__py3-none-any.whl → 0.22.16__py3-none-any.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.
Potentially problematic release.
This version of ez-a-sync might be problematic. Click here for more details.
- a_sync/ENVIRONMENT_VARIABLES.py +37 -5
- a_sync/__init__.py +53 -12
- a_sync/_smart.py +231 -28
- a_sync/_typing.py +112 -15
- a_sync/a_sync/__init__.py +35 -10
- a_sync/a_sync/_descriptor.py +248 -38
- a_sync/a_sync/_flags.py +78 -9
- a_sync/a_sync/_helpers.py +46 -13
- a_sync/a_sync/_kwargs.py +33 -8
- a_sync/a_sync/_meta.py +149 -28
- a_sync/a_sync/abstract.py +150 -28
- a_sync/a_sync/base.py +34 -16
- a_sync/a_sync/config.py +85 -14
- a_sync/a_sync/decorator.py +441 -139
- a_sync/a_sync/function.py +709 -147
- a_sync/a_sync/method.py +437 -110
- a_sync/a_sync/modifiers/__init__.py +85 -5
- a_sync/a_sync/modifiers/cache/__init__.py +116 -17
- a_sync/a_sync/modifiers/cache/memory.py +130 -20
- a_sync/a_sync/modifiers/limiter.py +101 -22
- a_sync/a_sync/modifiers/manager.py +142 -16
- a_sync/a_sync/modifiers/semaphores.py +121 -15
- a_sync/a_sync/property.py +383 -82
- a_sync/a_sync/singleton.py +44 -19
- a_sync/aliases.py +0 -1
- a_sync/asyncio/__init__.py +140 -1
- a_sync/asyncio/as_completed.py +213 -79
- a_sync/asyncio/create_task.py +70 -20
- a_sync/asyncio/gather.py +125 -58
- a_sync/asyncio/utils.py +3 -3
- a_sync/exceptions.py +248 -26
- a_sync/executor.py +164 -69
- a_sync/future.py +1227 -168
- a_sync/iter.py +173 -56
- a_sync/primitives/__init__.py +14 -2
- a_sync/primitives/_debug.py +72 -18
- a_sync/primitives/_loggable.py +41 -10
- a_sync/primitives/locks/__init__.py +5 -2
- a_sync/primitives/locks/counter.py +107 -38
- a_sync/primitives/locks/event.py +21 -7
- a_sync/primitives/locks/prio_semaphore.py +262 -63
- a_sync/primitives/locks/semaphore.py +138 -89
- a_sync/primitives/queue.py +601 -60
- a_sync/sphinx/__init__.py +0 -1
- a_sync/sphinx/ext.py +160 -50
- a_sync/task.py +313 -112
- a_sync/utils/__init__.py +12 -6
- a_sync/utils/iterators.py +170 -50
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/METADATA +1 -1
- ez_a_sync-0.22.16.dist-info/RECORD +74 -0
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/WHEEL +1 -1
- tests/conftest.py +1 -2
- tests/executor.py +250 -9
- tests/fixtures.py +61 -32
- tests/test_abstract.py +22 -4
- tests/test_as_completed.py +54 -21
- tests/test_base.py +264 -19
- tests/test_cache.py +31 -15
- tests/test_decorator.py +54 -28
- tests/test_executor.py +31 -13
- tests/test_future.py +45 -8
- tests/test_gather.py +8 -2
- tests/test_helpers.py +2 -0
- tests/test_iter.py +55 -13
- tests/test_limiter.py +5 -3
- tests/test_meta.py +23 -9
- tests/test_modified.py +4 -1
- tests/test_semaphore.py +15 -8
- tests/test_singleton.py +28 -11
- tests/test_task.py +162 -36
- ez_a_sync-0.22.14.dist-info/RECORD +0 -74
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/LICENSE.txt +0 -0
- {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/top_level.txt +0 -0
a_sync/a_sync/decorator.py
CHANGED
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
# mypy: disable-error-code=misc
|
|
3
3
|
from a_sync._typing import *
|
|
4
4
|
from a_sync.a_sync import _flags, config
|
|
5
|
-
from a_sync.a_sync.function import (
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
from a_sync.a_sync.function import (
|
|
6
|
+
ASyncDecorator,
|
|
7
|
+
ASyncFunction,
|
|
8
|
+
ASyncDecoratorAsyncDefault,
|
|
9
|
+
ASyncDecoratorSyncDefault,
|
|
10
|
+
ASyncFunctionAsyncDefault,
|
|
11
|
+
ASyncFunctionSyncDefault,
|
|
12
|
+
)
|
|
8
13
|
|
|
9
14
|
########################
|
|
10
15
|
# The a_sync decorator #
|
|
@@ -18,129 +23,426 @@ from a_sync.a_sync.function import (ASyncDecorator, ASyncFunction, ASyncDecorato
|
|
|
18
23
|
# async def some_fn():
|
|
19
24
|
# pass
|
|
20
25
|
|
|
26
|
+
|
|
21
27
|
@overload
|
|
22
28
|
def a_sync(
|
|
23
29
|
default: Literal["async"],
|
|
24
30
|
**modifiers: Unpack[ModifierKwargs],
|
|
25
|
-
) -> ASyncDecoratorAsyncDefault
|
|
31
|
+
) -> ASyncDecoratorAsyncDefault:
|
|
32
|
+
"""
|
|
33
|
+
Creates an asynchronous default decorator.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
default: Specifies the default execution mode as 'async'.
|
|
37
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
Basic usage with an asynchronous default:
|
|
41
|
+
|
|
42
|
+
>>> @a_sync(default='async')
|
|
43
|
+
... async def my_function():
|
|
44
|
+
... return True
|
|
45
|
+
>>> await my_function()
|
|
46
|
+
True
|
|
47
|
+
>>> my_function(sync=True)
|
|
48
|
+
True
|
|
49
|
+
|
|
50
|
+
See Also:
|
|
51
|
+
:class:`ASyncDecoratorAsyncDefault`
|
|
52
|
+
"""
|
|
53
|
+
|
|
26
54
|
|
|
27
55
|
@overload
|
|
28
56
|
def a_sync(
|
|
29
57
|
default: Literal["sync"],
|
|
30
58
|
**modifiers: Unpack[ModifierKwargs],
|
|
31
|
-
) -> ASyncDecoratorSyncDefault
|
|
59
|
+
) -> ASyncDecoratorSyncDefault:
|
|
60
|
+
"""
|
|
61
|
+
Creates a synchronous default decorator.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
default: Specifies the default execution mode as 'sync'.
|
|
65
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
66
|
+
|
|
67
|
+
Examples:
|
|
68
|
+
Basic usage with a synchronous default:
|
|
69
|
+
|
|
70
|
+
>>> @a_sync(default='sync')
|
|
71
|
+
... def my_function():
|
|
72
|
+
... return True
|
|
73
|
+
>>> my_function()
|
|
74
|
+
True
|
|
75
|
+
>>> await my_function(sync=False)
|
|
76
|
+
True
|
|
77
|
+
|
|
78
|
+
See Also:
|
|
79
|
+
:class:`ASyncDecoratorSyncDefault`
|
|
80
|
+
"""
|
|
81
|
+
|
|
32
82
|
|
|
33
83
|
@overload
|
|
34
84
|
def a_sync(
|
|
35
85
|
**modifiers: Unpack[ModifierKwargs],
|
|
36
|
-
) -> ASyncDecorator
|
|
86
|
+
) -> ASyncDecorator:
|
|
87
|
+
"""
|
|
88
|
+
Creates a decorator with no default execution mode specified.
|
|
37
89
|
|
|
38
|
-
|
|
39
|
-
|
|
90
|
+
Args:
|
|
91
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
Usage without specifying a default mode:
|
|
95
|
+
|
|
96
|
+
>>> @a_sync
|
|
97
|
+
... async def my_function():
|
|
98
|
+
... return True
|
|
99
|
+
>>> await my_function()
|
|
100
|
+
True
|
|
101
|
+
>>> my_function(sync=True)
|
|
102
|
+
True
|
|
103
|
+
|
|
104
|
+
See Also:
|
|
105
|
+
:class:`ASyncDecorator`
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@overload # async def, None default
|
|
110
|
+
def a_sync(
|
|
40
111
|
coro_fn: CoroFn[P, T],
|
|
41
112
|
default: Literal[None] = None,
|
|
42
113
|
**modifiers: Unpack[ModifierKwargs],
|
|
43
|
-
) -> ASyncFunctionAsyncDefault[P, T]
|
|
114
|
+
) -> ASyncFunctionAsyncDefault[P, T]:
|
|
115
|
+
"""
|
|
116
|
+
Decorates an asynchronous function with no default execution mode specified.
|
|
44
117
|
|
|
45
|
-
|
|
46
|
-
|
|
118
|
+
Args:
|
|
119
|
+
coro_fn: The coroutine function to be decorated.
|
|
120
|
+
default: Specifies no default execution mode.
|
|
121
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
122
|
+
|
|
123
|
+
Examples:
|
|
124
|
+
Decorating an asynchronous function without a default mode:
|
|
125
|
+
|
|
126
|
+
>>> async def my_function():
|
|
127
|
+
... return True
|
|
128
|
+
>>> decorated_function = a_sync(my_function)
|
|
129
|
+
>>> await decorated_function()
|
|
130
|
+
True
|
|
131
|
+
>>> decorated_function(sync=True)
|
|
132
|
+
True
|
|
133
|
+
|
|
134
|
+
See Also:
|
|
135
|
+
:class:`ASyncFunctionAsyncDefault`
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@overload # sync def none default
|
|
140
|
+
def a_sync(
|
|
47
141
|
coro_fn: SyncFn[P, T],
|
|
48
142
|
default: Literal[None] = None,
|
|
49
143
|
**modifiers: Unpack[ModifierKwargs],
|
|
50
|
-
) -> ASyncFunctionSyncDefault[P, T]
|
|
144
|
+
) -> ASyncFunctionSyncDefault[P, T]:
|
|
145
|
+
"""
|
|
146
|
+
Decorates a synchronous function with no default execution mode specified.
|
|
51
147
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
148
|
+
Args:
|
|
149
|
+
coro_fn: The synchronous function to be decorated.
|
|
150
|
+
default: Specifies no default execution mode.
|
|
151
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
152
|
+
|
|
153
|
+
Examples:
|
|
154
|
+
Decorating a synchronous function without a default mode:
|
|
155
|
+
|
|
156
|
+
>>> def my_function():
|
|
157
|
+
... return True
|
|
158
|
+
>>> decorated_function = a_sync(my_function)
|
|
159
|
+
>>> decorated_function()
|
|
160
|
+
True
|
|
161
|
+
>>> await decorated_function(sync=False)
|
|
162
|
+
True
|
|
163
|
+
|
|
164
|
+
See Also:
|
|
165
|
+
:class:`ASyncFunctionSyncDefault`
|
|
166
|
+
"""
|
|
61
167
|
|
|
62
|
-
|
|
63
|
-
|
|
168
|
+
|
|
169
|
+
@overload
|
|
170
|
+
def a_sync(
|
|
64
171
|
coro_fn: Literal[None],
|
|
65
|
-
default: Literal[
|
|
172
|
+
default: Literal["async"],
|
|
66
173
|
**modifiers: Unpack[ModifierKwargs],
|
|
67
|
-
) -> ASyncDecoratorAsyncDefault
|
|
174
|
+
) -> ASyncDecoratorAsyncDefault:
|
|
175
|
+
"""
|
|
176
|
+
Creates an asynchronous default decorator with no function specified.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
coro_fn: Specifies no function.
|
|
180
|
+
default: Specifies the default execution mode as 'async'.
|
|
181
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
182
|
+
|
|
183
|
+
Examples:
|
|
184
|
+
Creating an asynchronous default decorator without a function:
|
|
185
|
+
|
|
186
|
+
>>> @a_sync(default='async')
|
|
187
|
+
... async def my_function():
|
|
188
|
+
... return True
|
|
189
|
+
>>> await my_function()
|
|
190
|
+
True
|
|
191
|
+
>>> my_function(sync=True)
|
|
192
|
+
True
|
|
68
193
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
194
|
+
See Also:
|
|
195
|
+
:class:`ASyncDecoratorAsyncDefault`
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@overload # if you try to use default as the only arg
|
|
200
|
+
def a_sync(
|
|
201
|
+
coro_fn: Literal["async"],
|
|
72
202
|
default: Literal[None],
|
|
73
203
|
**modifiers: Unpack[ModifierKwargs],
|
|
74
|
-
) -> ASyncDecoratorAsyncDefault
|
|
204
|
+
) -> ASyncDecoratorAsyncDefault:
|
|
205
|
+
"""
|
|
206
|
+
Creates an asynchronous default decorator with no default execution mode specified.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
coro_fn: Specifies the default execution mode as 'async'.
|
|
210
|
+
default: Specifies no default execution mode.
|
|
211
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
75
212
|
|
|
76
|
-
|
|
213
|
+
Examples:
|
|
214
|
+
Using 'async' as the only argument:
|
|
215
|
+
|
|
216
|
+
>>> @a_sync('async')
|
|
217
|
+
... async def my_function():
|
|
218
|
+
... return True
|
|
219
|
+
>>> await my_function()
|
|
220
|
+
True
|
|
221
|
+
>>> my_function(sync=True)
|
|
222
|
+
True
|
|
223
|
+
|
|
224
|
+
See Also:
|
|
225
|
+
:class:`ASyncDecoratorAsyncDefault`
|
|
226
|
+
"""
|
|
77
227
|
|
|
78
|
-
|
|
79
|
-
def
|
|
228
|
+
|
|
229
|
+
@overload # async def, async default
|
|
230
|
+
def a_sync(
|
|
80
231
|
coro_fn: CoroFn[P, T],
|
|
81
|
-
default: Literal[
|
|
232
|
+
default: Literal["async"],
|
|
82
233
|
**modifiers: Unpack[ModifierKwargs],
|
|
83
|
-
) -> ASyncFunctionAsyncDefault[P, T]
|
|
234
|
+
) -> ASyncFunctionAsyncDefault[P, T]:
|
|
235
|
+
"""
|
|
236
|
+
Decorates an asynchronous function with an asynchronous default execution mode.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
coro_fn: The coroutine function to be decorated.
|
|
240
|
+
default: Specifies the default execution mode as 'async'.
|
|
241
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
84
242
|
|
|
85
|
-
|
|
86
|
-
|
|
243
|
+
Examples:
|
|
244
|
+
Decorating an asynchronous function with an async default:
|
|
245
|
+
|
|
246
|
+
>>> async def my_function():
|
|
247
|
+
... return True
|
|
248
|
+
>>> decorated_function = a_sync(my_function, default='async')
|
|
249
|
+
>>> await decorated_function()
|
|
250
|
+
True
|
|
251
|
+
>>> decorated_function(sync=True)
|
|
252
|
+
True
|
|
253
|
+
|
|
254
|
+
See Also:
|
|
255
|
+
:class:`ASyncFunctionAsyncDefault`
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@overload # sync def async default
|
|
260
|
+
def a_sync(
|
|
87
261
|
coro_fn: SyncFn[P, T],
|
|
88
|
-
default: Literal[
|
|
262
|
+
default: Literal["async"],
|
|
89
263
|
**modifiers: Unpack[ModifierKwargs],
|
|
90
|
-
) -> ASyncFunctionAsyncDefault[P, T]
|
|
264
|
+
) -> ASyncFunctionAsyncDefault[P, T]:
|
|
265
|
+
"""
|
|
266
|
+
Decorates a synchronous function with an asynchronous default execution mode.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
coro_fn: The synchronous function to be decorated.
|
|
270
|
+
default: Specifies the default execution mode as 'async'.
|
|
271
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
91
272
|
|
|
92
|
-
|
|
273
|
+
Examples:
|
|
274
|
+
Decorating a synchronous function with an async default:
|
|
275
|
+
|
|
276
|
+
>>> def my_function():
|
|
277
|
+
... return True
|
|
278
|
+
>>> decorated_function = a_sync(my_function, default='async')
|
|
279
|
+
>>> await decorated_function()
|
|
280
|
+
True
|
|
281
|
+
>>> decorated_function(sync=True)
|
|
282
|
+
True
|
|
283
|
+
|
|
284
|
+
See Also:
|
|
285
|
+
:class:`ASyncFunctionAsyncDefault`
|
|
286
|
+
"""
|
|
93
287
|
|
|
94
|
-
|
|
95
|
-
def
|
|
288
|
+
|
|
289
|
+
@overload # async def, sync default
|
|
290
|
+
def a_sync(
|
|
96
291
|
coro_fn: CoroFn[P, T],
|
|
97
|
-
default: Literal[
|
|
292
|
+
default: Literal["sync"],
|
|
98
293
|
**modifiers: Unpack[ModifierKwargs],
|
|
99
|
-
) -> ASyncFunctionSyncDefault
|
|
294
|
+
) -> ASyncFunctionSyncDefault:
|
|
295
|
+
"""
|
|
296
|
+
Decorates an asynchronous function with a synchronous default execution mode.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
coro_fn: The coroutine function to be decorated.
|
|
300
|
+
default: Specifies the default execution mode as 'sync'.
|
|
301
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
302
|
+
|
|
303
|
+
Examples:
|
|
304
|
+
Decorating an asynchronous function with a sync default:
|
|
305
|
+
|
|
306
|
+
>>> async def my_function():
|
|
307
|
+
... return True
|
|
308
|
+
>>> decorated_function = a_sync(my_function, default='sync')
|
|
309
|
+
>>> decorated_function()
|
|
310
|
+
True
|
|
311
|
+
>>> await decorated_function(sync=False)
|
|
312
|
+
True
|
|
313
|
+
|
|
314
|
+
See Also:
|
|
315
|
+
:class:`ASyncFunctionSyncDefault`
|
|
316
|
+
"""
|
|
317
|
+
|
|
100
318
|
|
|
101
|
-
@overload
|
|
102
|
-
def a_sync(
|
|
319
|
+
@overload # sync def sync default
|
|
320
|
+
def a_sync(
|
|
103
321
|
coro_fn: SyncFn[P, T],
|
|
104
|
-
default: Literal[
|
|
322
|
+
default: Literal["sync"],
|
|
105
323
|
**modifiers: Unpack[ModifierKwargs],
|
|
106
|
-
) -> ASyncFunctionSyncDefault
|
|
324
|
+
) -> ASyncFunctionSyncDefault:
|
|
325
|
+
"""
|
|
326
|
+
Decorates a synchronous function with a synchronous default execution mode.
|
|
107
327
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
#
|
|
116
|
-
# NOTE These should output a decorator that will be applied to 'some_fn'
|
|
328
|
+
Args:
|
|
329
|
+
coro_fn: The synchronous function to be decorated.
|
|
330
|
+
default: Specifies the default execution mode as 'sync'.
|
|
331
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
332
|
+
|
|
333
|
+
Examples:
|
|
334
|
+
Decorating a synchronous function with a sync default:
|
|
117
335
|
|
|
118
|
-
|
|
119
|
-
|
|
336
|
+
>>> def my_function():
|
|
337
|
+
... return True
|
|
338
|
+
>>> decorated_function = a_sync(my_function, default='sync')
|
|
339
|
+
>>> decorated_function()
|
|
340
|
+
True
|
|
341
|
+
>>> await decorated_function(sync=False)
|
|
342
|
+
True
|
|
343
|
+
|
|
344
|
+
See Also:
|
|
345
|
+
:class:`ASyncFunctionSyncDefault`
|
|
346
|
+
"""
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
@overload
|
|
350
|
+
def a_sync(
|
|
120
351
|
coro_fn: Literal[None],
|
|
121
|
-
default: Literal[
|
|
352
|
+
default: Literal["sync"],
|
|
122
353
|
**modifiers: Unpack[ModifierKwargs],
|
|
123
|
-
) -> ASyncDecoratorSyncDefault
|
|
354
|
+
) -> ASyncDecoratorSyncDefault:
|
|
355
|
+
"""
|
|
356
|
+
Creates a synchronous default decorator with no function specified.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
coro_fn: Specifies no function.
|
|
360
|
+
default: Specifies the default execution mode as 'sync'.
|
|
361
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
124
362
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
363
|
+
Examples:
|
|
364
|
+
Creating a synchronous default decorator without a function:
|
|
365
|
+
|
|
366
|
+
>>> @a_sync(default='sync')
|
|
367
|
+
... def my_function():
|
|
368
|
+
... return True
|
|
369
|
+
>>> my_function()
|
|
370
|
+
True
|
|
371
|
+
>>> await my_function(sync=False)
|
|
372
|
+
True
|
|
373
|
+
|
|
374
|
+
See Also:
|
|
375
|
+
:class:`ASyncDecoratorSyncDefault`
|
|
376
|
+
"""
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
@overload # if you try to use default as the only arg
|
|
380
|
+
def a_sync(
|
|
381
|
+
coro_fn: Literal["sync"],
|
|
128
382
|
default: Literal[None] = None,
|
|
129
383
|
**modifiers: Unpack[ModifierKwargs],
|
|
130
|
-
) -> ASyncDecoratorSyncDefault
|
|
384
|
+
) -> ASyncDecoratorSyncDefault:
|
|
385
|
+
"""
|
|
386
|
+
Creates a synchronous default decorator with no default execution mode specified.
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
coro_fn: Specifies the default execution mode as 'sync'.
|
|
390
|
+
default: Specifies no default execution mode.
|
|
391
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
131
392
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
393
|
+
Examples:
|
|
394
|
+
Using 'sync' as the only argument:
|
|
395
|
+
|
|
396
|
+
>>> @a_sync('sync')
|
|
397
|
+
... def my_function():
|
|
398
|
+
... return True
|
|
399
|
+
>>> my_function()
|
|
400
|
+
True
|
|
401
|
+
>>> await my_function(sync=False)
|
|
402
|
+
True
|
|
403
|
+
|
|
404
|
+
See Also:
|
|
405
|
+
:class:`ASyncDecoratorSyncDefault`
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@overload # if you try to use default as the only arg
|
|
410
|
+
def a_sync(
|
|
411
|
+
coro_fn: Literal["sync"],
|
|
135
412
|
default: Literal[None],
|
|
136
413
|
**modifiers: Unpack[ModifierKwargs],
|
|
137
|
-
) -> ASyncDecoratorSyncDefault
|
|
138
|
-
|
|
414
|
+
) -> ASyncDecoratorSyncDefault:
|
|
415
|
+
"""
|
|
416
|
+
Creates a synchronous default decorator with no default execution mode specified.
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
coro_fn: Specifies the default execution mode as 'sync'.
|
|
420
|
+
default: Specifies no default execution mode.
|
|
421
|
+
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
422
|
+
|
|
423
|
+
Examples:
|
|
424
|
+
Using 'sync' as the only argument:
|
|
425
|
+
|
|
426
|
+
>>> @a_sync('sync')
|
|
427
|
+
... def my_function():
|
|
428
|
+
... return True
|
|
429
|
+
>>> my_function()
|
|
430
|
+
True
|
|
431
|
+
>>> await my_function(sync=False)
|
|
432
|
+
True
|
|
433
|
+
|
|
434
|
+
See Also:
|
|
435
|
+
:class:`ASyncDecoratorSyncDefault`
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
|
|
139
439
|
# catchall
|
|
140
|
-
def a_sync(
|
|
440
|
+
def a_sync(
|
|
141
441
|
coro_fn: Optional[AnyFn[P, T]] = None,
|
|
142
442
|
default: DefaultMode = config.DEFAULT_MODE,
|
|
143
|
-
**modifiers: Unpack[
|
|
443
|
+
**modifiers: Unpack[
|
|
444
|
+
ModifierKwargs
|
|
445
|
+
], # default values are set by passing these kwargs into a ModifierManager object.
|
|
144
446
|
) -> Union[ASyncDecorator, ASyncFunction[P, T]]:
|
|
145
447
|
"""
|
|
146
448
|
A versatile decorator that enables both synchronous and asynchronous execution of functions.
|
|
@@ -155,97 +457,96 @@ def a_sync(
|
|
|
155
457
|
If None, the mode is inferred from the decorated function type.
|
|
156
458
|
**modifiers: Additional keyword arguments to modify the behavior of the decorated function.
|
|
157
459
|
See :class:`ModifierKwargs` for available options.
|
|
158
|
-
|
|
460
|
+
|
|
159
461
|
Modifiers:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
462
|
+
The following modifiers can be used to customize the behavior of the decorator:
|
|
463
|
+
|
|
464
|
+
- cache_type: Can be None or 'memory'. 'memory' is an LRU cache which can be modified with
|
|
465
|
+
the 'cache_typed', 'ram_cache_maxsize', and 'ram_cache_ttl' modifiers.
|
|
466
|
+
- cache_typed: Set to True if you want types considered for cache keys. For example, with
|
|
467
|
+
cache_typed=True, Decimal(0) and 0 will be considered separate keys.
|
|
468
|
+
- ram_cache_maxsize: The max size for your LRU cache. None if the cache is unbounded. If you
|
|
469
|
+
set this value without specifying a cache type, 'memory' will automatically be applied.
|
|
470
|
+
- ram_cache_ttl: The TTL for items in your LRU cache. Set to None. If you set this value
|
|
471
|
+
without specifying a cache type, 'memory' will automatically be applied.
|
|
472
|
+
- runs_per_minute: Setting this value enables a rate limiter for the decorated function.
|
|
473
|
+
- semaphore: Drop in a Semaphore for your async defined functions.
|
|
474
|
+
- executor: The executor for the synchronous function. Set to the library's default of
|
|
475
|
+
config.default_sync_executor.
|
|
174
476
|
|
|
175
477
|
Examples:
|
|
176
478
|
The decorator can be used in several ways.
|
|
177
479
|
|
|
178
480
|
1. As a simple decorator:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
>>> some_sync_fn(sync=False)
|
|
195
|
-
<coroutine object some_sync_fn at 0x12345678>
|
|
196
|
-
```
|
|
481
|
+
>>> @a_sync
|
|
482
|
+
... async def some_async_fn():
|
|
483
|
+
... return True
|
|
484
|
+
>>> await some_async_fn()
|
|
485
|
+
True
|
|
486
|
+
>>> some_async_fn(sync=True)
|
|
487
|
+
True
|
|
488
|
+
|
|
489
|
+
>>> @a_sync
|
|
490
|
+
... def some_sync_fn():
|
|
491
|
+
... return True
|
|
492
|
+
>>> some_sync_fn()
|
|
493
|
+
True
|
|
494
|
+
>>> some_sync_fn(sync=False)
|
|
495
|
+
<coroutine object some_sync_fn at 0x7fb4f5fb49c0>
|
|
197
496
|
|
|
198
497
|
2. As a decorator with default mode specified:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
498
|
+
>>> @a_sync(default='sync')
|
|
499
|
+
... async def some_fn():
|
|
500
|
+
... return True
|
|
501
|
+
...
|
|
502
|
+
>>> some_fn()
|
|
503
|
+
True
|
|
504
|
+
>>> some_fn(sync=False)
|
|
505
|
+
<coroutine object some_fn at 0x7fb4f5fb49c0>
|
|
506
|
+
|
|
507
|
+
>>> @a_sync('async')
|
|
508
|
+
... def some_fn():
|
|
509
|
+
... return True
|
|
510
|
+
...
|
|
511
|
+
>>> some_fn()
|
|
512
|
+
<coroutine object some_fn at 0x7fb4f5fb49c0>
|
|
513
|
+
>>> some_fn(asynchronous=False)
|
|
514
|
+
True
|
|
207
515
|
|
|
208
516
|
3. As a decorator with modifiers:
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
True
|
|
216
|
-
```
|
|
517
|
+
>>> @a_sync(cache_type='memory', runs_per_minute=60)
|
|
518
|
+
... async def some_fn():
|
|
519
|
+
... return True
|
|
520
|
+
...
|
|
521
|
+
>>> some_fn(sync=True)
|
|
522
|
+
True
|
|
217
523
|
|
|
218
524
|
4. Applied directly to a function:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
"some return value"
|
|
223
|
-
```
|
|
525
|
+
>>> some_fn = a_sync(some_existing_function, default='sync')
|
|
526
|
+
>>> some_fn()
|
|
527
|
+
"some return value"
|
|
224
528
|
|
|
225
529
|
The decorated function can then be called either synchronously or asynchronously:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
result = some_fn() # Synchronous call
|
|
229
|
-
result = await some_fn() # Asynchronous call
|
|
230
|
-
```
|
|
530
|
+
>>> result = some_fn() # Synchronous call
|
|
531
|
+
>>> result = await some_fn() # Asynchronous call
|
|
231
532
|
|
|
232
533
|
The execution mode can also be explicitly specified during the call:
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
result = some_fn(sync=True) # Force synchronous execution
|
|
236
|
-
result = await some_fn(sync=False) # Force asynchronous execution
|
|
237
|
-
```
|
|
534
|
+
>>> result = some_fn(sync=True) # Force synchronous execution
|
|
535
|
+
>>> result = await some_fn(sync=False) # Force asynchronous execution
|
|
238
536
|
|
|
239
537
|
This decorator is particularly useful for libraries that need to support
|
|
240
538
|
both synchronous and asynchronous usage, or for gradually migrating
|
|
241
539
|
synchronous code to asynchronous without breaking existing interfaces.
|
|
540
|
+
|
|
541
|
+
See Also:
|
|
542
|
+
:class:`ASyncFunction`, :class:`ASyncDecorator`
|
|
242
543
|
"""
|
|
243
|
-
|
|
544
|
+
|
|
244
545
|
# If the dev tried passing a default as an arg instead of a kwarg, ie: @a_sync('sync')...
|
|
245
|
-
if coro_fn in [
|
|
546
|
+
if coro_fn in ["async", "sync"]:
|
|
246
547
|
default = coro_fn # type: ignore [assignment]
|
|
247
548
|
coro_fn = None
|
|
248
|
-
|
|
549
|
+
|
|
249
550
|
if default == "sync":
|
|
250
551
|
deco = ASyncDecoratorSyncDefault(default=default, **modifiers)
|
|
251
552
|
elif default == "async":
|
|
@@ -254,4 +555,5 @@ def a_sync(
|
|
|
254
555
|
deco = ASyncDecorator(default=default, **modifiers)
|
|
255
556
|
return deco if coro_fn is None else deco(coro_fn) # type: ignore [arg-type]
|
|
256
557
|
|
|
257
|
-
|
|
558
|
+
|
|
559
|
+
# TODO: in a future release, I will make this usable with sync functions as well
|