Run async workflows using pytest-fixtures-style dependency injection
Project description
asyncinject
Run async workflows using pytest-fixtures-style dependency injection
Installation
Install this library using pip
:
$ pip install asyncinject
Usage
This library is inspired by pytest fixtures.
The idea is to simplify executing parallel asyncio
operations by allowing them to be collected in a class, with the names of parameters to the class methods specifying which other methods should be executed first.
This then allows the library to create and execute a plan for executing various dependent methods in parallel.
Here's an example, using the httpx HTTP library.
from asyncinject import AsyncInjectAll
import httpx
async def get(url):
async with httpx.AsyncClient() as client:
return (await client.get(url)).text
class FetchThings(AsyncInjectAll):
async def example(self):
return await get("http://www.example.com/")
async def simonwillison(self):
return await get("https://simonwillison.net/search/?tag=empty")
async def both(self, example, simonwillison):
return example + "\n\n" + simonwillison
combined = await FetchThings().both()
print(combined)
If you run this in ipython
(which supports top-level await) you will see output that combines HTML from both of those pages.
The HTTP requests to www.example.com
and simonwillison.net
will be performed in parallel.
The library will notice that both()
takes two arguments which are the names of other async def
methods on that class, and will construct an execution plan that executes those two methods in parallel, then passes their results to the both()
method.
AsyncInject and @inject
The above example illustrates the AsyncInjectAll
class, which assumes that every async def
method on the class should be treated as a dependency injection method.
You can also specify individual methods using the AsyncInject
base class an the @inject
decorator:
from asyncinject import AsyncInject, inject
class FetchThings(AsyncInject):
@inject
async def example(self):
return await get("http://www.example.com/")
@inject
async def simonwillison(self):
return await get("https://simonwillison.net/search/?tag=empty")
@inject
async def both(self, example, simonwillison):
return example + "\n\n" + simonwillison
The resolve() function
If you want to execute a set of methods in parallel without defining a third method that lists them as parameters, you can do so using the resolve()
function. This will execute the specified methods (in parallel, where possible) and return a dictionary of the results.
from asyncinject import resolve
fetcher = FetchThings()
results = await resolve(fetcher, ["example", "simonwillison"])
results
will now be:
{
"example": "contents of http://www.example.com/",
"simonwillison": "contents of https://simonwillison.net/search/?tag=empty"
}
Development
To contribute to this library, first checkout the code. Then create a new virtual environment:
cd asyncinject
python -m venv venv
source venv/bin/activate
Or if you are using pipenv
:
pipenv shell
Now install the dependencies and test dependencies:
pip install -e '.[test]'
To run the tests:
pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file asyncinject-0.1a0.tar.gz
.
File metadata
- Download URL: asyncinject-0.1a0.tar.gz
- Upload date:
- Size: 10.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.6.0 importlib_metadata/4.8.2 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.8
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2d971e811541b06d57270066cba3c896f1aedd884cf86884ed81ba0c6807d6c2 |
|
MD5 | 008bcc1835ac25099249b7d2b54cb8df |
|
BLAKE2b-256 | eaacad1cf51693574bd6f85e3d8b2002d32e1c9bc9fb1c7646e70a122a56c4e4 |
File details
Details for the file asyncinject-0.1a0-py3-none-any.whl
.
File metadata
- Download URL: asyncinject-0.1a0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.6.0 importlib_metadata/4.8.2 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.8
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 71105250ab3b26053ec650344e66285024753e2ecd51b1e8af38fbce58b4f5f2 |
|
MD5 | 5dc8664e5b4a72a4d720baff0f2e9c14 |
|
BLAKE2b-256 | ba0eb79df7a45adbd0c4dfc7c6363bc2610eba03707c7675fbae20c863574f67 |