From 146d70922d0dfe99ab2693c6e8cbc3e7a3906ac0 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Sat, 30 Nov 2024 08:11:34 +0000 Subject: [PATCH 1/2] fix: some excs cant be re-raised how we like --- a_sync/__init__.py | 11 ++++++++++- a_sync/a_sync/modifiers/semaphores.py | 8 ++++---- a_sync/primitives/locks/semaphore.pyx | 3 ++- a_sync/primitives/queue.py | 12 +++--------- a_sync/utils/iterators.py | 4 +--- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/a_sync/__init__.py b/a_sync/__init__.py index d8f68d19..7b19975f 100644 --- a/a_sync/__init__.py +++ b/a_sync/__init__.py @@ -16,6 +16,7 @@ - Iterators: :class:`~ASyncIterable`, :class:`~ASyncIterator`, :class:`~filter`, :class:`~sorted` for async iteration. - Utilities: :func:`~all`, :func:`~any`, :func:`~as_yielded` for async utilities. - :func:`~a_sync.a_sync.modifiers.semaphores.apply_semaphore`: Function to apply semaphores to coroutines. + - :class:`~TaskMapping`: A class for managing and asynchronously generating tasks based on input iterables. Alias for backward compatibility: - :class:`~ASyncBase` is an alias for :class:`~ASyncGenericBase`, which will be removed eventually, probably in version 0.1.0. @@ -38,6 +39,14 @@ >>> result = await obj.my_method() >>> print(result) + Using `TaskMapping` for asynchronous task management: + >>> from a_sync import TaskMapping + >>> async def fetch_data(url): + ... return f"Data from {url}" + >>> tasks = TaskMapping(fetch_data, ['http://example.com', 'https://www.python.org']) + >>> async for key, result in tasks: + ... print(f"Data for {key}: {result}") + See Also: - :mod:`a_sync.a_sync`: Contains the core classes and decorators. - :mod:`a_sync.asyncio`: Provides enhanced asyncio functions. @@ -120,4 +129,4 @@ # executor aliases "ThreadPoolExecutor", "ProcessPoolExecutor", -] +] \ No newline at end of file diff --git a/a_sync/a_sync/modifiers/semaphores.py b/a_sync/a_sync/modifiers/semaphores.py index 8a781c94..575b7529 100644 --- a/a_sync/a_sync/modifiers/semaphores.py +++ b/a_sync/a_sync/modifiers/semaphores.py @@ -43,7 +43,7 @@ def apply_semaphore( # type: ignore [misc] - :class:`primitives.Semaphore` Note: - `primitives.Semaphore` is a subclass of `asyncio.Semaphore`. Therefore, when the documentation refers to `asyncio.Semaphore`, it also includes `primitives.Semaphore` and any other subclasses. + `primitives.Semaphore` implements the same API as `asyncio.Semaphore`. Therefore, when the documentation refers to `asyncio.Semaphore`, it also includes `primitives.Semaphore` and any other implementations that conform to the same interface. """ @@ -81,7 +81,7 @@ def apply_semaphore( - :class:`primitives.Semaphore` Note: - `primitives.Semaphore` is a subclass of `asyncio.Semaphore`. Therefore, when the documentation refers to `asyncio.Semaphore`, it also includes `primitives.Semaphore` and any other subclasses. + `primitives.Semaphore` implements the same API as `asyncio.Semaphore`. Therefore, when the documentation refers to `asyncio.Semaphore`, it also includes `primitives.Semaphore` and any other implementations that conform to the same interface. """ @@ -128,7 +128,7 @@ def apply_semaphore( - :class:`primitives.Semaphore` Note: - `primitives.Semaphore` is a subclass of `asyncio.Semaphore`. Therefore, when the documentation refers to `asyncio.Semaphore`, it also includes `primitives.Semaphore` and any other subclasses. + `primitives.Semaphore` implements the same API as `asyncio.Semaphore`. Therefore, when the documentation refers to `asyncio.Semaphore`, it also includes `primitives.Semaphore` and any other implementations that conform to the same interface. """ # Parse Inputs if isinstance(coro_fn, (int, asyncio.Semaphore, primitives.Semaphore)): @@ -169,4 +169,4 @@ async def semaphore_wrap(*args, **kwargs) -> T: dummy_semaphore = primitives.DummySemaphore() -"""A dummy semaphore that does not enforce any concurrency limits.""" +"""A dummy semaphore that does not enforce any concurrency limits.""" \ No newline at end of file diff --git a/a_sync/primitives/locks/semaphore.pyx b/a_sync/primitives/locks/semaphore.pyx index 569b3d7b..ea6f43da 100644 --- a/a_sync/primitives/locks/semaphore.pyx +++ b/a_sync/primitives/locks/semaphore.pyx @@ -349,7 +349,8 @@ cdef class DummySemaphore(Semaphore): """An optional name for the counter, used in debug logs.""" if self._name == NULL: - raise MemoryError("Failed to allocate memory for __name.") + raise MemoryError("Failed to allocate memory for _name.") + # Copy the bytes data into the char* strcpy(self._name, encoded_name) diff --git a/a_sync/primitives/queue.py b/a_sync/primitives/queue.py index 86caa820..33398b98 100644 --- a/a_sync/primitives/queue.py +++ b/a_sync/primitives/queue.py @@ -438,17 +438,11 @@ def _ensure_workers(self) -> None: if worker.done(): # its only done if its broken exc = worker.exception() # re-raise with clean traceback - try: - raise type(exc)(*exc.args).with_traceback(exc.__traceback__) # type: ignore [union-attr] - except TypeError as e: - raise exc.with_traceback(exc.__traceback__) from e + raise exc.with_traceback(exc.__traceback__) from exc.__cause__ # this should never be reached, but just in case exc = self._workers.exception() - try: - # re-raise with clean traceback - raise type(exc)(*exc.args).with_traceback(exc.__traceback__) # type: ignore [union-attr] - except TypeError as e: - raise exc.with_traceback(exc.__traceback__) from e + # re-raise with clean traceback + raise exc.with_traceback(exc.__traceback__) from exc.__cause__ @functools.cached_property def _workers(self) -> "asyncio.Task[NoReturn]": diff --git a/a_sync/utils/iterators.py b/a_sync/utils/iterators.py index b50c9f56..44e4da58 100644 --- a/a_sync/utils/iterators.py +++ b/a_sync/utils/iterators.py @@ -258,9 +258,7 @@ def _as_yielded_done_callback(t: asyncio.Task) -> None: del task del queue if item._exc: - raise type(item._exc)(*item._exc.args).with_traceback( - item._tb - ) from item._exc.__cause__ + raise item._exc.with_traceback(item._tb) from item._exc.__cause__ return yield item From 44fb7af1da06a7c43c30f3da22b0811e696fe341 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 30 Nov 2024 08:12:06 +0000 Subject: [PATCH 2/2] chore: `black .` --- a_sync/__init__.py | 2 +- a_sync/a_sync/modifiers/semaphores.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/a_sync/__init__.py b/a_sync/__init__.py index 7b19975f..e5bea89a 100644 --- a/a_sync/__init__.py +++ b/a_sync/__init__.py @@ -129,4 +129,4 @@ # executor aliases "ThreadPoolExecutor", "ProcessPoolExecutor", -] \ No newline at end of file +] diff --git a/a_sync/a_sync/modifiers/semaphores.py b/a_sync/a_sync/modifiers/semaphores.py index 575b7529..fe554192 100644 --- a/a_sync/a_sync/modifiers/semaphores.py +++ b/a_sync/a_sync/modifiers/semaphores.py @@ -169,4 +169,4 @@ async def semaphore_wrap(*args, **kwargs) -> T: dummy_semaphore = primitives.DummySemaphore() -"""A dummy semaphore that does not enforce any concurrency limits.""" \ No newline at end of file +"""A dummy semaphore that does not enforce any concurrency limits."""