Simple dependency injection tool
Project description
yggsdrasyl
Simplistic, but totally explicit dependency injection tool. Main goal is to provide simple, but powerful API for registering dependencies by type and their extensible resolution mechanism in functions.
Why
yggdrasyl? This is misspelling ofyggdrasil- the ancient tree of life in Nordic / Scandinavian mythologies, that connects all the worlds, like DI Framework connects dependencies.
Usage
Main entry point to dependency management is class Dependencies. You can create your
own instance, or use predefined global one - deps.
Dependency Registration
To register a dependency invoke method Dependencies.register:
from yggdrasyl import deps
deps.register(UserServiceConfig, lambda d: UserServiceConfig())
deps.register(UserService, lambda d: UserService(config=d.resolve(UserServiceConfig)))
Dependencies.register accepts accepts 2 required arguments:
- dependency type - identifier for dependency resolution
- factory function - function that accepts
Dependenciesobject and returns dependency instance
Also there are multiple optional keyword-only arguments:
cached- ifTruethan dependency object is reused across all resolutions,Trueby defaultmanaged- ifTruethan dependency object is managed by context manager and can be initialized with all the other dependenciesoverride- ifTruethan existing dependency with same type is overridden,Falseby default
For simplification of registering objects from instances one can use from_instance
utility function. If one has factory function (for example class constructor) use
from_factory.
from yggdrasyl import deps, from_instance, from_factory
deps.register(int, from_instance(1))
deps.register(IService, from_factory(Service))
If dependency type is already registered, then TypeAlreadyRegisteredError is raised.
Dependency Resolution
To resolve dependency invoke Dependencies.resolve method with single desired type
argument:
from yggdrasyl import deps
user_service = deps.resolve(UserService)
If type is not registered, then TypeNotRegisteredError is raised.
Context Manager Dependencies
Some dependencies require being initialized on application startup. In order not to
forget one and rule management from single place there is a managed parameter, that
indicates that this dependency should be resolved on startup and is sync or async
context manager, that should be initialized. By default it takes False meaning, that
one must explicitly tell, that dependency is managed.
After marking only dependencies as managed just open Dependencies.initialize context
and all the dependencies will be initialized at once. Basically this method should be
used as lifespan for ASGI applications (for example).
from contextlib import asynccontextmanager
from fastapi import FastAPI
from yggdrasyl import deps
@asynccontextmanager
async def _lifespan(app: FastAPI):
async with deps.initialize():
yield
Dependency Wiring
In order not to call Dependencies.resolve manually for each dependency, there is a way to tell that some callable requires some dependencies via Dependencies.wire decorator:
from yggdrasyl import deps, Injected
@deps.wire
async def _handle_register_user(
action: RegisterUser,
user_service: UserService = Injected[UserService]
) -> UserID:
...
To mark argument to be injected from DI container one should use Injected object with
wanted type in [].
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yggdrasyl-0.1.0.tar.gz.
File metadata
- Download URL: yggdrasyl-0.1.0.tar.gz
- Upload date:
- Size: 24.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9139948d81523700a5a9bf244eeb512539d968b312a889b81d2d9436ad16ab0a
|
|
| MD5 |
32f094ee120144db5ddf6b760a2a8038
|
|
| BLAKE2b-256 |
0928f51ed86191a5643f7912d7f0196101b2ea433323b641b8a66b9e81e651fb
|
File details
Details for the file yggdrasyl-0.1.0-py3-none-any.whl.
File metadata
- Download URL: yggdrasyl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 5.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a10e0642e9c30b52fff35e214a84ae57fb5b6be7c8b19c3f42a93912490abd9b
|
|
| MD5 |
dc31b873bf3aa016c9be1dd3a059f389
|
|
| BLAKE2b-256 |
435cacc2e216eb33aa97914e970724ef89fee6ab1a6a62c72175884b0be89bdd
|