Basic usage¶
Sync¶
To use FunDI in synchronous mode you need to use inject function and ExitStack class
from fundi import Scope, from_, inject, scan
def require_user() -> str:
return "user"
def application(user: str = from_(require_user)):
print(f"Application started with {user = }")
inject(Scope(), scan(application))
Async¶
To use FunDI with asynchronous code - you need to use ainject function and AsyncExitStack class
import asyncio
from fundi import Scope, from_, ainject, scan
async def require_user() -> str:
return "user"
async def application(user: str = from_(require_user)):
print(f"Application started with {user = }")
async def main():
await ainject(Scope(), scan(application))
if __name__ == "__main__":
asyncio.run(main())
Mixed¶
You can mix async and sync dependencies using ainject function
import asyncio
from fundi import Scope, from_, ainject, scan
def require_user() -> str:
return "user"
async def application(user: str = from_(require_user)):
print(f"Application started with {user = }")
async def main():
await ainject(Scope(), scan(application))
if __name__ == "__main__":
asyncio.run(main())
Positional dependencies¶
You may want to define dependencies inside a positional parameter. To do so, you need to use typing.Annotated in pair of from_()
from typing import Annotated
from fundi import Scope, from_, inject, scan
def require_int() -> int:
return 255
def application(value: Annotated[int, from_(require_int)], scope_value: str):
print(f"Application started with {value = } and {scope_value = !r}")
inject(Scope({"scope_value": "17/03/2026"}), scan(application))