A Container for the Dependency Injection in Python.

Overview

Python Dependency Injection library

aiodi is a Container for the Dependency Injection in Python.

Installation

Use the package manager pip to install aiodi.

pip install aiodi

Documentation

Usage

from abc import ABC, abstractmethod
from logging import Logger, getLogger, NOTSET, StreamHandler, Formatter
from os import getenv

from aiodi import Container
from typing import Optional, Union

_CONTAINER: Optional[Container] = None


def get_simple_logger(
        name: Optional[str] = None,
        level: Union[str, int] = NOTSET,
        fmt: str = '[%(asctime)s] - %(name)s - %(levelname)s - %(message)s',
) -> Logger:
    logger = getLogger(name)
    logger.setLevel(level)
    handler = StreamHandler()
    handler.setLevel(level)
    formatter = Formatter(fmt)
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    return logger


class GreetTo(ABC):
    @abstractmethod
    def __call__(self, who: str) -> None:
        pass


class GreetToWithPrint(GreetTo):
    def __call__(self, who: str) -> None:
        print('Hello ' + who)


class GreetToWithLogger(GreetTo):
    _logger: Logger

    def __init__(self, logger: Logger) -> None:
        self._logger = logger

    def __call__(self, who: str) -> None:
        self._logger.info('Hello ' + who)


def container() -> Container:
    global _CONTAINER
    if _CONTAINER:
        return _CONTAINER
    di = Container({'env': {
        'name': getenv('APP_NAME', 'aiodi'),
        'log_level': getenv('APP_LEVEL', 'INFO'),
    }})
    di.resolve([
        (
            Logger,
            get_simple_logger,
            {
                'name': di.resolve_parameter(lambda di_: di_.get('env.name', typ=str)),
                'level': di.resolve_parameter(lambda di_: di_.get('env.log_level', typ=str)),
            },
        ),
        (GreetTo, GreetToWithLogger),  # -> (GreetTo, GreetToWithLogger, {})
        GreetToWithPrint,  # -> (GreetToWithPrint, GreetToWithPrint, {})
    ])
    di.set('who', 'World!')
    # ...
    _CONTAINER = di
    return di


def main() -> None:
    di = container()

    di.get(Logger).info('Just simple call get with the type')

    for greet_to in di.get(GreetTo, instance_of=True):
        greet_to(di.get('who'))


if __name__ == '__main__':
    main()

Requirements

  • Python >= 3.6

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

MIT

Comments
  • Add status badges to README.md

    Add status badges to README.md

    As other Open source projects have, add the badges of the status of the CI passing the tests in GitHub Actions, of the latest version available in PyPi and the number of total downloads to the README.md.

    documentation good first issue 
    opened by ticdenis 0
  • Supports multiple casting for variables using ContainerBuilder

    Supports multiple casting for variables using ContainerBuilder

    Currently we have 3 options to cast variables using the ContainerBuilder:

    # pyproject.toml
    
    [tool.aiodi.variables]
    # Get static text.
    debug = "Text"
    # Get as str a variable.
    debug2 = "%var(debug)%"
    # Cast to int an environment variable.
    debug3 = "%env(int:APP_DEBUG, '1')%"
    

    But we can not do:

    # pyproject.toml
    
    [tool.aiodi.variables]
    # ...
    debug4 = "%env(bool:int:APP_DEBUG, '1')%"
    

    We've detected that this is a common operation so would be great have it integrate it on ContainerBuilder.

    enhancement 
    opened by ticdenis 0
  • Support for resolving Generic types as argument

    Support for resolving Generic types as argument

    Currently is not supported if we have something like:

    from typing import TypeVar
    
    
    Driver = TypeVar('Driver')
    
    class Connection(Generic[Driver]):
      ...
      
    class FakeConnection(Connection[int]):
      ...
      
    class App:
      def __init__(self, connection: Connection[int]) -> None:
        self._connection = connection
    

    When we try to resolve Connection as an argument will fail, example:

    # ...
    
    di.resolve([
      (Connection, FakeConnection()),
      (App), # will fail
    ])
    
    bug help wanted 
    opened by ticdenis 0
  • Improve CommandBuilder dependency resolution system

    Improve CommandBuilder dependency resolution system

    It is currently quite convoluted, abusing loops with a limit of the cube depending on the number of elements to be solved and messing up the unsolved elements so that they can be incorporated into the head of the next iteration and avoid infinite loops. But there can be.

    The dependency resolution system should be improved, as an idea based on a tree system.

    bug enhancement help wanted 
    opened by ticdenis 0
  • Support for resolving typed lists with ContainerBuilder

    Support for resolving typed lists with ContainerBuilder

    This is currently not possible and it would be great if examples like the following could work.

    class UserPermission:
      pass
    
    def default_user_permissions() -> list[UserPermission]:
      return [UserPermission()]
    
    class UserHandler:
      __slots__  = '_permissions'
      
      def __init__(self, permissions: list[UserPermission]) -> None:
        self._permissions = permissions 
    
    [tool.aiodi.services."default_user_permissions"]
    class = "sample.default_user_permissions"
    
    [tool.aiodi.services."UserHandler"]
    class = "sample.UserHandler" # <- this will fails because library does not inspect list type.
    
    enhancement help wanted 
    opened by ticdenis 0
Releases(1.1.4)
  • 1.1.4(Jun 9, 2022)

  • 1.1.2(Feb 20, 2022)

    What's Changed

    • refactor(*): Improve ContainerBuilder architecture by @ticdenis in https://github.com/ticdenis/python-aiodi/pull/6
    • Support multiple casting for variables and allows "None" as None for default values by @ticdenis in https://github.com/ticdenis/python-aiodi/pull/7

    Full Changelog: https://github.com/ticdenis/python-aiodi/compare/1.1.1...1.1.2

    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Feb 10, 2022)

  • 1.1.0(Jan 19, 2022)

    What's Changed

    • release(1.0.0): Initial release by @ticdenis in https://github.com/ticdenis/python-aiodi/pull/2
    • docs: Add symbolic link for index.md to en/index.md by @ticdenis in https://github.com/ticdenis/python-aiodi/pull/3
    • feat(*): Add support for pyproject.toml by @ticdenis in https://github.com/ticdenis/python-aiodi/pull/4

    Full Changelog: https://github.com/ticdenis/python-aiodi/commits/1.1.0

    Source code(tar.gz)
    Source code(zip)
Owner
Denis NA
Denis NA
Dependency injection lib for Python 3.8+

PyDI Dependency injection lib for python How to use To define the classes that should be injected and stored as bean use decorator @component @compone

Nikita Antropov 2 Nov 9, 2021
Python lightweight dependency injection library

pythondi pythondi is a lightweight dependency injection library for python Support both sync and async functions Installation pip3 install pythondi Us

Hide 41 Dec 16, 2022
Run async workflows using pytest-fixtures-style dependency injection

Run async workflows using pytest-fixtures-style dependency injection

Simon Willison 26 Jun 26, 2022
✨ Voici un code en Python par moi, et en français qui permet d'exécuter du Javascript en Python.

JavaScript In Python ❗ Voici un code en Python par moi, et en français qui permet d'exécuter du Javascript en Python. ?? Une vidéo pour vous expliquer

MrGabin 4 Mar 28, 2022
Simple python module to get the information regarding battery in python.

Battery Stats A python3 module created for easily reading the current parameters of Battery in realtime. It reads battery stats from /sys/class/power_

Shreyas Ashtamkar 5 Oct 21, 2022
ticktock is a minimalist library to view Python time performance of Python code.

ticktock is a minimalist library to view Python time performance of Python code.

Victor Benichoux 30 Sep 28, 2022
Python @deprecat decorator to deprecate old python classes, functions or methods.

deprecat Decorator Python @deprecat decorator to deprecate old python classes, functions or methods. Installation pip install deprecat Usage To use th

null 12 Dec 12, 2022
A python package containing all the basic functions and classes for python. From simple addition to advanced file encryption.

A python package containing all the basic functions and classes for python. From simple addition to advanced file encryption.

PyBash 11 May 22, 2022
Find dependent python scripts of a python script in a project directory.

Find dependent python scripts of a python script in a project directory.

null 2 Dec 5, 2021
A functional standard library for Python.

Toolz A set of utility functions for iterators, functions, and dictionaries. See the PyToolz documentation at https://toolz.readthedocs.io LICENSE New

null 4.1k Dec 30, 2022
Python Classes Without Boilerplate

attrs is the Python package that will bring back the joy of writing classes by relieving you from the drudgery of implementing object protocols (aka d

The attrs Cabal 4.6k Jan 6, 2023
🔩 Like builtins, but boltons. 250+ constructs, recipes, and snippets which extend (and rely on nothing but) the Python standard library. Nothing like Michael Bolton.

Boltons boltons should be builtins. Boltons is a set of over 230 BSD-licensed, pure-Python utilities in the same spirit as — and yet conspicuously mis

Mahmoud Hashemi 6k Jan 4, 2023
Retrying library for Python

Tenacity Tenacity is an Apache 2.0 licensed general-purpose retrying library, written in Python, to simplify the task of adding retry behavior to just

Julien Danjou 4.3k Jan 5, 2023
Simple yet flexible natural sorting in Python.

natsort Simple yet flexible natural sorting in Python. Source Code: https://github.com/SethMMorton/natsort Downloads: https://pypi.org/project/natsort

Seth Morton 712 Dec 23, 2022
A Python utility belt containing simple tools, a stdlib like feel, and extra batteries. Hashing, Caching, Timing, Progress, and more made easy!

Ubelt is a small library of robust, tested, documented, and simple functions that extend the Python standard library. It has a flat API that all behav

Jon Crall 638 Dec 13, 2022
Retrying is an Apache 2.0 licensed general-purpose retrying library, written in Python, to simplify the task of adding retry behavior to just about anything.

Retrying Retrying is an Apache 2.0 licensed general-purpose retrying library, written in Python, to simplify the task of adding retry behavior to just

Ray Holder 1.9k Dec 29, 2022
Pampy: The Pattern Matching for Python you always dreamed of.

Pampy: Pattern Matching for Python Pampy is pretty small (150 lines), reasonably fast, and often makes your code more readable and hence easier to rea

Claudio Santini 3.5k Jan 6, 2023
Hot reloading for Python

Hot reloading for Python

Olivier Breuleux 769 Jan 3, 2023
isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections and by type.

isort is a Python utility / library to sort imports alphabetically, and automatically separated into sections and by type. It provides a command line utility, Python library and plugins for various editors to quickly sort all your imports.

Python Code Quality Authority 5.5k Jan 8, 2023