Skip to content

Commit

Permalink
Support non-async-functions too, closes #15
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Jan 20, 2023
1 parent ddb71fd commit c6b8245
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,16 @@ registry = Registry(example, simonwillison, both)
combined = await registry.resolve(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.
If you run this in `ipython` or `python -m asyncio` (to enable top-level await in the console) 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 notices that `both()` takes two arguments which are the names of other registered `async def` functions, and will construct an execution plan that executes those two functions in parallel, then passes their results to the `both()` method.

### Registering additional functions

Functions that are registered can be regular functions or `async def` functions.

In addition to registering functions by passing them to the constructor, you can also add them to a registry using the `.register()` method:

```python
Expand Down
17 changes: 14 additions & 3 deletions asyncinject/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,20 @@ def _plan(self, names, results=None):
return ts

def _get_awaitable(self, name, results):
aw = self._registry[name](
**{k: v for k, v in results.items() if k in self.graph[name]},
)
fn = self._registry[name]
kwargs = {k: v for k, v in results.items() if k in self.graph[name]}

awaitable_fn = fn

if not asyncio.iscoroutinefunction(fn):

async def _awaitable(*args, **kwargs):
return fn(*args, **kwargs)

_awaitable.__name__ = fn.__name__
awaitable_fn = _awaitable

aw = awaitable_fn(**kwargs)
if self.timer:
aw = self._make_time_logger(aw)
return aw
Expand Down
26 changes: 25 additions & 1 deletion tests/test_asyncinject.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ def three_not_async(one, two):
async def test_register():
registry = Registry()

async def one():
# Mix in a non-async function too:
def one():
return "one"

async def two_():
Expand All @@ -207,3 +208,26 @@ async def three(one, two):
result = await registry.resolve(three)

assert result == "onetwo"


@pytest.mark.asyncio
@pytest.mark.parametrize("parallel", (True, False))
async def test_just_sync_functions(parallel):
def one():
return 1

def two():
return 2

def three(one, two):
return one + two

timed = []

registry = Registry(
one, two, three, parallel=parallel, timer=lambda *args: timed.append(args)
)
result = await registry.resolve(three)
assert result == 3

assert {t[0] for t in timed} == {"two", "one", "three"}

0 comments on commit c6b8245

Please sign in to comment.