Skip to content

Commit

Permalink
feat(docs): way better docs + examples
Browse files Browse the repository at this point in the history
  • Loading branch information
BobTheBuidler committed Nov 14, 2024
1 parent 8c56f5a commit e82bb38
Show file tree
Hide file tree
Showing 41 changed files with 3,250 additions and 627 deletions.
55 changes: 49 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@
- [async modifiers](#async-modifiers)
- [sync modifiers](#sync-modifiers)
- [Default Modifiers](#default-modifiers)
- [Other Helpful Classes](#other-helpful-classes)
- [Other Helpful Classes](#other-helpful-modules)
- [ASyncIterable](#asynciterable)
- [ASyncIterator](#asynciterator)
- [ASyncFilter](#asyncfilter)
- [ASyncSorter](#asyncsorter)
- [Other Helpful Modules](#other-helpful-modules)
- [future](#future)
- [ASyncFuture](#asyncfuture)
- [future decorator](#future-decorator)
- [asyncio](#asyncio)

<!-- /TOC -->
## Introduction
Expand Down Expand Up @@ -203,7 +208,7 @@ Instead of setting modifiers one by one in functions, you can set a default valu

### 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.
The [ASyncIterable](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.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
Expand All @@ -219,9 +224,11 @@ for item in async_iterable:
...
```

See the [documentation](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.ASyncIterable) for more information.

#### 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.
The [ASyncIterator](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.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
Expand All @@ -237,9 +244,11 @@ for item in async_iterator:
...
```

See the [documentation](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.ASyncIterator) for more information.

#### ASyncFilter

The `ASyncFilter` class filters items of an async iterable based on a provided function. It can handle both synchronous and asynchronous filter functions.
The [ASyncFilter](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.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
Expand All @@ -263,9 +272,11 @@ for item in filtered_iterable:
...
```

See the [documentation](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.ASyncFilter) for more information.

#### ASyncSorter

The `ASyncSorter` class sorts items of an async iterable based on a provided key function. It supports both synchronous and asynchronous key functions.
The [ASyncSorter](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.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
Expand All @@ -283,4 +294,36 @@ async for item in sorted_iterable:

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

See the [documentation](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.ASyncSorter) for more information.

## Other Helpful Modules
The stuff here is unrelated to the main purpose of ez-a-sync, but cool and useful nonetheless

### asyncio

The `ez-a-sync` library extends the functionality of Python's `asyncio` module with additional utilities to simplify asynchronous programming.

- **as_completed**: This function allows you to iterate over awaitables as they complete, similar to `asyncio.as_completed`. It supports both synchronous and asynchronous iteration. [Learn more about `as_completed`](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.asyncio.as_completed).

- **gather**: A utility to run multiple asynchronous operations concurrently and wait for all of them to complete. It is similar to `asyncio.gather` but integrates seamlessly with the `ez-a-sync` library. [Learn more about `gather`](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.asyncio.gather).

- **create_task**: A function to create a new task from a coroutine, similar to `asyncio.create_task`, but with additional features provided by `ez-a-sync`. [Learn more about `create_task`](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.asyncio.create_task).

- **as_completed**: This function allows you to iterate over awaitables as they complete, similar to `asyncio.as_completed`. It supports both synchronous and asynchronous iteration. [Learn more about `as_completed`](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.asyncio.as_completed).

These utilities enhance the standard `asyncio` module, providing more flexibility and control over asynchronous operations. For detailed documentation and examples, please refer to the [documentation](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.asyncio)

### future
The future module is something totally different.
TODO: short explainer of module value prop and use case

#### ASyncFuture
[documentation](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.future.ASyncFuture)
TODO: short explainers on ASyncFuture class

#### future decorator
[documentation](#https://bobthebuidler.github.io/ez-a-sync/source/a_sync.html#a_sync.future.future)
TODO: short explainers on future fn
37 changes: 34 additions & 3 deletions a_sync/ENVIRONMENT_VARIABLES.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,41 @@

# We have some envs here to help you debug your custom class implementations

# If you're only interested in debugging a specific class, set this to the class name
DEBUG_CLASS_NAME = envs.create_env("DEBUG_CLASS_NAME", str, default="", verbose=False)
"""str: The name of the class to debug.
If you're only interested in debugging a specific class, set this to the class name.
Examples:
To debug a class named `MyClass`, set the environment variable:
.. code-block:: bash
export EZASYNC_DEBUG_CLASS_NAME=MyClass
See Also:
:func:`DEBUG_MODE` for enabling debug mode on all classes.
"""

# Set this to enable debug mode on all classes
DEBUG_MODE = envs.create_env(
"DEBUG_MODE", bool, default=DEBUG_CLASS_NAME, verbose=False
"DEBUG_MODE", bool, default=bool(DEBUG_CLASS_NAME), verbose=False
)
"""bool: Enables debug mode on all classes.
Set this environment variable to `True` to enable debug mode on all classes.
If `DEBUG_CLASS_NAME` is set to a truthy value other than an empty string,
`DEBUG_MODE` will default to `True`.
Examples:
To enable debug mode globally, set the environment variable:
.. code-block:: bash
export EZASYNC_DEBUG_MODE=True
If you have set `DEBUG_CLASS_NAME` to a specific class, `DEBUG_MODE` will
automatically be `True` unless `DEBUG_CLASS_NAME` is an empty string.
See Also:
:func:`DEBUG_CLASS_NAME` for debugging a specific class.
"""
42 changes: 32 additions & 10 deletions a_sync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,41 @@
such as queues and locks, with extra functionality.
Modules and components included:
- `aliases`, `exceptions`, `iter`, `task`: Core modules of the library.
- `ASyncGenericBase`, `ASyncGenericSingleton`, `a_sync`: Base classes and decorators for dual-context execution.
- `apply_semaphore`: Function to apply semaphores to coroutines.
- `ASyncCachedPropertyDescriptor`, `ASyncPropertyDescriptor`, `cached_property`, `property`: Property descriptors for async properties.
- `as_completed`, `create_task`, `gather`: Enhanced asyncio functions.
- Executors: `AsyncThreadPoolExecutor`, `AsyncProcessPoolExecutor`, `PruningThreadPoolExecutor` for async execution.
- Iterators: `ASyncFilter`, `ASyncSorter`, `ASyncIterable`, `ASyncIterator` for async iteration.
- Utilities: `all`, `any`, `as_yielded` for async utilities.
- :mod:`~aliases`, :mod:`~exceptions`, :mod:`~iter`, :mod:`~task`: Core modules of the library.
- :class:`~ASyncGenericBase`, :class:`~ASyncGenericSingleton`, :func:`~a_sync`: Base classes and decorators for dual-context execution.
- :class:`~ASyncCachedPropertyDescriptor`, :class:`~ASyncPropertyDescriptor`, `cached_property`, `property`: Property descriptors for async properties.
- :func:`~as_completed`, :func:`~create_task`, :func:`~gather`: Enhanced asyncio functions.
- Executors: :class:`~AsyncThreadPoolExecutor`, :class:`~AsyncProcessPoolExecutor`, :class:`~PruningThreadPoolExecutor` for async execution.
- Iterators: :class:`~ASyncFilter`, :class:`~ASyncSorter`, :class:`~ASyncIterable`, :class:`~ASyncIterator` for async iteration.
- Utilities: :func:`~all`, :func:`~any`, :func:`~as_yielded`, :func:`~exhaust_iterator`, :func:`~exhaust_iterators` for async utilities.
- :func:`~apply_semaphore`: Function to apply semaphores to coroutines.
Alias for backward compatibility:
- `ASyncBase` is an alias for `ASyncGenericBase`, which will be removed eventually, probably in version 0.1.0.
"""
- :class:`~ASyncBase` is an alias for :class:`~ASyncGenericBase`, which will be removed eventually, probably in version 0.1.0.
Examples:
Using the `@a_sync` decorator:
>>> from a_sync import a_sync
>>> @a_sync
... async def my_function():
... return "Hello, World!"
>>> result = await my_function()
>>> print(result)
Using `ASyncGenericBase` for dual-context classes:
>>> from a_sync import ASyncGenericBase
>>> class MyClass(ASyncGenericBase):
... async def my_method(self):
... return "Hello from MyClass"
>>> obj = MyClass()
>>> result = await obj.my_method()
>>> print(result)
See Also:
- :mod:`a_sync.a_sync`: Contains the core classes and decorators.
- :mod:`a_sync.asyncio`: Provides enhanced asyncio functions.
- :mod:`a_sync.primitives`: Includes modified versions of standard asyncio primitives.
"""
from a_sync import aliases, exceptions, iter, task
from a_sync.a_sync import ASyncGenericBase, ASyncGenericSingleton, a_sync
from a_sync.a_sync.modifiers.semaphores import apply_semaphore
Expand Down
41 changes: 30 additions & 11 deletions a_sync/_smart.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""
This module defines smart future and task utilities for the a_sync library.
These utilities provide enhanced functionality for managing asynchronous tasks and futures,
including task shielding and a custom task factory for creating SmartTask instances.
including a custom task factory for creating :class:`~SmartTask` instances and a shielding mechanism
to protect tasks from cancellation.
"""

import asyncio
Expand Down Expand Up @@ -45,10 +46,19 @@ def __await__(self: Union["SmartFuture", "SmartTask"]) -> Generator[Any, None, T
RuntimeError: If await wasn't used with future.
Example:
Awaiting a SmartFuture:
```python
future = SmartFuture()
result = await future
```
Awaiting a SmartTask:
```python
task = SmartTask(coro=my_coroutine())
result = await task
```
"""
if self.done():
return self.result() # May raise too.
Expand All @@ -67,9 +77,6 @@ def num_waiters(self: Union["SmartFuture", "SmartTask"]) -> int:
"""
Get the number of waiters currently awaiting the future or task.
Returns:
int: The number of waiters.
Example:
```python
future = SmartFuture()
Expand Down Expand Up @@ -108,10 +115,12 @@ class SmartFuture(_SmartFutureMixin[T], asyncio.Future):
"""
A smart future that tracks waiters and integrates with a smart processing queue.
Inherits from both _SmartFutureMixin and asyncio.Future, providing additional functionality
Inherits from both :class:`_SmartFutureMixin` and :class:`asyncio.Future`, providing additional functionality
for tracking waiters and integrating with a smart processing queue.
Example:
Creating and awaiting a SmartFuture:
```python
future = SmartFuture()
await future
Expand Down Expand Up @@ -160,9 +169,6 @@ def __lt__(self, other: "SmartFuture[T]") -> bool:
Args:
other: Another SmartFuture to compare with.
Returns:
True if self has more waiters than other.
Example:
```python
future1 = SmartFuture()
Expand All @@ -180,7 +186,7 @@ def create_future(
loop: Optional[asyncio.AbstractEventLoop] = None,
) -> SmartFuture[V]:
"""
Create a SmartFuture instance.
Create a :class:`~SmartFuture` instance.
Args:
queue: Optional; a smart processing queue.
Expand All @@ -191,6 +197,8 @@ def create_future(
A SmartFuture instance.
Example:
Creating a SmartFuture using the factory function:
```python
future = create_future(queue=my_queue, key=my_key)
```
Expand All @@ -202,10 +210,12 @@ class SmartTask(_SmartFutureMixin[T], asyncio.Task):
"""
A smart task that tracks waiters and integrates with a smart processing queue.
Inherits from both _SmartFutureMixin and asyncio.Task, providing additional functionality
Inherits from both :class:`_SmartFutureMixin` and :class:`asyncio.Task`, providing additional functionality
for tracking waiters and integrating with a smart processing queue.
Example:
Creating and awaiting a SmartTask:
```python
task = SmartTask(coro=my_coroutine())
await task
Expand Down Expand Up @@ -253,10 +263,15 @@ def smart_task_factory(
A SmartTask instance running the provided coroutine.
Example:
Using the smart task factory to create a SmartTask:
```python
loop = asyncio.get_event_loop()
task = smart_task_factory(loop, my_coroutine())
```
See Also:
- :func:`set_smart_task_factory`
"""
return SmartTask(coro, loop=loop)

Expand All @@ -269,6 +284,8 @@ def set_smart_task_factory(loop: asyncio.AbstractEventLoop = None) -> None:
loop: Optional; the event loop. If None, the current event loop is used.
Example:
Setting the smart task factory for the current event loop:
```python
set_smart_task_factory()
```
Expand Down Expand Up @@ -315,6 +332,8 @@ def shield(
loop: Optional; the event loop. Deprecated since Python 3.8.
Example:
Using shield to protect a coroutine from cancellation:
```python
result = await shield(my_coroutine())
```
Expand Down Expand Up @@ -371,4 +390,4 @@ def _outer_done_callback(outer):
"SmartTask",
"smart_task_factory",
"set_smart_task_factory",
]
]
Loading

0 comments on commit e82bb38

Please sign in to comment.