Skip to main content

A decorator-based dependency injection tool.

Project description

Kiwi-DI

A decorator-based dependency injection library.

Quick Start

Basic Usage

Decorate a class with @comoponent, then it will be registered and instantiated as a singleton, and you can use it everywhere.

# ------------------- flowers.py -----------------------
from kiwi_di import component


@component
class Rose:
    ...


@component
class Tulip:
    ...

If a class depends on some other classes, it can be instantiated as singleton if all of its constructor parameter are either:

  • of the type that is decorated with @component, like the Rose and Tulip.
  • has a default value, like the Sunflower
# ------------------- garden.py -----------------------

from kiwi_di import component
from flowers import Rose, Tulip

class Sunflower:
    pass

@component
class Garden:
    
    def __init__(self, rose: Rose, tulip: Tulip, sunflower: Sunflower = Sunflower()):
        self.rose = rose
        self.tulip = tulip
        self.sunflower = sunflower

You can use @inject to inject the instances of registered classes to the wherever they are needed.

# ------------------- main.py -----------------------
from kiwi_di import inject
from garden import Garden


@inject
def main(my_garden: Garden):
    print(my_garden.rose)
    print(my_garden.tulip)
    print(my_garden.sunflower)

    
if __name__ == '__main__':
    # No need to pass any arguments
    main()

# Output:
# <flowers.Rose object at 0x00000260B6D29310>
# <flowers.Tulip object at 0x00000260B6D29280>
# <garden.Sunflower object at 0x000001DBFBA30440>

Use @named_component to handle inheritance

You can use the decorator @named_component to create different instances of the same superclass.

In the example below, two instances of the class Animal will be created, each with a specific qualifier.

# ------------------- animal.py -----------------------
import abc
from typing import override
from kiwi_di import named_component

class Animal(abc.ABC):

    @abc.abstractmethod
    def greeting(self) -> str: ...


@named_component(qualifier="cat")
class Cat(Animal):

    @override
    def greeting(self) -> str:
        return "Hello, I'm a cat."


@named_component(qualifier="dog")
class Dog(Animal):

    @override
    def greeting(self) -> str:
        return "Hello, I'm a dog."

When injecting these instance, use Qualifier to specify which instance you want.

# ------------------- animal_family.py -----------------------
from typing import Annotated
from kiwi_di import component, Qualifier
from animal import Animal

@component
class AnimalFamily:

    def __init__(
        self,
        cat: Annotated[Animal, Qualifier("cat")],
        dog: Annotated[Animal, Qualifier("dog")],
    ):
        self.cat = cat
        self.dog = dog

Check the output.

# ------------------- main.py -----------------------
from animal import AnimalFamily
from kiwi_di import inject


@inject
def main(animal_family: AnimalFamily):
    print(animal_family.dog)
    print(animal_family.cat)


if __name__ == '__main__':
    main()

# Output:
# <animal.Dog object at 0x000001AD33900710>
# <animal.Cat object at 0x000001AD33900440>

About the decorated classes & functions

Classes

If a class is decorated with @component or @named_component:

  • You can still instantiate the class in the normal way:
animal_family = AnimalFamily(cat=Cat(), dog=Dog())

# <__main__.AnimalFamily object at 0x0000022D88BDC230>
  • It still has its original type:
print(AnimalFamily.__name__)
# Output: AnimalFamily

animal_family = AnimalFamily(cat=Cat(), dog=Dog())
print(isinstance(animal_family, AnimalFamily))
# Output: True

Functions

If a function is decorated with @inject, its signature will be changed:

  • It will become a function that takes no arguments.
  • Its return type will not be changed.

It's not recommended to decorate a function with @component or @named_component, the behaviour of which is undefined and not the purpose of these decorators.

Project details


Download files

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

Source Distribution

kiwi_di-0.1.1.tar.gz (7.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kiwi_di-0.1.1-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file kiwi_di-0.1.1.tar.gz.

File metadata

  • Download URL: kiwi_di-0.1.1.tar.gz
  • Upload date:
  • Size: 7.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for kiwi_di-0.1.1.tar.gz
Algorithm Hash digest
SHA256 61ccd1005037480c1022b9c119f9ee41a658fe54c9fa6973ae146ad2ee4dc8f7
MD5 90542e79b5916874115167941909d30d
BLAKE2b-256 d1c6f37bb113860bcec9403ca59b959ba98b7886385d3f6d97744fc2602fb1b3

See more details on using hashes here.

File details

Details for the file kiwi_di-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: kiwi_di-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 9.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for kiwi_di-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 09a716ad59f656f21d4cd8ee0527b65f4eb7d88efcc611b08c42d9c278eed3de
MD5 3a9ceb348dff353ef056988188245409
BLAKE2b-256 9610b4ab4cb19ef78ef273eff9d4db0aa49b32cbf691516a069d4880967e19b3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page