Skip to content

Quickstart

I suppose, if you are already here, you are exactly known about this library usage.

It is using the same way as FastAPI is.

But, I can remember you, if it's necessary.

Basic usage

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from fast_depends import inject, Depends

def simple_dependency(a: int, b: int = 3):
    return a + b

@inject
def method(a: int, d: int = Depends(simple_dependency)):
    return a + d

assert method("1") == 5
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import asyncio
from fast_depends import inject, Depends

async def simple_dependency(a: int, b: int = 3):
    return a + b

def another_dependency(a: int):
    return a

@inject
async def method(
    a: int,
    b: int = Depends(simple_dependency),
    c: int = Depends(another_dependency),
):
    return a + b + c

assert asyncio.run(method("1")) == 6

Be accurate

At async code we can use sync and async dependencies both, but at sync runtime only sync dependencies are available.

First step: we need to declare our dependency: it can be any Callable object.

Callable

"Callable" - object is able to be "called". It can be any function, class, or class method.

Another words: if we can write following the code my_object() - my_object is "Callable"

6
7
8
@inject
def method(a: int, d: int = Depends(simple_dependency)):
    return a + d
10
11
12
13
14
15
16
@inject
async def method(
    a: int,
    b: int = Depends(simple_dependency),
    c: int = Depends(another_dependency),
):
    return a + b + c

Second step: declare dependency required with Depends

 6
 7
 8
 9
10
@inject
def method(a: int, d: int = Depends(simple_dependency)):
    return a + d

assert method("1") == 5
10
11
12
13
14
15
16
17
18
@inject
async def method(
    a: int,
    b: int = Depends(simple_dependency),
    c: int = Depends(another_dependency),
):
    return a + b + c

assert asyncio.run(method("1")) == 6

Last step: just use the dependencies calling result!

That was easy, isn't it?

Auto @inject

At the code above you can note, that original Depends functions wasn't decorated by @inject.

It's true: all dependencies are decorated by default at using. Keep it at your mind.

Nested Dependencies

Dependencies are also able to contain their own dependencies. There is nothing unexpected with this case: just declare Depends requirement at original dependency function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from fast_depends import inject, Depends

def another_dependency(a: int):
    return a * 2

def simple_dependency(a: int, b: int = Depends(another_dependency)): # (1)
    return a + b

@inject
def method(
    a: int,
    b: int = Depends(another_dependency),
    c: int = Depends(simple_dependency)
):
    return a + b + c

assert method("1") == 6
  1. Call another_dependency here
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import asyncio
from fast_depends import inject, Depends

def another_dependency(a: int):
    return a * 2

async def simple_dependency(a: int, b: int = Depends(another_dependency)): # (1)
    return a + b

@inject
async def method(
    a: int,
    b: int = Depends(simple_dependency),
    c: int = Depends(another_dependency),
):
    return a + b + c

assert asyncio.run(method("1")) == 6
  1. Call another_dependency here

Cache

At the examples above another_dependency was called AT ONCE!. FastDepends caches all dependencies responses throw ONE @inject callstask. It means, that all nested dependencies give a one-time cached response. But, with different injected function calls, cache will differ too.

To disable that behavior, just use Depends(..., cache=False). This way dependency will be executed each time.

Dependencies type casting

If you remember, FastDepends casts function return too. This means, dependency output will be casted twice: at dependency function out and at the injector in. Nothing bad, if they are the same type, nothing overhead occurs. Just keep it in your mind. Or don't... My work is done anyway.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from fast_depends import inject, Depends

def simple_dependency(a: int, b: int = 3) -> str:
    return a + b  # cast 'return' to str first time

@inject
def method(a: int, d: int = Depends(simple_dependency)):
    # cast 'd' to int second time
    return a + d

assert method("1") == 5

Also, return type will be cached. If you are using this dependency at N functions, cached return will be casted N times.

To avoid this problem use mypy to check types at your project or just be accurate with your outer annotations.