Dependency injection for python.
Dependency injection made for python
- Easy to use interface
- Extensible with custom dependency resolvers
- Automatic dependency injection
- Support for async with asyncio
pip install kink
Adding service to dependency injection container
Dependency container is a dict-like object, adding new service to dependency container is as simple as the following example:
from kink import di from os import getenv di["db_name"] = getenv("DB_NAME") di["db_password"] = getenv("DB_PASSWORD")
Adding service factory to dependency injection container
Kink also supports on-demand service creation. In order to define such a service, lambda function should be used:
from kink import di from sqlite3 import connect di["db_connection"] = lambda di: connect(di["db_name"])
In this scenario connection to database will not be established until service is requested.
Adding factorised services to dependency injection
Factorised services are services that are instantiated every time they are requested.
from kink import di from sqlite3 import connect di.factories["db_connection"] = lambda di: connect(di["db_name"]) connection_1 = di["db_connection"] connection_2 = di["db_connection"] connection_1 != connection_2
In the above example we defined factorised service
di_connection, and below by accessing the service from di we created
two separate connection to database.
Requesting services fromm dependency injection container
from kink import di from sqlite3 import connect # Setting services di["db_name"] = "test_db.db" di["db_connection"] = lambda di: connect(di["db_name"]) # Getting service connection = di["db_connection"] # will return instance of sqlite3.Connection assert connection == di["db_connection"] # True
from kink import di, inject from sqlite3 import connect, Connection di["db_name"] = "test_db.db" di["db_connection"] = lambda di: connect(di["db_name"]) # Inject connection from di, connection is established once function is called. @inject def get_database(db_connection: Connection): ... connection = get_database() connection_with_passed_connection = get_database(connect("temp.db")) # will use passed connection
from kink import inject, di import MySQLdb # Set dependencies di["db_host"] = "localhost" di["db_name"] = "test" di["db_user"] = "user" di["db_password"] = "password" di["db_connection"] = lambda di: MySQLdb.connect(host=di["db_host"], user=di["db_user"], passwd=di["db_password"], db=di["db_name"]) @inject class AbstractRepository: def __init__(self, db_connection): self.connection = db_connection class UserRepository(AbstractRepository): ... repository = UserRepository() repository.connection # mysql db connection is resolved and available to use.
When class is annotated by
inject annotation it will be automatically added to the container for future use (eg autowiring).
When you registering service with
@inject decorator you can attach your own alias name, please consider the following example:
from kink import inject from typing import Protocol class IUserRepository(Protocol): ... @inject(alias=IUserRepository) class UserRepository: ... assert di[IUserRepository] == di[UserRepository] # returns true
For more examples check tests directory
Clearing di cache
from kink import inject, di ... # set and accesss your services di.clear_cache() # this will clear cache of all services inside di container that are not factorised services
Release history Release notifications | RSS feed
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
|Filename, size||File type||Python version||Upload date||Hashes|
|Filename, size kink-0.5.0-py3-none-any.whl (7.1 kB)||File type Wheel||Python version py3||Upload date||Hashes View|
|Filename, size kink-0.5.0.tar.gz (7.0 kB)||File type Source||Python version None||Upload date||Hashes View|