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/_typing.py
CHANGED
|
@@ -1,22 +1,106 @@
|
|
|
1
1
|
"""
|
|
2
|
-
This module provides type definitions and type-related utilities for the a_sync library.
|
|
3
|
-
|
|
4
|
-
to enhance type checking and provide better IDE support.
|
|
2
|
+
This module provides type definitions and type-related utilities for the `a_sync` library.
|
|
3
|
+
|
|
4
|
+
It includes various type aliases and protocols used throughout the library to enhance type checking and provide better IDE support.
|
|
5
|
+
|
|
6
|
+
Examples:
|
|
7
|
+
The following examples demonstrate how to use some of the type aliases and protocols defined in this module.
|
|
8
|
+
|
|
9
|
+
Example of a function that can return either an awaitable or a direct value:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from a_sync._typing import MaybeAwaitable
|
|
13
|
+
from typing import Awaitable
|
|
14
|
+
|
|
15
|
+
async def process_data(data: MaybeAwaitable[int]) -> int:
|
|
16
|
+
if isinstance(data, Awaitable):
|
|
17
|
+
return await data
|
|
18
|
+
return data
|
|
19
|
+
|
|
20
|
+
# Usage
|
|
21
|
+
import asyncio
|
|
22
|
+
|
|
23
|
+
async def main():
|
|
24
|
+
result = await process_data(asyncio.sleep(1, result=42))
|
|
25
|
+
print(result) # Output: 42
|
|
26
|
+
|
|
27
|
+
result = await process_data(42)
|
|
28
|
+
print(result) # Output: 42
|
|
29
|
+
|
|
30
|
+
asyncio.run(main())
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Example of defining a coroutine function type:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from a_sync._typing import CoroFn
|
|
37
|
+
|
|
38
|
+
async def async_function(x: int) -> str:
|
|
39
|
+
return str(x)
|
|
40
|
+
|
|
41
|
+
coro_fn: CoroFn[[int], str] = async_function
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Example of defining a synchronous function type:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from a_sync._typing import SyncFn
|
|
48
|
+
|
|
49
|
+
def sync_function(x: int) -> str:
|
|
50
|
+
return str(x)
|
|
51
|
+
|
|
52
|
+
sync_fn: SyncFn[[int], str] = sync_function
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
See Also:
|
|
56
|
+
- :mod:`typing`
|
|
57
|
+
- :mod:`asyncio`
|
|
5
58
|
"""
|
|
6
59
|
|
|
7
60
|
import asyncio
|
|
8
61
|
from concurrent.futures._base import Executor
|
|
9
62
|
from decimal import Decimal
|
|
10
|
-
from typing import (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
63
|
+
from typing import (
|
|
64
|
+
TYPE_CHECKING,
|
|
65
|
+
Any,
|
|
66
|
+
AsyncGenerator,
|
|
67
|
+
AsyncIterable,
|
|
68
|
+
AsyncIterator,
|
|
69
|
+
Awaitable,
|
|
70
|
+
Callable,
|
|
71
|
+
Coroutine,
|
|
72
|
+
DefaultDict,
|
|
73
|
+
Deque,
|
|
74
|
+
Dict,
|
|
75
|
+
Generator,
|
|
76
|
+
Generic,
|
|
77
|
+
ItemsView,
|
|
78
|
+
Iterable,
|
|
79
|
+
Iterator,
|
|
80
|
+
KeysView,
|
|
81
|
+
List,
|
|
82
|
+
Literal,
|
|
83
|
+
Mapping,
|
|
84
|
+
NoReturn,
|
|
85
|
+
Optional,
|
|
86
|
+
Protocol,
|
|
87
|
+
Set,
|
|
88
|
+
Tuple,
|
|
89
|
+
Type,
|
|
90
|
+
TypedDict,
|
|
91
|
+
TypeVar,
|
|
92
|
+
Union,
|
|
93
|
+
ValuesView,
|
|
94
|
+
final,
|
|
95
|
+
overload,
|
|
96
|
+
runtime_checkable,
|
|
97
|
+
)
|
|
15
98
|
|
|
16
99
|
from typing_extensions import Concatenate, ParamSpec, Self, Unpack
|
|
17
100
|
|
|
18
101
|
if TYPE_CHECKING:
|
|
19
102
|
from a_sync import ASyncGenericBase
|
|
103
|
+
|
|
20
104
|
B = TypeVar("B", bound=ASyncGenericBase)
|
|
21
105
|
else:
|
|
22
106
|
B = TypeVar("B")
|
|
@@ -27,7 +111,7 @@ V = TypeVar("V")
|
|
|
27
111
|
I = TypeVar("I")
|
|
28
112
|
"""A :class:`TypeVar` that is used to represent instances of a common class."""
|
|
29
113
|
|
|
30
|
-
E = TypeVar(
|
|
114
|
+
E = TypeVar("E", bound=Exception)
|
|
31
115
|
TYPE = TypeVar("TYPE", bound=Type)
|
|
32
116
|
|
|
33
117
|
P = ParamSpec("P")
|
|
@@ -51,6 +135,7 @@ SyncFn = Callable[P, T]
|
|
|
51
135
|
AnyFn = Union[CoroFn[P, T], SyncFn[P, T]]
|
|
52
136
|
"Type alias for any function, whether synchronous or asynchronous."
|
|
53
137
|
|
|
138
|
+
|
|
54
139
|
class CoroBoundMethod(Protocol[I, P, T]):
|
|
55
140
|
"""
|
|
56
141
|
Protocol for coroutine bound methods.
|
|
@@ -59,13 +144,15 @@ class CoroBoundMethod(Protocol[I, P, T]):
|
|
|
59
144
|
class MyClass:
|
|
60
145
|
async def my_method(self, x: int) -> str:
|
|
61
146
|
return str(x)
|
|
62
|
-
|
|
147
|
+
|
|
63
148
|
instance = MyClass()
|
|
64
149
|
bound_method: CoroBoundMethod[MyClass, [int], str] = instance.my_method
|
|
65
150
|
"""
|
|
151
|
+
|
|
66
152
|
__self__: I
|
|
67
153
|
__call__: Callable[P, Awaitable[T]]
|
|
68
154
|
|
|
155
|
+
|
|
69
156
|
class SyncBoundMethod(Protocol[I, P, T]):
|
|
70
157
|
"""
|
|
71
158
|
Protocol for synchronous bound methods.
|
|
@@ -74,36 +161,43 @@ class SyncBoundMethod(Protocol[I, P, T]):
|
|
|
74
161
|
class MyClass:
|
|
75
162
|
def my_method(self, x: int) -> str:
|
|
76
163
|
return str(x)
|
|
77
|
-
|
|
164
|
+
|
|
78
165
|
instance = MyClass()
|
|
79
166
|
bound_method: SyncBoundMethod[MyClass, [int], str] = instance.my_method
|
|
80
167
|
"""
|
|
168
|
+
|
|
81
169
|
__self__: I
|
|
82
170
|
__call__: Callable[P, T]
|
|
83
171
|
|
|
172
|
+
|
|
84
173
|
AnyBoundMethod = Union[CoroBoundMethod[Any, P, T], SyncBoundMethod[Any, P, T]]
|
|
85
174
|
"Type alias for any bound method, whether synchronous or asynchronous."
|
|
86
175
|
|
|
176
|
+
|
|
87
177
|
@runtime_checkable
|
|
88
178
|
class AsyncUnboundMethod(Protocol[I, P, T]):
|
|
89
179
|
"""
|
|
90
180
|
Protocol for unbound asynchronous methods.
|
|
91
|
-
|
|
181
|
+
|
|
92
182
|
An unbound method is a method that hasn't been bound to an instance of a class yet.
|
|
93
183
|
It's essentially the function object itself, before it's accessed through an instance.
|
|
94
184
|
"""
|
|
185
|
+
|
|
95
186
|
__get__: Callable[[I, Type], CoroBoundMethod[I, P, T]]
|
|
96
187
|
|
|
188
|
+
|
|
97
189
|
@runtime_checkable
|
|
98
190
|
class SyncUnboundMethod(Protocol[I, P, T]):
|
|
99
191
|
"""
|
|
100
192
|
Protocol for unbound synchronous methods.
|
|
101
|
-
|
|
193
|
+
|
|
102
194
|
An unbound method is a method that hasn't been bound to an instance of a class yet.
|
|
103
195
|
It's essentially the function object itself, before it's accessed through an instance.
|
|
104
196
|
"""
|
|
197
|
+
|
|
105
198
|
__get__: Callable[[I, Type], SyncBoundMethod[I, P, T]]
|
|
106
199
|
|
|
200
|
+
|
|
107
201
|
AnyUnboundMethod = Union[AsyncUnboundMethod[I, P, T], SyncUnboundMethod[I, P, T]]
|
|
108
202
|
"Type alias for any unbound method, whether synchronous or asynchronous."
|
|
109
203
|
|
|
@@ -122,19 +216,21 @@ AsyncDecorator = Callable[[CoroFn[P, T]], CoroFn[P, T]]
|
|
|
122
216
|
AsyncDecoratorOrCoroFn = Union[AsyncDecorator[P, T], CoroFn[P, T]]
|
|
123
217
|
"Type alias for either an asynchronous decorator or a coroutine function."
|
|
124
218
|
|
|
125
|
-
DefaultMode = Literal[
|
|
219
|
+
DefaultMode = Literal["sync", "async", None]
|
|
126
220
|
"Type alias for default modes of operation."
|
|
127
221
|
|
|
128
|
-
CacheType = Literal[
|
|
222
|
+
CacheType = Literal["memory", None]
|
|
129
223
|
"Type alias for cache types."
|
|
130
224
|
|
|
131
225
|
SemaphoreSpec = Optional[Union[asyncio.Semaphore, int]]
|
|
132
226
|
"Type alias for semaphore specifications."
|
|
133
227
|
|
|
228
|
+
|
|
134
229
|
class ModifierKwargs(TypedDict, total=False):
|
|
135
230
|
"""
|
|
136
231
|
TypedDict for keyword arguments that modify the behavior of asynchronous operations.
|
|
137
232
|
"""
|
|
233
|
+
|
|
138
234
|
default: DefaultMode
|
|
139
235
|
cache_type: CacheType
|
|
140
236
|
cache_typed: bool
|
|
@@ -145,6 +241,7 @@ class ModifierKwargs(TypedDict, total=False):
|
|
|
145
241
|
# sync modifiers
|
|
146
242
|
executor: Executor
|
|
147
243
|
|
|
244
|
+
|
|
148
245
|
AnyIterable = Union[AsyncIterable[K], Iterable[K]]
|
|
149
246
|
"Type alias for any iterable, whether synchronous or asynchronous."
|
|
150
247
|
|
a_sync/a_sync/__init__.py
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module enables developers to write both synchronous and asynchronous code without having to write redundant code.
|
|
3
|
+
|
|
4
|
+
The two main objects you should use are
|
|
5
|
+
- a decorator `@a_sync()`
|
|
6
|
+
- a base class `ASyncGenericBase` which can be used to create classes that can be utilized in both synchronous and asynchronous contexts.
|
|
7
|
+
|
|
8
|
+
The rest of the objects are exposed for type checking only, you should not make use of them otherwise.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# TODO: double check on these before adding them to docs
|
|
12
|
+
# - two decorators @:class:`property` and @:class:`cached_property` for the creation of dual-function properties and cached properties, respectively.
|
|
1
13
|
|
|
2
14
|
from a_sync.a_sync.base import ASyncGenericBase
|
|
3
15
|
from a_sync.a_sync.decorator import a_sync
|
|
4
|
-
from a_sync.a_sync.function import
|
|
16
|
+
from a_sync.a_sync.function import (
|
|
17
|
+
ASyncFunction,
|
|
18
|
+
ASyncFunctionAsyncDefault,
|
|
19
|
+
ASyncFunctionSyncDefault,
|
|
20
|
+
)
|
|
5
21
|
from a_sync.a_sync.modifiers.semaphores import apply_semaphore
|
|
22
|
+
|
|
6
23
|
# NOTE: Some of these we purposely import without including in __all__. Do not remove.
|
|
7
|
-
from a_sync.a_sync.property import (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
24
|
+
from a_sync.a_sync.property import (
|
|
25
|
+
ASyncCachedPropertyDescriptor,
|
|
26
|
+
ASyncCachedPropertyDescriptorAsyncDefault,
|
|
27
|
+
ASyncCachedPropertyDescriptorSyncDefault,
|
|
28
|
+
ASyncPropertyDescriptor,
|
|
29
|
+
ASyncPropertyDescriptorAsyncDefault,
|
|
30
|
+
ASyncPropertyDescriptorSyncDefault,
|
|
31
|
+
HiddenMethod,
|
|
32
|
+
HiddenMethodDescriptor,
|
|
33
|
+
cached_property,
|
|
34
|
+
property,
|
|
35
|
+
)
|
|
11
36
|
from a_sync.a_sync.singleton import ASyncGenericSingleton
|
|
12
37
|
|
|
13
38
|
|
|
@@ -15,14 +40,14 @@ __all__ = [
|
|
|
15
40
|
# entrypoints
|
|
16
41
|
"a_sync",
|
|
17
42
|
"ASyncGenericBase",
|
|
18
|
-
|
|
19
|
-
#
|
|
20
|
-
"ASyncFunction",
|
|
21
|
-
|
|
43
|
+
# maybe entrypoints (?)
|
|
44
|
+
# TODO: double check how I intended for these to be used
|
|
22
45
|
"property",
|
|
23
46
|
"cached_property",
|
|
47
|
+
# classes exposed for type hinting only
|
|
48
|
+
"ASyncFunction",
|
|
24
49
|
"ASyncPropertyDescriptor",
|
|
25
50
|
"ASyncCachedPropertyDescriptor",
|
|
26
51
|
"HiddenMethod",
|
|
27
52
|
"HiddenMethodDescriptor",
|
|
28
|
-
]
|
|
53
|
+
]
|