ez-a-sync 0.22.16__tar.gz → 0.23.0__tar.gz
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.
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.github/workflows/pytest.yaml +5 -3
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.github/workflows/release.yaml +2 -2
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.gitignore +5 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/Makefile +3 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/PKG-INFO +2 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/ENVIRONMENT_VARIABLES.py +1 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/__init__.py +8 -10
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/_smart.py +57 -4
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/_typing.py +9 -2
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/_descriptor.py +42 -79
- ez_a_sync-0.23.0/a_sync/a_sync/_flags.c +7452 -0
- ez_a_sync-0.23.0/a_sync/a_sync/_flags.pyi +61 -0
- ez_a_sync-0.22.16/a_sync/a_sync/_flags.py → ez_a_sync-0.23.0/a_sync/a_sync/_flags.pyx +30 -15
- ez_a_sync-0.23.0/a_sync/a_sync/_kwargs.c +7900 -0
- ez_a_sync-0.23.0/a_sync/a_sync/_kwargs.pyi +52 -0
- ez_a_sync-0.22.16/a_sync/a_sync/_kwargs.py → ez_a_sync-0.23.0/a_sync/a_sync/_kwargs.pyx +3 -3
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/base.py +1 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/config.py +41 -13
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/decorator.py +4 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/function.py +6 -5
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/method.py +5 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/modifiers/manager.py +85 -18
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/modifiers/semaphores.py +1 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/property.py +5 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/singleton.py +5 -3
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/asyncio/__init__.py +8 -3
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/asyncio/as_completed.py +4 -4
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/asyncio/create_task.py +4 -7
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/exceptions.py +15 -2
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/executor.py +56 -18
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/future.py +24 -6
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/iter.py +50 -9
- ez_a_sync-0.23.0/a_sync/primitives/__init__.py +53 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/_debug.py +1 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/_loggable.py +5 -2
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/locks/counter.py +5 -3
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/locks/prio_semaphore.py +8 -2
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/locks/semaphore.py +6 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/task.py +2 -2
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/conf.py +5 -0
- ez_a_sync-0.23.0/docs/index.rst +48 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/ez_a_sync.egg-info/PKG-INFO +2 -1
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/ez_a_sync.egg-info/SOURCES.txt +7 -2
- ez_a_sync-0.23.0/ez_a_sync.egg-info/not-zip-safe +1 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/ez_a_sync.egg-info/requires.txt +1 -0
- ez_a_sync-0.23.0/pyproject.yaml +5 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/requirements-dev.txt +2 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/requirements.txt +1 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/setup.py +5 -3
- ez_a_sync-0.23.0/tests/executor.py +240 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_executor.py +19 -6
- ez_a_sync-0.22.16/a_sync/primitives/__init__.py +0 -30
- ez_a_sync-0.22.16/docs/index.rst +0 -20
- ez_a_sync-0.22.16/pyproject.yaml +0 -2
- ez_a_sync-0.22.16/tests/executor.py +0 -252
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.coverage +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.github/workflows/black.yaml +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.github/workflows/codeql.yaml +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.github/workflows/docs.yaml +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.github/workflows/mypy.yaml +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/.sourcery.yaml +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/LICENSE.txt +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/README.md +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/TODO +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/__init__.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/_helpers.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/_meta.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/abstract.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/modifiers/__init__.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/modifiers/cache/__init__.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/modifiers/cache/memory.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/a_sync/modifiers/limiter.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/aliases.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/asyncio/gather.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/asyncio/utils.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/locks/__init__.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/locks/event.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/primitives/queue.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/py.typed +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/sphinx/__init__.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/sphinx/ext.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/utils/__init__.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/a_sync/utils/iterators.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/Makefile +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/alabaster.css +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/basic.css +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/custom.css +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/doctools.js +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/documentation_options.js +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/file.png +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/language_data.js +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/minus.png +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/plus.png +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/pygments.css +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/searchtools.js +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/_build/html/_static/sphinx_highlight.js +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/docs/make.bat +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/ez_a_sync.egg-info/dependency_links.txt +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/ez_a_sync.egg-info/top_level.txt +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/setup.cfg +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/__init__.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/conftest.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/fixtures.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_abstract.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_as_completed.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_base.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_cache.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_decorator.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_future.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_gather.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_helpers.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_iter.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_limiter.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_meta.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_modified.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_semaphore.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_singleton.py +0 -0
- {ez_a_sync-0.22.16 → ez_a_sync-0.23.0}/tests/test_task.py +0 -0
|
@@ -38,10 +38,12 @@ jobs:
|
|
|
38
38
|
python-version: ${{ matrix.pyversion }}
|
|
39
39
|
|
|
40
40
|
- name: Install dependencies
|
|
41
|
+
run: pip install -r requirements.txt -r requirements-dev.txt
|
|
42
|
+
|
|
43
|
+
- name: Install ez-a-sync
|
|
41
44
|
run: |
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
pip install -r requirements-dev.txt
|
|
45
|
+
python setup.py build_ext --inplace
|
|
46
|
+
python setup.py install
|
|
45
47
|
|
|
46
48
|
- name: Run test suite
|
|
47
49
|
run: pytest
|
|
@@ -21,11 +21,11 @@ jobs:
|
|
|
21
21
|
- name: Install dependencies
|
|
22
22
|
run: |
|
|
23
23
|
python -m pip install --upgrade pip
|
|
24
|
-
pip install setuptools wheel twine
|
|
24
|
+
pip install setuptools wheel twine cython
|
|
25
25
|
- name: Build and publish
|
|
26
26
|
env:
|
|
27
27
|
TWINE_USERNAME: __token__
|
|
28
28
|
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
|
|
29
29
|
run: |
|
|
30
|
-
python setup.py sdist
|
|
30
|
+
python setup.py sdist
|
|
31
31
|
twine upload dist/*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ez-a-sync
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.0
|
|
4
4
|
Summary: A library that makes it easy to define objects that can be used for both sync and async use cases.
|
|
5
5
|
Home-page: https://github.com/BobTheBuidler/a-sync
|
|
6
6
|
Author: BobTheBuidler
|
|
@@ -11,5 +11,6 @@ License-File: LICENSE.txt
|
|
|
11
11
|
Requires-Dist: aiolimiter==1.0.0
|
|
12
12
|
Requires-Dist: async_lru_threadsafe==2.0.4
|
|
13
13
|
Requires-Dist: async_property==0.2.1
|
|
14
|
+
Requires-Dist: Cython>=3.0.11
|
|
14
15
|
Requires-Dist: typed_envs>=0.0.2
|
|
15
16
|
Requires-Dist: typing_extensions>=4.1.0
|
|
@@ -26,7 +26,7 @@ DEBUG_MODE = envs.create_env(
|
|
|
26
26
|
"""bool: Enables debug mode on all classes.
|
|
27
27
|
|
|
28
28
|
Set this environment variable to `True` to enable debug mode on all classes.
|
|
29
|
-
If `DEBUG_CLASS_NAME` is set to a
|
|
29
|
+
If `DEBUG_CLASS_NAME` is set to a non-empty string,
|
|
30
30
|
`DEBUG_MODE` will default to `True`.
|
|
31
31
|
|
|
32
32
|
Examples:
|
|
@@ -8,14 +8,14 @@ that can operate in both synchronous and asynchronous contexts. Additionally, it
|
|
|
8
8
|
such as queues and locks, with extra functionality.
|
|
9
9
|
|
|
10
10
|
Modules and components included:
|
|
11
|
-
- :mod:`~aliases`, :mod:`~exceptions`, :mod:`~iter`, :mod:`~task`: Core modules of the library.
|
|
12
|
-
- :class:`~ASyncGenericBase`, :class:`~ASyncGenericSingleton`, :func:`~a_sync`: Base classes and decorators for dual-context execution.
|
|
13
|
-
- :class:`~ASyncCachedPropertyDescriptor`, :class:`~ASyncPropertyDescriptor`, `cached_property`, `property`: Property descriptors for async properties.
|
|
14
|
-
- :func:`~as_completed`, :func:`~create_task`, :func:`~gather`: Enhanced asyncio functions.
|
|
15
|
-
- Executors: :class:`~AsyncThreadPoolExecutor`, :class:`~AsyncProcessPoolExecutor`, :class:`~PruningThreadPoolExecutor` for async execution.
|
|
16
|
-
- Iterators: :class:`~
|
|
17
|
-
- Utilities: :func:`~all`, :func:`~any`, :func:`~as_yielded
|
|
18
|
-
- :func:`~apply_semaphore`: Function to apply semaphores to coroutines.
|
|
11
|
+
- :mod:`~a_sync.aliases`, :mod:`~a_sync.exceptions`, :mod:`~a_sync.iter`, :mod:`~a_sync.task`: Core modules of the library.
|
|
12
|
+
- :class:`~ASyncGenericBase`, :class:`~ASyncGenericSingleton`, :func:`~a_sync`: Base classes and decorators for dual-context execution.
|
|
13
|
+
- :class:`~ASyncCachedPropertyDescriptor`, :class:`~ASyncPropertyDescriptor`, `cached_property`, `property`: Property descriptors for async properties.
|
|
14
|
+
- :func:`~as_completed`, :func:`~create_task`, :func:`~gather`: Enhanced asyncio functions.
|
|
15
|
+
- Executors: :class:`~AsyncThreadPoolExecutor`, :class:`~AsyncProcessPoolExecutor`, :class:`~PruningThreadPoolExecutor` for async execution.
|
|
16
|
+
- Iterators: :class:`~ASyncIterable`, :class:`~ASyncIterator`, :class:`~filter`, :class:`~sorted` for async iteration.
|
|
17
|
+
- Utilities: :func:`~all`, :func:`~any`, :func:`~as_yielded` for async utilities.
|
|
18
|
+
- :func:`~a_sync.a_sync.modifiers.semaphores.apply_semaphore`: Function to apply semaphores to coroutines.
|
|
19
19
|
|
|
20
20
|
Alias for backward compatibility:
|
|
21
21
|
- :class:`~ASyncBase` is an alias for :class:`~ASyncGenericBase`, which will be removed eventually, probably in version 0.1.0.
|
|
@@ -91,8 +91,6 @@ __all__ = [
|
|
|
91
91
|
"all",
|
|
92
92
|
"any",
|
|
93
93
|
"as_yielded",
|
|
94
|
-
"exhaust_iterator",
|
|
95
|
-
"exhaust_iterators",
|
|
96
94
|
"map",
|
|
97
95
|
# classes
|
|
98
96
|
"ASyncIterable",
|
|
@@ -29,6 +29,26 @@ class _SmartFutureMixin(Generic[T]):
|
|
|
29
29
|
Mixin class that provides common functionality for smart futures and tasks.
|
|
30
30
|
|
|
31
31
|
This mixin provides methods for managing waiters and integrating with a smart processing queue.
|
|
32
|
+
It uses weak references to manage resources efficiently.
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
Creating a SmartFuture and awaiting it:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
future = SmartFuture()
|
|
39
|
+
result = await future
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Creating a SmartTask and awaiting it:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
task = SmartTask(coro=my_coroutine())
|
|
46
|
+
result = await task
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
See Also:
|
|
50
|
+
- :class:`SmartFuture`
|
|
51
|
+
- :class:`SmartTask`
|
|
32
52
|
"""
|
|
33
53
|
|
|
34
54
|
_queue: Optional["SmartProcessingQueue[Any, Any, T]"] = None
|
|
@@ -73,18 +93,22 @@ class _SmartFutureMixin(Generic[T]):
|
|
|
73
93
|
|
|
74
94
|
@property
|
|
75
95
|
def num_waiters(self: Union["SmartFuture", "SmartTask"]) -> int:
|
|
76
|
-
# NOTE: we check .done() because the callback may not have ran yet and its very lightweight
|
|
77
96
|
"""
|
|
78
97
|
Get the number of waiters currently awaiting the future or task.
|
|
79
98
|
|
|
99
|
+
This property checks if the future or task is done to ensure accurate counting
|
|
100
|
+
of waiters, as the callback may not have run yet.
|
|
101
|
+
|
|
80
102
|
Example:
|
|
81
103
|
```python
|
|
82
104
|
future = SmartFuture()
|
|
83
105
|
print(future.num_waiters)
|
|
84
106
|
```
|
|
107
|
+
|
|
108
|
+
See Also:
|
|
109
|
+
- :meth:`_waiter_done_cleanup_callback`
|
|
85
110
|
"""
|
|
86
111
|
if self.done():
|
|
87
|
-
# if there are any waiters left, there won't be once the event loop runs once
|
|
88
112
|
return 0
|
|
89
113
|
return sum(getattr(waiter, "num_waiters", 1) or 1 for waiter in self._waiters)
|
|
90
114
|
|
|
@@ -94,10 +118,13 @@ class _SmartFutureMixin(Generic[T]):
|
|
|
94
118
|
"""
|
|
95
119
|
Callback to clean up waiters when a waiter task is done.
|
|
96
120
|
|
|
97
|
-
Removes the waiter from _waiters, and _queue._futs if applicable
|
|
121
|
+
Removes the waiter from _waiters, and _queue._futs if applicable.
|
|
98
122
|
|
|
99
123
|
Args:
|
|
100
124
|
waiter: The waiter task to clean up.
|
|
125
|
+
|
|
126
|
+
Example:
|
|
127
|
+
Automatically called when a waiter task completes.
|
|
101
128
|
"""
|
|
102
129
|
if not self.done():
|
|
103
130
|
self._waiters.remove(waiter)
|
|
@@ -105,6 +132,8 @@ class _SmartFutureMixin(Generic[T]):
|
|
|
105
132
|
def _self_done_cleanup_callback(self: Union["SmartFuture", "SmartTask"]) -> None:
|
|
106
133
|
"""
|
|
107
134
|
Callback to clean up waiters and remove the future from the queue when done.
|
|
135
|
+
|
|
136
|
+
This method clears all waiters and removes the future from the associated queue.
|
|
108
137
|
"""
|
|
109
138
|
self._waiters.clear()
|
|
110
139
|
if queue := self._queue:
|
|
@@ -125,6 +154,10 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
|
|
|
125
154
|
future = SmartFuture()
|
|
126
155
|
await future
|
|
127
156
|
```
|
|
157
|
+
|
|
158
|
+
See Also:
|
|
159
|
+
- :class:`_SmartFutureMixin`
|
|
160
|
+
- :class:`asyncio.Future`
|
|
128
161
|
"""
|
|
129
162
|
|
|
130
163
|
_queue = None
|
|
@@ -149,6 +182,9 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
|
|
|
149
182
|
```python
|
|
150
183
|
future = SmartFuture(queue=my_queue, key=my_key)
|
|
151
184
|
```
|
|
185
|
+
|
|
186
|
+
See Also:
|
|
187
|
+
- :class:`SmartProcessingQueue`
|
|
152
188
|
"""
|
|
153
189
|
super().__init__(loop=loop)
|
|
154
190
|
if queue:
|
|
@@ -175,6 +211,9 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
|
|
|
175
211
|
future2 = SmartFuture()
|
|
176
212
|
print(future1 < future2)
|
|
177
213
|
```
|
|
214
|
+
|
|
215
|
+
See Also:
|
|
216
|
+
- :meth:`num_waiters`
|
|
178
217
|
"""
|
|
179
218
|
return self.num_waiters > other.num_waiters
|
|
180
219
|
|
|
@@ -202,6 +241,9 @@ def create_future(
|
|
|
202
241
|
```python
|
|
203
242
|
future = create_future(queue=my_queue, key=my_key)
|
|
204
243
|
```
|
|
244
|
+
|
|
245
|
+
See Also:
|
|
246
|
+
- :class:`SmartFuture`
|
|
205
247
|
"""
|
|
206
248
|
return SmartFuture(queue=queue, key=key, loop=loop or asyncio.get_event_loop())
|
|
207
249
|
|
|
@@ -220,6 +262,10 @@ class SmartTask(_SmartFutureMixin[T], asyncio.Task):
|
|
|
220
262
|
task = SmartTask(coro=my_coroutine())
|
|
221
263
|
await task
|
|
222
264
|
```
|
|
265
|
+
|
|
266
|
+
See Also:
|
|
267
|
+
- :class:`_SmartFutureMixin`
|
|
268
|
+
- :class:`asyncio.Task`
|
|
223
269
|
"""
|
|
224
270
|
|
|
225
271
|
def __init__(
|
|
@@ -241,6 +287,9 @@ class SmartTask(_SmartFutureMixin[T], asyncio.Task):
|
|
|
241
287
|
```python
|
|
242
288
|
task = SmartTask(coro=my_coroutine(), name="my_task")
|
|
243
289
|
```
|
|
290
|
+
|
|
291
|
+
See Also:
|
|
292
|
+
- :func:`asyncio.create_task`
|
|
244
293
|
"""
|
|
245
294
|
super().__init__(coro, loop=loop, name=name)
|
|
246
295
|
self._waiters: Set["asyncio.Task[T]"] = set()
|
|
@@ -272,6 +321,7 @@ def smart_task_factory(
|
|
|
272
321
|
|
|
273
322
|
See Also:
|
|
274
323
|
- :func:`set_smart_task_factory`
|
|
324
|
+
- :class:`SmartTask`
|
|
275
325
|
"""
|
|
276
326
|
return SmartTask(coro, loop=loop)
|
|
277
327
|
|
|
@@ -300,7 +350,7 @@ def set_smart_task_factory(loop: asyncio.AbstractEventLoop = None) -> None:
|
|
|
300
350
|
|
|
301
351
|
def shield(
|
|
302
352
|
arg: Awaitable[T], *, loop: Optional[asyncio.AbstractEventLoop] = None
|
|
303
|
-
) -> SmartFuture[T]:
|
|
353
|
+
) -> Union[SmartFuture[T], asyncio.Future]:
|
|
304
354
|
"""
|
|
305
355
|
Wait for a future, shielding it from cancellation.
|
|
306
356
|
|
|
@@ -331,6 +381,9 @@ def shield(
|
|
|
331
381
|
arg: The awaitable to shield from cancellation.
|
|
332
382
|
loop: Optional; the event loop. Deprecated since Python 3.8.
|
|
333
383
|
|
|
384
|
+
Returns:
|
|
385
|
+
A :class:`SmartFuture` or :class:`asyncio.Future` instance.
|
|
386
|
+
|
|
334
387
|
Example:
|
|
335
388
|
Using shield to protect a coroutine from cancellation:
|
|
336
389
|
|
|
@@ -30,10 +30,14 @@ Examples:
|
|
|
30
30
|
asyncio.run(main())
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Example of defining a coroutine function type
|
|
33
|
+
Example of defining a coroutine function type using `CoroFn` with `ParamSpec`:
|
|
34
34
|
|
|
35
35
|
```python
|
|
36
36
|
from a_sync._typing import CoroFn
|
|
37
|
+
from typing_extensions import ParamSpec
|
|
38
|
+
from typing import Awaitable
|
|
39
|
+
|
|
40
|
+
P = ParamSpec("P")
|
|
37
41
|
|
|
38
42
|
async def async_function(x: int) -> str:
|
|
39
43
|
return str(x)
|
|
@@ -41,10 +45,13 @@ Examples:
|
|
|
41
45
|
coro_fn: CoroFn[[int], str] = async_function
|
|
42
46
|
```
|
|
43
47
|
|
|
44
|
-
Example of defining a synchronous function type
|
|
48
|
+
Example of defining a synchronous function type using `SyncFn` with `ParamSpec`:
|
|
45
49
|
|
|
46
50
|
```python
|
|
47
51
|
from a_sync._typing import SyncFn
|
|
52
|
+
from typing_extensions import ParamSpec
|
|
53
|
+
|
|
54
|
+
P = ParamSpec("P")
|
|
48
55
|
|
|
49
56
|
def sync_function(x: int) -> str:
|
|
50
57
|
return str(x)
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
This module contains the :class:`ASyncDescriptor` class, which is used to create dual-function sync/async methods
|
|
3
3
|
and properties.
|
|
4
4
|
|
|
5
|
-
The :class:`ASyncDescriptor` class provides
|
|
6
|
-
|
|
7
|
-
and finding the minimum, maximum, or sum of results of the
|
|
5
|
+
The :class:`ASyncDescriptor` class provides a base for creating descriptors that can handle both synchronous and asynchronous
|
|
6
|
+
operations. It includes utility methods for mapping operations across multiple instances and provides access to common
|
|
7
|
+
operations such as checking if all or any results are truthy, and finding the minimum, maximum, or sum of results of the
|
|
8
|
+
method or property mapped across multiple instances through the use of :class:`~a_sync.a_sync.function.ASyncFunction`.
|
|
8
9
|
|
|
9
10
|
See Also:
|
|
10
11
|
- :class:`~a_sync.a_sync.function.ASyncFunction`
|
|
11
12
|
- :class:`~a_sync.a_sync.method.ASyncMethodDescriptor`
|
|
13
|
+
- :class:`~a_sync.a_sync.property.ASyncPropertyDescriptor`
|
|
12
14
|
"""
|
|
13
15
|
|
|
14
16
|
import functools
|
|
@@ -28,7 +30,7 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
28
30
|
This class provides functionality for mapping operations across multiple instances
|
|
29
31
|
and includes utility methods for common operations such as checking if all or any
|
|
30
32
|
results are truthy, and finding the minimum, maximum, or sum of results of the method
|
|
31
|
-
or property mapped across multiple instances.
|
|
33
|
+
or property mapped across multiple instances through the use of :class:`~a_sync.a_sync.function.ASyncFunction`.
|
|
32
34
|
|
|
33
35
|
Examples:
|
|
34
36
|
To create a dual-function method or property, subclass :class:`ASyncDescriptor` and implement
|
|
@@ -36,12 +38,10 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
36
38
|
across multiple instances.
|
|
37
39
|
|
|
38
40
|
```python
|
|
39
|
-
class MyDescriptor(ASyncDescriptor):
|
|
40
|
-
def __init__(self, func):
|
|
41
|
-
super().__init__(func)
|
|
42
|
-
|
|
43
41
|
class MyClass:
|
|
44
|
-
|
|
42
|
+
@ASyncDescriptor
|
|
43
|
+
def my_method(self, x):
|
|
44
|
+
return x * 2
|
|
45
45
|
|
|
46
46
|
instance = MyClass()
|
|
47
47
|
result = instance.my_method.map([1, 2, 3])
|
|
@@ -119,12 +119,10 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
119
119
|
A :class:`TaskMapping` object.
|
|
120
120
|
|
|
121
121
|
Examples:
|
|
122
|
-
class MyDescriptor(ASyncDescriptor):
|
|
123
|
-
def __init__(self, func):
|
|
124
|
-
super().__init__(func)
|
|
125
|
-
|
|
126
122
|
class MyClass:
|
|
127
|
-
|
|
123
|
+
@ASyncDescriptor
|
|
124
|
+
def my_method(self, x):
|
|
125
|
+
return x * 2
|
|
128
126
|
|
|
129
127
|
instance = MyClass()
|
|
130
128
|
result = instance.my_method.map([1, 2, 3])
|
|
@@ -142,12 +140,10 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
142
140
|
An :class:`ASyncFunction` object.
|
|
143
141
|
|
|
144
142
|
Examples:
|
|
145
|
-
class MyDescriptor(ASyncDescriptor):
|
|
146
|
-
def __init__(self, func):
|
|
147
|
-
super().__init__(func)
|
|
148
|
-
|
|
149
143
|
class MyClass:
|
|
150
|
-
|
|
144
|
+
@ASyncDescriptor
|
|
145
|
+
def my_method(self, x):
|
|
146
|
+
return x > 0
|
|
151
147
|
|
|
152
148
|
instance = MyClass()
|
|
153
149
|
result = await instance.my_method.all([1, 2, 3])
|
|
@@ -163,12 +159,10 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
163
159
|
An :class:`ASyncFunction` object.
|
|
164
160
|
|
|
165
161
|
Examples:
|
|
166
|
-
class MyDescriptor(ASyncDescriptor):
|
|
167
|
-
def __init__(self, func):
|
|
168
|
-
super().__init__(func)
|
|
169
|
-
|
|
170
162
|
class MyClass:
|
|
171
|
-
|
|
163
|
+
@ASyncDescriptor
|
|
164
|
+
def my_method(self, x):
|
|
165
|
+
return x > 0
|
|
172
166
|
|
|
173
167
|
instance = MyClass()
|
|
174
168
|
result = await instance.my_method.any([-1, 0, 1])
|
|
@@ -185,12 +179,10 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
185
179
|
|
|
186
180
|
Examples:
|
|
187
181
|
```python
|
|
188
|
-
class MyDescriptor(ASyncDescriptor):
|
|
189
|
-
def __init__(self, func):
|
|
190
|
-
super().__init__(func)
|
|
191
|
-
|
|
192
182
|
class MyClass:
|
|
193
|
-
|
|
183
|
+
@ASyncDescriptor
|
|
184
|
+
def my_method(self, x):
|
|
185
|
+
return x
|
|
194
186
|
|
|
195
187
|
instance = MyClass()
|
|
196
188
|
result = await instance.my_method.min([3, 1, 2])
|
|
@@ -207,12 +199,10 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
207
199
|
An :class:`ASyncFunction` object.
|
|
208
200
|
|
|
209
201
|
Examples:
|
|
210
|
-
class MyDescriptor(ASyncDescriptor):
|
|
211
|
-
def __init__(self, func):
|
|
212
|
-
super().__init__(func)
|
|
213
|
-
|
|
214
202
|
class MyClass:
|
|
215
|
-
|
|
203
|
+
@ASyncDescriptor
|
|
204
|
+
def my_method(self, x):
|
|
205
|
+
return x
|
|
216
206
|
|
|
217
207
|
instance = MyClass()
|
|
218
208
|
result = await instance.my_method.max([3, 1, 2])
|
|
@@ -229,12 +219,10 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
229
219
|
|
|
230
220
|
Examples:
|
|
231
221
|
```python
|
|
232
|
-
class MyDescriptor(ASyncDescriptor):
|
|
233
|
-
def __init__(self, func):
|
|
234
|
-
super().__init__(func)
|
|
235
|
-
|
|
236
222
|
class MyClass:
|
|
237
|
-
|
|
223
|
+
@ASyncDescriptor
|
|
224
|
+
def my_method(self, x):
|
|
225
|
+
return x
|
|
238
226
|
|
|
239
227
|
instance = MyClass()
|
|
240
228
|
result = await instance.my_method.sum([1, 2, 3])
|
|
@@ -258,17 +246,12 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
258
246
|
name: Optional name for the task.
|
|
259
247
|
**kwargs: Additional keyword arguments.
|
|
260
248
|
|
|
261
|
-
Returns:
|
|
262
|
-
A boolean indicating if all results are truthy.
|
|
263
|
-
|
|
264
249
|
Examples:
|
|
265
250
|
```python
|
|
266
|
-
class MyDescriptor(ASyncDescriptor):
|
|
267
|
-
def __init__(self, func):
|
|
268
|
-
super().__init__(func)
|
|
269
|
-
|
|
270
251
|
class MyClass:
|
|
271
|
-
|
|
252
|
+
@ASyncDescriptor
|
|
253
|
+
def my_method(self, x):
|
|
254
|
+
return x > 0
|
|
272
255
|
|
|
273
256
|
instance = MyClass()
|
|
274
257
|
result = await instance.my_method._all([1, 2, 3])
|
|
@@ -294,17 +277,12 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
294
277
|
name: Optional name for the task.
|
|
295
278
|
**kwargs: Additional keyword arguments.
|
|
296
279
|
|
|
297
|
-
Returns:
|
|
298
|
-
A boolean indicating if any result is truthy.
|
|
299
|
-
|
|
300
280
|
Examples:
|
|
301
281
|
```python
|
|
302
|
-
class MyDescriptor(ASyncDescriptor):
|
|
303
|
-
def __init__(self, func):
|
|
304
|
-
super().__init__(func)
|
|
305
|
-
|
|
306
282
|
class MyClass:
|
|
307
|
-
|
|
283
|
+
@ASyncDescriptor
|
|
284
|
+
def my_method(self, x):
|
|
285
|
+
return x > 0
|
|
308
286
|
|
|
309
287
|
instance = MyClass()
|
|
310
288
|
result = await instance.my_method._any([-1, 0, 1])
|
|
@@ -330,17 +308,12 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
330
308
|
name: Optional name for the task.
|
|
331
309
|
**kwargs: Additional keyword arguments.
|
|
332
310
|
|
|
333
|
-
Returns:
|
|
334
|
-
The minimum result.
|
|
335
|
-
|
|
336
311
|
Examples:
|
|
337
312
|
```python
|
|
338
|
-
class MyDescriptor(ASyncDescriptor):
|
|
339
|
-
def __init__(self, func):
|
|
340
|
-
super().__init__(func)
|
|
341
|
-
|
|
342
313
|
class MyClass:
|
|
343
|
-
|
|
314
|
+
@ASyncDescriptor
|
|
315
|
+
def my_method(self, x):
|
|
316
|
+
return x
|
|
344
317
|
|
|
345
318
|
instance = MyClass()
|
|
346
319
|
result = await instance.my_method._min([3, 1, 2])
|
|
@@ -366,17 +339,12 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
366
339
|
name: Optional name for the task.
|
|
367
340
|
**kwargs: Additional keyword arguments.
|
|
368
341
|
|
|
369
|
-
Returns:
|
|
370
|
-
The maximum result.
|
|
371
|
-
|
|
372
342
|
Examples:
|
|
373
343
|
```python
|
|
374
|
-
class MyDescriptor(ASyncDescriptor):
|
|
375
|
-
def __init__(self, func):
|
|
376
|
-
super().__init__(func)
|
|
377
|
-
|
|
378
344
|
class MyClass:
|
|
379
|
-
|
|
345
|
+
@ASyncDescriptor
|
|
346
|
+
def my_method(self, x):
|
|
347
|
+
return x
|
|
380
348
|
|
|
381
349
|
instance = MyClass()
|
|
382
350
|
result = await instance.my_method._max([3, 1, 2])
|
|
@@ -402,17 +370,12 @@ class ASyncDescriptor(_ModifiedMixin, Generic[I, P, T]):
|
|
|
402
370
|
name: Optional name for the task.
|
|
403
371
|
**kwargs: Additional keyword arguments.
|
|
404
372
|
|
|
405
|
-
Returns:
|
|
406
|
-
The sum of the results.
|
|
407
|
-
|
|
408
373
|
Examples:
|
|
409
374
|
```python
|
|
410
|
-
class MyDescriptor(ASyncDescriptor):
|
|
411
|
-
def __init__(self, func):
|
|
412
|
-
super().__init__(func)
|
|
413
|
-
|
|
414
375
|
class MyClass:
|
|
415
|
-
|
|
376
|
+
@ASyncDescriptor
|
|
377
|
+
def my_method(self, x):
|
|
378
|
+
return x
|
|
416
379
|
|
|
417
380
|
instance = MyClass()
|
|
418
381
|
result = await instance.my_method._sum([1, 2, 3])
|