Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: some excs cant be re-raised how we like #459

Merged
merged 2 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions a_sync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions a_sync/a_sync/modifiers/semaphores.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
"""


Expand Down Expand Up @@ -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.
"""


Expand Down Expand Up @@ -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)):
Expand Down
3 changes: 2 additions & 1 deletion a_sync/primitives/locks/semaphore.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
12 changes: 3 additions & 9 deletions a_sync/primitives/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]":
Expand Down
4 changes: 1 addition & 3 deletions a_sync/utils/iterators.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down