
Product
Go Support Is Now Generally Available
Socket's Go support is now generally available, bringing automatic scanning and deep code analysis to all users with Go projects.
Cute DI framework with scopes and agreeable API.
This library provides IoC container that's genuinely useful. If you're exhausted from endlessly passing objects just to create other objects, only to have those objects create even more — you're not alone, and we have a solution. Not every project requires IoC container, but take a look at what we offer.
Unlike other tools, Dishka focuses only on dependency injection without trying to solve unrelated tasks. It keeps DI in place without cluttering your code with global variables and scattered specifiers.
To see how Dishka stands out among other dependency injection tools, check out the detailed comparison.
See more in technical requirements.
pip install dishka
Service
(business logic) and
DAO
(data access), along with an external API client:class DAO(Protocol):
...
class Service:
def __init__(self, dao: DAO):
...
class DAOImpl(DAO):
def __init__(self, connection: Connection):
...
class SomeClient:
...
Provider
instance and specify how to provide dependencies.Providers are used only to set up factories providing your objects.
Use scope=Scope.APP
for dependencies created once for the entire application lifetime,
and scope=Scope.REQUEST
for those that need to be recreated for each request, event, etc.
To learn more about scopes, see documentation.
from dishka import Provider, Scope
service_provider = Provider(scope=Scope.REQUEST)
service_provider.provide(Service)
service_provider.provide(DAOImpl, provides=DAO)
service_provider.provide(SomeClient, scope=Scope.APP) # override provider scope
To provide a connection, you might need some custom code:
from dishka import Provider, provide, Scope
class ConnectionProvider(Provider):
@provide(scope=Scope.REQUEST)
def new_connection(self) -> Iterable[Connection]:
conn = sqlite3.connect(":memory:")
yield conn
conn.close()
Container
instance, passing providers, and enter APP
scope.from dishka import make_container
container = make_container(service_provider, ConnectionProvider())
.get
method to access APP
-scoped dependencies:client = container.get(SomeClient) # `SomeClient` has Scope.APP, so it is accessible here
client = container.get(SomeClient) # same instance of `SomeClient`
REQUEST
scope repeatedly using a context manager:# subcontainer to access shorter-living objects
with container() as request_container:
service = request_container.get(Service)
service = request_container.get(Service) # same service instance
# since we exited the context manager, the connection is now closed
# new subcontainer to have a new lifespan for request processing
with container() as request_container:
service = request_container.get(Service) # new service instance
container.close()
from dishka.integrations.fastapi import (
FromDishka, inject, setup_dishka,
)
@router.get("/")
@inject
async def index(service: FromDishka[Service]) -> str:
...
...
setup_dishka(container, app)
Dependency is what you need for some parts of your code to work. Dependencies are simply objects you don't create directly in place and might want to replace someday, at least for testing purposes. Some of them live for the entire application lifetime, while others are created and destroyed with each request. Dependencies can also rely on other objects, which then become their dependencies.
Scope is the lifespan of a dependency. Standard scopes are (with some skipped):
APP
-> REQUEST
-> ACTION
-> STEP
.
You decide when to enter and exit each scope, but this is done one by one. You set a scope for each dependency when you configure how it is created. If the same dependency is requested multiple times within a single scope without leaving it, then by default the same instance is returned.
For a web application, enter APP
scope on startup and REQUEST
scope for each HTTP request.
You can create a custom scope by defining your own Scope
class if the standard scope flow doesn't fit your needs.
Container is what you use to get your dependencies.
You simply call .get(SomeType)
and it finds a way to provide you with an instance of that type.
Container itself doesn't create objects but manages their lifecycle and caches.
It delegates object creation to providers that are passed during creation.
Provider is a collection of functions that provide concrete objects.
Provider
is a class with attributes and methods, each being the result of provide
, alias
, from_context
, or
decorate
.
They can be used as provider methods, functions to assign attributes, or method decorators.
@provide
can be used as a decorator for a method.
This method will be called when the corresponding dependency has to be created.
Name doesn't matter: just make sure it's different from other Provider
attributes.
Type hints do matter: they indicate what this method creates and what it requires.
All method parameters are treated as dependencies and are created using the container.
If provide
is applied to a class, that class itself is treated as a factory (its __init__
parameters are analyzed).
Remember to assign this call to an attribute; otherwise, it will be ignored.
Component is an isolated group of providers within the same container, identified by a unique string. When a dependency is requested, it is only searched within the same component as its direct dependant, unless explicitly specified otherwise.
This structure allows you to build different parts of the application separately without worrying about using the same types.
FAQs
Cute DI framework with scopes and agreeable API
We found that dishka demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket's Go support is now generally available, bringing automatic scanning and deep code analysis to all users with Go projects.
Security News
vlt adds real-time security selectors powered by Socket, enabling developers to query and analyze package risks directly in their dependency graph.
Security News
CISA extended MITRE’s CVE contract by 11 months, avoiding a shutdown but leaving long-term governance and coordination issues unresolved.