Skip to main content

Simple Dependency Injector for python

Project description

A simple async-friendly dependency injection framework for Python 3.

  • Async methods
  • Parametrized dependencies
  • Type annotations

Simple Example

import diana

class MyThing(object):
    def __init__(self, prefix):
        self.prefix = prefix

    def get(self, suffix):
        return self.prefix + suffix

class MyModule(diana.Module):
    def provide_thing(self) -> MyThing:
        return MyThing("a_prefix_")

def requires_a_thing(*, thing: MyThing):
    return thing.get('suffix')


requires_a_thing()  # returns "a_prefix_suffix"

Parametrized Dependencies

import diana
import typing

Snake = typing.NewType('Snake', str)

class SnakeModule(diana.Module):
    def provide_snake(self, length: int) -> Snake:
        return Snake('-' + ('=' * length) + e)

@diana.injector.param('a_snake', length=5)
def snake_printer(a_snake):
    print(a_snake, "Hissss")


snake_printer() # Prints: -=====e Hissss


Modules provide dependencies.


The same dependency can be provided by both an async and sync providers as shown in the AType providers below.

class MyModule(diana.Module):
    def load(self, injector):
        # Called when the module is loaded against `injector`.

    def unload(self, injector):
        # Called when the module is unloaded against `injector`.

    def provide_atype(self) -> AType:
        return AType()

    async def provide_atype_async(self) -> AType:
        await async_stuff()
        return AType()

    def provide_btype(self):
        return BType()

def provide_ctype(module) -> CType:
    return CType()

def provide_dtype(module):
    return DType()

Injection Styles

There are three formats for injecting dependencies into functions

  • Type Annotation w/ inspect
  • Explicit
  • Parametrized

The following examples are all equivalent.

# Type Annotation w/ Inspect
def func_a(*, a: AType, b: BType):

# Explicit
@diana.injector.inject(a=AType, b=BType)
def func_a(*, a, b):

# Parametrized.
# Note, if the second argument to param() is omitted, the type must be
# hinted by one of the previous methods.
@diana.injector.param('a', AType, a_param=...)
@diana.injector.param('b', BType, b_param=...)
def func_a(*, a, b):

In all cases, injected arguments must be keyword-only.

Alternatively, a dependency can be manually provided, bypassing any injection.

func_a(a=AType(), b=BType())

Missing Features

Compared to other dependency injection frameworks, a few features are missing.

  • Scope management - Currently there is no provision for scope to be managed by diana and remains the Module/provider’s responsibility.
  • Constructor/Instance Injecting - it is not possible to have Diana set attributes on instances by decorating the class definition.
  • Thread safety - There have been no attempts to make Diana thread safe. In theory, if modules are only loaded once (presumably at runtime), thread safety can be managed by the Modules/providers.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for diana, version 3.1.2
Filename, size File type Python version Upload date Hashes
Filename, size diana-3.1.2-py3-none-any.whl (7.5 kB) File type Wheel Python version py3 Upload date Hashes View

Supported by

Pingdom Pingdom Monitoring Google Google Object Storage and Download Analytics Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page