Skip to content

Commit

Permalink
feat(docs): add some examples
Browse files Browse the repository at this point in the history
  • Loading branch information
BobTheBuidler committed Nov 13, 2024
1 parent 910b702 commit 78a8a47
Show file tree
Hide file tree
Showing 14 changed files with 1,254 additions and 149 deletions.
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
- [async modifiers](#async-modifiers)
- [sync modifiers](#sync-modifiers)
- [Default Modifiers](#default-modifiers)
- [Other Helpful Classes](#other-helpful-classes)
- [ASyncIterable](#asynciterable)
- [ASyncIterator](#asynciterator)
- [ASyncFilter](#asyncfilter)
- [ASyncSorter](#asyncsorter)

<!-- /TOC -->
## Introduction
Expand Down Expand Up @@ -195,3 +200,87 @@ Instead of setting modifiers one by one in functions, you can set a default valu
- `RAM_CACHE_TTL`
- `RUNS_PER_MINUTE`
- `SEMAPHORE`

### Other Helpful Classes
#### ASyncIterable
The `ASyncIterable` class allows objects to be iterated over using either a standard `for` loop or an `async for` loop. This is particularly useful in scenarios where the mode of iteration needs to be flexible or is determined at runtime.

```python
from a_sync import ASyncIterable

async_iterable = ASyncIterable(some_async_iterable)

# Asynchronous iteration
async for item in async_iterable:
...

# Synchronous iteration
for item in async_iterable:
...
```

#### ASyncIterator

The `ASyncIterator` class provides a unified interface for iteration that can operate in both synchronous and asynchronous contexts. It allows the wrapping of asynchronous iterable objects or async generator functions.

```python
from a_sync import ASyncIterator

async_iterator = ASyncIterator(some_async_iterator)

# Asynchronous iteration
async for item in async_iterator:
...

# Synchronous iteration
for item in async_iterator:
...
```

#### ASyncFilter

The `ASyncFilter` class filters items of an async iterable based on a provided function. It can handle both synchronous and asynchronous filter functions.

```python
from a_sync import ASyncFilter

async def is_even(x):
return x % 2 == 0

filtered_iterable = ASyncFilter(is_even, some_async_iterable)

# or use the alias
import a_sync

filtered_iterable = a_sync.filter(is_even, some_async_iterable)

# Asynchronous iteration
async for item in filtered_iterable:
...

# Synchronous iteration
for item in filtered_iterable:
...
```

#### ASyncSorter

The `ASyncSorter` class sorts items of an async iterable based on a provided key function. It supports both synchronous and asynchronous key functions.

```python
from a_sync import ASyncSorter

sorted_iterable = ASyncSorter(some_async_iterable, key=lambda x: x.value)

# or use the alias
import a_sync

sorted_iterable = a_sync.sort(some_async_iterable, key=lambda x: x.value)

# Asynchronous iteration
async for item in sorted_iterable:
...

# Synchronous iteration
for item in sorted_iterable:
...
82 changes: 81 additions & 1 deletion a_sync/_smart.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ class _SmartFutureMixin(Generic[T]):
def __await__(self: Union["SmartFuture", "SmartTask"]) -> Generator[Any, None, T]:
"""
Await the smart future or task, handling waiters and logging.
Yields:
The result of the future or task.
Raises:
RuntimeError: If await wasn't used with future.
Example:
```python
future = SmartFuture()
result = await future
```
"""
if self.done():
return self.result() # May raise too.
Expand All @@ -54,6 +66,15 @@ def num_waiters(self: Union["SmartFuture", "SmartTask"]) -> int:
# NOTE: we check .done() because the callback may not have ran yet and its very lightweight
"""
Get the number of waiters currently awaiting the future or task.
Returns:
int: The number of waiters.
Example:
```python
future = SmartFuture()
print(future.num_waiters)
```
"""
if self.done():
# if there are any waiters left, there won't be once the event loop runs once
Expand All @@ -67,6 +88,9 @@ def _waiter_done_cleanup_callback(
Callback to clean up waiters when a waiter task is done.
Removes the waiter from _waiters, and _queue._futs if applicable
Args:
waiter: The waiter task to clean up.
"""
if not self.done():
self._waiters.remove(waiter)
Expand All @@ -86,6 +110,12 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
Inherits from both _SmartFutureMixin and asyncio.Future, providing additional functionality
for tracking waiters and integrating with a smart processing queue.
Example:
```python
future = SmartFuture()
await future
```
"""

_queue = None
Expand All @@ -105,6 +135,11 @@ def __init__(
queue: Optional; a smart processing queue.
key: Optional; a key identifying the future.
loop: Optional; the event loop.
Example:
```python
future = SmartFuture(queue=my_queue, key=my_key)
```
"""
super().__init__(loop=loop)
if queue:
Expand All @@ -127,6 +162,13 @@ def __lt__(self, other: "SmartFuture[T]") -> bool:
Returns:
True if self has more waiters than other.
Example:
```python
future1 = SmartFuture()
future2 = SmartFuture()
print(future1 < future2)
```
"""
return self.num_waiters > other.num_waiters

Expand All @@ -147,6 +189,11 @@ def create_future(
Returns:
A SmartFuture instance.
Example:
```python
future = create_future(queue=my_queue, key=my_key)
```
"""
return SmartFuture(queue=queue, key=key, loop=loop or asyncio.get_event_loop())

Expand All @@ -157,6 +204,12 @@ class SmartTask(_SmartFutureMixin[T], asyncio.Task):
Inherits from both _SmartFutureMixin and asyncio.Task, providing additional functionality
for tracking waiters and integrating with a smart processing queue.
Example:
```python
task = SmartTask(coro=my_coroutine())
await task
```
"""

def __init__(
Expand All @@ -173,6 +226,11 @@ def __init__(
coro: The coroutine to run in the task.
loop: Optional; the event loop.
name: Optional; the name of the task.
Example:
```python
task = SmartTask(coro=my_coroutine(), name="my_task")
```
"""
super().__init__(coro, loop=loop, name=name)
self._waiters: Set["asyncio.Task[T]"] = set()
Expand All @@ -193,6 +251,12 @@ def smart_task_factory(
Returns:
A SmartTask instance running the provided coroutine.
Example:
```python
loop = asyncio.get_event_loop()
task = smart_task_factory(loop, my_coroutine())
```
"""
return SmartTask(coro, loop=loop)

Expand All @@ -203,6 +267,14 @@ def set_smart_task_factory(loop: asyncio.AbstractEventLoop = None) -> None:
Args:
loop: Optional; the event loop. If None, the current event loop is used.
Example:
```python
set_smart_task_factory()
```
See Also:
- :func:`smart_task_factory`
"""
if loop is None:
loop = a_sync.asyncio.get_event_loop()
Expand Down Expand Up @@ -241,6 +313,14 @@ def shield(
Args:
arg: The awaitable to shield from cancellation.
loop: Optional; the event loop. Deprecated since Python 3.8.
Example:
```python
result = await shield(my_coroutine())
```
See Also:
- :func:`asyncio.shield`
"""
if loop is not None:
warnings.warn(
Expand Down Expand Up @@ -291,4 +371,4 @@ def _outer_done_callback(outer):
"SmartTask",
"smart_task_factory",
"set_smart_task_factory",
]
]
Loading

0 comments on commit 78a8a47

Please sign in to comment.