FastAPI like dependency injection implementation
Project description
Taskiq dependencies
This project is used to add FastAPI-like dependency injection to projects.
This project is a part of the taskiq, but it doesn't have any dependencies, and you can easily integrate it in any project.
Installation
pip install taskiq-dependencies
Usage
Let's imagine you want to add DI in your project. What should you do? At first we need to create a dependency graph, check if there any cycles and compute the order of dependencies. This can be done with DependencyGraph. It does all of those actions on create. So we can remember all graphs at the start of our program for later use. Or we can do it when needed, but it's less optimal.
from taskiq_dependencies import Depends
def dep1() -> int:
return 1
def target_func(some_int: int = Depends(dep1)):
print(some_int)
return some_int + 1
In this example we have a function called target_func
and as you can see, it depends on dep1
dependency.
To create a dependnecy graph have to write this:
from taskiq_dependencies import DependencyGraph
graph = DependencyGraph(target_func)
That's it. Now we want to resolve all dependencies and call a function. It's simple as this:
with graph.sync_ctx() as ctx:
graph.target(**ctx.resolve_kwargs())
Voila! We resolved all dependencies and called a function with no arguments.
The resolve_kwargs
function will return a dict, where keys are parameter names, and values are resolved dependencies.
Async usage
If your lib is asynchronous, you should use async context, it's similar to sync context, but instead of with
you should use async with
. But this way your users can use async dependencies and async generators. It's not possible in sync context.
async with graph.async_ctx() as ctx:
kwargs = await ctx.resolve_kwargs()
Q&A
Why should I use
with
orasync with
statements?
Becuase users can use generator functions as dependencies.
Everything before yield
happens before injecting the dependency, and everything after yield
is executed after the with
statement is over.
How to provide default dependencies?
It maybe useful to have default dependencies for your project.
For example, taskiq has Context
and State
classes that can be used as dependencies. sync_context
and async_context
methods have a parameter, where you can pass a dict with precalculated dependencies.
from taskiq_dependencies import Depends, DependencyGraph
class DefaultDep:
...
def target_func(dd: DefaultDep = Depends()):
print(dd)
return 1
graph = DependencyGraph(target_func)
with graph.sync_ctx({DefaultDep: DefaultDep()}) as ctx:
print(ctx.resolve_kwargs())
You can run this code. It will resolve dd dependency into a DefaultDep
variable you provide.
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
Hashes for taskiq_dependencies-1.1.0.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0e5a6652cb30ceff84871c7e61251db84375c7ea0e94a43c31e7d23d8d58c05c |
|
MD5 | 268d249a6ca6813b7a79ebcf4dfe0421 |
|
BLAKE2b-256 | cbc066c735b7c55b4def829f51499540e26b31b15d88abf19c86c733e2856746 |
Hashes for taskiq_dependencies-1.1.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 467a016765f85484318106f600f352d3be0386deebec5ff08dbdc87663c517bd |
|
MD5 | 88a9b72c44ba89c1c1a9bdd452dfb857 |
|
BLAKE2b-256 | 930b78baff3c05b77ce1aef4115b814bdd9bda1c3569aae6e7613808c89d342a |