jacked

Dependency injection for Python


Keywords
dependency-injection, python, python3, python35, python36, python37
License
MIT
Install
pip install jacked==1.0.0a3

Documentation

Build Status Pypi version Scrutinizer Code Quality codecov

NOTE: This project is in ALPHA state

jacked ~ python on roids

  • A light and easy to use dependency injection framework.
  • Inject objects, functions, classes or lists containing any of these.
  • Let jacked automatically discover your injectables in a package.
  • Loose coupling on the juice!
  • Excellent for making your code testable!

Install

pip install jacked

Usage

Inject instances

To inject instances, mark a class with the injectable decorator:

from jacked import injectable

@injectable
class Cat:
    def sound(self):
        return 'meow'

You can now inject it in a function anywhere. Place the inject decorator on top of the function or method. Let jacked know what type to inject by type hinting your parameters:

@inject
def what_sound_does_it_make(cat: Cat):
    print(cat.sound())
    
what_sound_does_it_make()

Inject functions

Injecting functions works similarly. Just make sure that your function has the proper type hints:

@injectable
def some_func(x: int, y: int) -> str:
    return f'The sum of {x} and {y} is {x + y}'

And like with instances, inject as follows:

@inject
def do_something(func: Callable[[int, int], str]):
    print(func(21, 21))
    
do_something()

Inject classes

Assuming that we have the same Cat injectable like before, we can inject that class as follows:

from typing import Type

@inject
def do_something(cat_type: Type[Cat]):
    print(cat_type.__name__)
    
do_something()

Inject lists

Let's suppose that we have the following two injectables of the same parent:

class Animal(ABC):
    @abstractmethod
    def sound(self):
        raise NotImplementedError
        
@injectable
class Cat(Animal):
    def sound(self):
        return 'meow'
        
@injectable
class Dog(Animal):
    def sound(self):
        return 'bark'

You can now inject them in a list:

@inject
def what_sound_does_it_make(animals: List[Animal]):
    for animal in animals:
        print(f'The {animal.__class__.__name__} does {animal.sound()}')
        
what_sound_does_it_make()

You could have also injected a list of classes or functions by hinting List[Type[...]] or List[Callable[...]] (the ... replaced by your injection target).

Singletons

You can annotate an injectable as singleton, meaning that if the injectable is a class, only one instance is ever injected:

@injectable(singleton=True)
class Dog(Animal):
    def sound(self):
        return 'bark'

Auto discovery

You can let jacked discover injectables in some package using the discover function:

from jacked import discover

discover('path/to/your/package')

All python modules in that package are imported and the injectables are registered.