Dependency Injector is a dependency injection framework for Python.

Overview

Latest Version License Supported Python versions Supported Python implementations Downloads Downloads Downloads Wheel Build Status Coverage Status

What is Dependency Injector?

Dependency Injector is a dependency injection framework for Python.

It helps implementing the dependency injection principle.

Key features of the Dependency Injector:

  • Providers. Provides Factory, Singleton, Callable, Coroutine, Object, List, Dict, Configuration, Resource, Dependency and Selector providers that help assembling your objects. See Providers.
  • Overriding. Can override any provider by another provider on the fly. This helps in testing and configuring dev / stage environment to replace API clients with stubs etc. See Provider overriding.
  • Configuration. Reads configuration from yaml & ini files, pydantic settings, environment variables, and dictionaries. See Configuration provider.
  • Containers. Provides declarative and dynamic containers. See Containers.
  • Resources. Helps with initialization and configuring of logging, event loop, thread or process pool, etc. Can be used for per-function execution scope in tandem with wiring. See Resource provider.
  • Wiring. Injects dependencies into functions and methods. Helps integrating with other frameworks: Django, Flask, Aiohttp, Sanic, FastAPI, etc. See Wiring.
  • Asynchronous. Supports asynchronous injections. See Asynchronous injections.
  • Typing. Provides typing stubs, mypy-friendly. See Typing and mypy.
  • Performance. Fast. Written in Cython.
  • Maturity. Mature and production-ready. Well-tested, documented and supported.
from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide


class Container(containers.DeclarativeContainer):

    config = providers.Configuration()

    api_client = providers.Singleton(
        ApiClient,
        api_key=config.api_key,
        timeout=config.timeout.as_int(),
    )

    service = providers.Factory(
        Service,
        api_client=api_client,
    )


@inject
def main(service: Service = Provide[Container.service]):
    ...


if __name__ == '__main__':
    container = Container()
    container.config.api_key.from_env('API_KEY')
    container.config.timeout.from_env('TIMEOUT')
    container.wire(modules=[sys.modules[__name__]])

    main()  # <-- dependency is injected automatically

    with container.api_client.override(mock.Mock()):
        main()  # <-- overridden dependency is injected automatically

When you call main() function the Service dependency is assembled and injected automatically.

When doing a testing you call the container.api_client.override() to replace the real API client with a mock. When you call main() the mock is injected.

You can override any provider with another provider.

It also helps you in configuring project for the different environments: replace an API client with a stub on the dev or stage.

With the Dependency Injector objects assembling is consolidated in the container. Dependency injections are defined explicitly. This makes easier to understand and change how application works.

Visit the docs to know more about the Dependency injection and inversion of control in Python.

Installation

The package is available on the PyPi:

pip install dependency-injector

Documentation

The documentation is available here.

Examples

Choose one of the following:

Tutorials

Choose one of the following:

Concept

The framework stands on the PEP20 (The Zen of Python) principle:

Explicit is better than implicit

You need to specify how to assemble and where to inject the dependencies explicitly.

The power of the framework is in a simplicity. Dependency Injector is a simple tool for the powerful concept.

Frequently asked questions

What is the dependency injection?
  • dependency injection is a principle that decreases coupling and increases cohesion
Why should I do the dependency injection?
  • your code becomes more flexible, testable and clear 😎
How do I start doing the dependency injection?
  • you start writing the code following the dependency injection principle
  • you register all of your application components and their dependencies in the container
  • when you need a component, you specify where to inject it or get it from the container
What price do I pay and what do I get?
  • you need to explicitly specify the dependencies
  • it will be extra work in the beginning
  • it will payoff as the project grows
Have a question?
Found a bug?
Want to help?
  • ⭐️ Star the Dependency Injector on the Github
  • 🆕 Start a new project with the Dependency Injector
  • 💬 Tell your friend about the Dependency Injector
Want to contribute?
  • 🔀 Fork the project
  • ⬅️ Open a pull request to the develop branch
Issues
  • server is http

    server is http

    Hello,

    all your docs are stored in a HTTP server, however, many company proxies/AntiVir block any HTTP site.

    Just mentioning that moving to a https will make your docs available to a bigger audience (including myself :)).

    Regards, A.

    enhancement docs 
    opened by alnavv 48
  • Adding type hints to dependency-injector

    Adding type hints to dependency-injector

    Hi,

    Now that python typing (type hints) is very common, it would be great that dependency-injector will have type hints / annotations. Currently when using Container / Provider classes mypy complains since it doesn't have information about a provider returned type, etc.

    For example:

    provider: Provider[Animal] = providers.Factory(Cat)
    
    animal = provider()  # mypy can know that animal is of type Animal
    

    My current workaround is to put type: ignore in many places but it is less desired since I won't get errors at type checking time.

    Thanks

    feature docs 
    opened by awaizman1 24
  • Configuration raises AttributeError when provider is called

    Configuration raises AttributeError when provider is called

    Hi, I just run into this issue with the Configuration provider. After scratching my head for a bit, I managed to find a workaround, but I was wondering if this is actually a bug or just something wrong I am doing. Any help would be appreciated!

    Steps to reproduce

    containers.py

    from dependency_injector import providers, containers
    
    class MyService(object):
        def __init__(self, **kwargs):
            self.key = kwargs.pop('key')
    
        def trigger(self):
            pass
    
    class MyDevice(object):
        def __init__(self, **kwargs):
            # doesn't raise an error because it's an instance of
            # dependency_injector.providers.Singleton
            self.service = kwargs.pop('service')
    
        def do_something(self):
            # raises "AttributeError: 'NoneType' object has no attribute 'get'"
            self.service().trigger()
    
    class ServiceContainer(containers.DeclarativeContainer):
        config = providers.Configuration()
    
        myservice = providers.Singleton(MyService, config=config.myservice)
    
    
    class Container(containers.DeclarativeContainer):
        config = providers.Configuration()
    
        services = providers.Container(ServiceContainer, config=config.services)
    
        mydevice = providers.Factory(MyDevice)
    

    If I run app.py

    import sys
    
    from containers import Container
    
    container = Container()
    container.config.from_yaml('config.yaml')
    container.init_resources()
    container.wire(modules=[sys.modules[__name__]])
    
    mydevice = container.mydevice(service=container.services.myservice)
    mydevice.do_something()
    

    with config.yaml

    foo:
      bar: 42
    

    it raises the following error

    File "/home/stefano/personal/test-error/containers.py", line 15, in do_something self.service().trigger() File "src/dependency_injector/providers.pyx", line 168, in dependency_injector.providers.Provider.call File "src/dependency_injector/providers.pyx", line 2245, in dependency_injector.providers.Singleton._provide File "src/dependency_injector/providers.pxd", line 550, in dependency_injector.providers.__factory_call File "src/dependency_injector/providers.pxd", line 536, in dependency_injector.providers.__callable_call File "src/dependency_injector/providers.pxd", line 495, in dependency_injector.providers.__call File "src/dependency_injector/providers.pxd", line 387, in dependency_injector.providers.__provide_keyword_args File "src/dependency_injector/providers.pxd", line 310, in dependency_injector.providers.__get_value File "src/dependency_injector/providers.pyx", line 168, in dependency_injector.providers.Provider.call File "src/dependency_injector/providers.pyx", line 1232, in dependency_injector.providers.ConfigurationOption._provide File "src/dependency_injector/providers.pyx", line 1467, in dependency_injector.providers.Configuration.get AttributeError: 'NoneType' object has no attribute 'get'

    Workaround To avoid the issue, I have to pass the whole config to ServiceContainer

    class ServiceContainer(containers.DeclarativeContainer):
        config = providers.Configuration()
    
        myservice = providers.Singleton(MyService, config=config.services.myservice)
    
    
    class Container(containers.DeclarativeContainer):
        config = providers.Configuration()
    
        services = providers.Container(ServiceContainer, config=config)
    
        mydevice = providers.Factory(MyDevice)
    

    Running the application now, raises the following (as expected)

    File "/home/stefano/personal/test-error/containers.py", line 18, in do_something self.service().trigger() File "src/dependency_injector/providers.pyx", line 168, in dependency_injector.providers.Provider.call File "src/dependency_injector/providers.pyx", line 2245, in dependency_injector.providers.Singleton._provide File "src/dependency_injector/providers.pxd", line 550, in dependency_injector.providers.__factory_call File "src/dependency_injector/providers.pxd", line 536, in dependency_injector.providers.__callable_call File "src/dependency_injector/providers.pxd", line 526, in dependency_injector.providers.__call File "/home/stefano/personal/test-error/containers.py", line 5, in init self.key = kwargs.pop('key') KeyError: 'key'

    bug 
    opened by StefanoFrazzetto 21
  • Injection not working for class methods

    Injection not working for class methods

    I am not quite sure if this is expected behavior or not. Methods annotated as @classmethod end up getting extra parameters injected. The following code demonstrates. I discovered this while using Closing, but filled out the example a bit as I discovered that it is a general issue for Provide.

    import sys
    from dependency_injector import containers, providers
    from dependency_injector.wiring import Provide, Closing
    
    
    def my_factory():
        return 'test-factory'
    
    
    def my_resource():
        yield 'test-resource'
        print('Closing')
    
    
    class Container(containers.DeclarativeContainer):
    
        factory = providers.Factory(my_factory)
        resource = providers.Resource(my_resource)
    
    
    def do_function_thing(r:str=Closing[Provide[Container.resource]]) -> None:
        print('from function', r)
    
    
    class MyClass():
    
        def do_instance_thing(self, r:str=Closing[Provide[Container.resource]]) -> None:
            print('from instance', r)
    
        @classmethod
        def do_class_thing(cls, r:str=Closing[Provide[Container.resource]]) -> None:
            print('from class', r)
    
        @classmethod
        def non_closing_class_thing(cls, r:str=Provide[Container.factory]) -> None:
            print('non-closing from class', r)
    
    
    container = Container()
    container.init_resources()
    container.wire(modules=[sys.modules[__name__]])
    
    
    do_function_thing()
    c = MyClass()
    c.do_instance_thing()
    
    # both of these end up getting multiple values for r:
    c.non_closing_class_thing()
    c.do_class_thing()
    

    The resulting output is:

    from function test-resource
    Closing
    from instance test-resource
    Closing
    Traceback (most recent call last):
      File "clstest.py", line 49, in <module>
        c.non_closing_class_thing()
      File "/Users/scott/repos/github.com/scott2b/Starlight/.venv/lib/python3.8/site-packages/dependency_injector/wiring.py", line 296, in _patched
        result = fn(*args, **to_inject)
    TypeError: non_closing_class_thing() got multiple values for argument 'r'
    
    bug 
    opened by scott2b 19
  • Unable to wire injections, Flask out of context error

    Unable to wire injections, Flask out of context error

    I'm hoping this is just because I'm new at this.

    I'm developing an application, and currently working on converting to use dependency-injector. I've written a container and have been able to get configuration and a data store factory working. However, I'm running into an issue when wiring up injections with a Flask blueprint.

    When I follow the documentation and call the function to wire the container, I get a RuntimeError (actually from Flask):

    Traceback (most recent call last):
      File "c:\source\personal\pydas\src\pydas\__init__.py", line 61, in create_app
        app.container.wire(
      File "src/dependency_injector/containers.pyx", line 250, in dependency_injector.containers.DynamicContainer.wire
      File "C:\Source\Personal\pyDAS\.env\lib\site-packages\dependency_injector\wiring.py", line 238, in wire
        if inspect.isfunction(member):
      File "C:\Python38\lib\inspect.py", line 169, in isfunction
        return isinstance(object, types.FunctionType)
      File "C:\Source\Personal\pyDAS\.env\lib\site-packages\werkzeug-2.0.0rc1-py3.8.egg\werkzeug\local.py", line 379, in __get__
        obj = instance._get_current_object()
      File "C:\Source\Personal\pyDAS\.env\lib\site-packages\werkzeug-2.0.0rc1-py3.8.egg\werkzeug\local.py", line 499, in _get_current_object
        return self.__local()  # type: ignore
      File "C:\Source\Personal\pyDAS\.env\lib\site-packages\flask-1.1.2-py3.8.egg\flask\globals.py", line 38, in _lookup_req_object
        raise RuntimeError(_request_ctx_err_msg)
    RuntimeError: Working outside of request context.
    
    This typically means that you attempted to use functionality that needed
    an active HTTP request.  Consult the documentation on testing for
    information about how to avoid this problem.
    

    Although it's from Flask, it is only raised when calling the wire function, passing in the modules to my blueprints. I've refactored my code to no longer use current_app, thinking that might have made an impact. My primary app factory can be found here: https://github.com/bvanfleet/pydas/blob/u/bvanfleet/di.support/src/pydas/init.py

    Has this ever been encountered before? I tried searching through the other issues, but couldn't find an obvious answer.

    bug 
    opened by bvanfleet 16
  • Using dynamic containers with Fastapi endpoint.

    Using dynamic containers with Fastapi endpoint.

    I have not been able to find any documentation/examples on how to setup an endpoint using dynamic containers. All i've seen is: def create_transaction( dbengine: MyDbEngine = Depends(Provide[DiContainer.dbengine_provider]) )

    Of course this doesn't work for dynamic containers since i have no declarative container called DiContainer. Am i correct here? I'm sure i'm missing something here being new to python etc...

    thx ~MarvinB

    feature 
    opened by marvfinsy 15
  • How to deal with async resources

    How to deal with async resources

    Hi, for my usecase I want to use aio_pika

    And my singleton resource connection is created via:

    connection = await connect(
            "amqp://guest:[email protected]/", loop=loop
        )
    

    and shutdown via

    await connection.close()
    

    but it looks like something like this is not supported yet:

    async def aio_pika_connection():
     connection = await connect(
            "amqp://guest:[email protected]/", loop=loop
        )
     yield connection
     await connection.close()
    
    class Container(containers.DeclarativeContainer):
    
        config = providers.Configuration()
    
        aio_pika_connection= providers.Resource(
            aio_pika_connection
        )
    

    Any hints how to deal with this?

    question feature 
    opened by mxab 13
  • Question: providers.Configuration from *.ini

    Question: providers.Configuration from *.ini

    Hi,

    I use this module daily at work and for me fits perfectly! Thanks so much for your work!

    Question: Is there any way to load ini file directly to dependency_injector.providers.Configuration? Currently I solve this by implementing in Core my configuration loader and then override config values. Other way is to use directly python ConfigParser, load ini file and then override Core.config. I don't want to use directly ConfigParser because I had too much customized this class.

    So there is another question: Is there any awy to use customized ConfigParser to paste parameters from ini to Core.config?

    best regards!

    feature 
    opened by thegrymek 13
  • Cannot load pickle file when parameters are passed through Provide

    Cannot load pickle file when parameters are passed through Provide

    Hello, I have a class that is in charge to load some pickle files for a "machine learning" purpose.

    Specifically, I call my class, called Regressor, in this way, through the usage of a .ini file reporting all the desired settings:

    from dependency_injector import containers, providers
    from dependency_injector.wiring import inject, Provide
    from src.service.costestimator.configuration.configuration import Container
    
    class Regressor():
        def __init__(self,
                     regressors_list = Provide[Container.config.regressors_scalers.regressors_list.as_(str)],
                     regressors_path = Provide[Container.config.regressors_scalers.regressors_path.as_(str)],
                     scalers_path = Provide[Container.config.regressors_scalers.scalers_path.as_(str)],
                     file_type_regressors = Provide[Container.config.regressors_scalers.file_type_regressors.as_(str)],
                     file_type_scalers = Provide[Container.config.regressors_scalers.file_type_scalers.as_(str)]):
    

    When it comes to the "core" part of the code, it fails to load the pickle file:

        def load_model(self):
            if self.regressors_out is None:
                resulting_reg = {}
                resulting_scal = {}
                
                for regressor in self.regressors_list:
                    with open(self.regressors_path.joinpath(self.regressors_path, f'{regressor}.{self.file_type_regressors}'), 'rb') as reg:
                        resulting_reg[regressor] = pickle.load(reg)
    

    The error I get is the following: ImportError: cannot import name '_ccallback_c' from 'scipy._lib'

    The funny part is that: if I instantiate my Regressor class using the "Factory approach", it perfectly works.

    Any idea? Thank you in advance for any response

    bug 
    opened by Balthus1989 12
  • impossible to perform wire when modules are dinamically invoked with importlib.import_module

    impossible to perform wire when modules are dinamically invoked with importlib.import_module

    Hello there, I noticed that an explicit import of a package works smoothly, while a dinamic import causes the wire function to not work properly

    When it works:

    `from dependency_injector import containers, providers from dependency_injector.wiring import inject, Provide from pathlib import Path

    from src.service.costestimator.costestimator import costestimator as CE

    if name == 'main': service = 'costestimator' customer = 'john_doe' plant = '0'

    # Retrieving paths
    root_dir = Path.cwd().parent
    ini_file = service + '_' + customer + '_' + plant + '.ini'
    ini_path = root_dir.joinpath(root_dir, 'config', 'params', ini_file)
    
    # Loading needed libraries
    container = importlib.import_module('src.service.' + service + '.configuration.configuration')
    configuration = container.Container()
    configuration.config.from_ini(ini_path)
    configuration.wire(modules=[sys.modules[__name__]])
    
    CE_1 = CE()`
    

    In this case, the output is constituted by prints of fields coming from an .ini file (i.e.: the desired output).

    In the following case, it does not work: ` from dependency_injector import containers, providers from dependency_injector.wiring import inject, Provide from pathlib import Path import importlib

    if name == 'main': service = 'costestimator' customer = 'john_doe' plant = '0'

    # Retrieving paths
    root_dir = Path.cwd().parent
    ini_file = service + '_' + customer + '_' + plant + '.ini'
    ini_path = root_dir.joinpath(root_dir, 'config', 'params', ini_file)
    
    # Loading needed libraries
    container = importlib.import_module('src.service.' + service + '.configuration.configuration')
    configuration = container.Container()
    configuration.config.from_ini(ini_path)
    configuration.wire(modules=[sys.modules[__name__]])
    
    getattr(importlib.import_module('src.service.' + service + '.' + service), service)()
    

    `

    in this case, the result is a print of the Provide objects.

    The init function of the class costestimator is written as: class costestimator(): def __init__(self, customer_name = Provide[Container.config.customer.customer_name.as_(str)], customer_plant = Provide[Container.config.customer.customer_plant.as_(str)]):

    question feature 
    opened by Balthus1989 12
  • Optional dependencies

    Optional dependencies

    I am trying to create a container that optionally takes a dependency, and otherwise provides a value derived from another provider. The (IMO) hacky solution I have so far is a custom provider which either provides a Callable, or a default value if the callable has an error. Then I use this with the Callable being the dependency provider.

    My questions are (1) is there a better way? and (2) even using this method, DefaultCallable defined below seems like a hack -- how can I improve?

    
    T = TypeVar("T")
    
    class DefaultCallable(providers.Provider):
    
        __slots__ = ("_callable", "_default")
    
        def __init__(
            self, callable: Callable[..., T], default: T, *args, **kwargs
        ):
            self._default = default
            self._callable = providers.Callable(callable, *args, **kwargs)
    
            super().__init__()
    
        def __deepcopy__(self, memo):
            copied = memo.get(id(self))
            if copied is not None:
                return copied
    
            # TODO: type?
            copied = self.__class__(
                cast(Callable[..., T], self._callable.provides),
                providers.deepcopy(self._default, memo),
                *providers.deepcopy(self._callable.args, memo),
                **providers.deepcopy(self._callable.kwargs, memo),
            )
            self._copy_overridings(copied, memo)
            return copied
    
        def _provide(self, args, kwargs):
            try:
                return self._callable(*args, **kwargs)
            except Exception:
                # TODO: why do we need to check if is provider?
                # type?
                if getattr(cast(Any, self._default), "__IS_PROVIDER__", False):
                    return cast(Any, self._default)()
                else:
                    return self._default
    
    # Used like
    
    class Foo(containers.DeclarativeContainer):
    
        #: specify dv for pattern discovery (optional)
        dv_in: Provider[xr.DataArray] = providers.Dependency(
            instance_of=xr.DataArray
        )
    
        #: dv for pattern discovery (specified or default)
        dv: Provider[xr.DataArray] = DefaultCallable(
            # cast(Callable[..., xr.DataArray], dv_in), type??
            cast(Any, dv_in),
            problem.training.provided["dv"],
        )
    
    question feature 
    opened by shaunc 12
  • @inject with @wraps

    @inject with @wraps

    Need to check if the following behavior can be improved:

    @fabiocerqueira I faced the same issue as well, adding wraps is breaking the inject. @rmk135 could you please have a look?

    My use case is similar to what Fabio mentioned:

    def tagger(tag):
        def inner(func):
            # @wraps(func)  # <-- using wraps break inject
            @inject
            def tagger_wrapper(text, sep=Provide[Container.conf.sep], **kwargs):
                result = func(text, **kwargs)
                return f"{result}{sep}({tag}[{func.__name__}])"
    
            return tagger_wrapper
    
        return inner
    

    Originally posted by @Jitesh-Khuttan in https://github.com/ets-labs/python-dependency-injector/issues/454#issuecomment-1074868659

    opened by rmk135 0
  • AutoWiring entire module not works on AioHTTP decorated routes

    AutoWiring entire module not works on AioHTTP decorated routes

    While this works

    @routes.get('/health')
    @inject
    async def health(_: web.Request, async_session: SessionMaker = Provide[Container.session_maker]) -> web.Response:
        async with async_session() as session:
            query = text('select version(), current_database(), current_user, session_user')
            res = await session.execute(query)
            row = res.fetchone()
        return web.json_response(
            dict(**row)
        )
    

    This does not.

    @routes.get('/health')
    async def health(_: web.Request, async_session: SessionMaker = Provide[Container.session_maker]) -> web.Response:
        async with async_session() as session:
            query = text('select version(), current_database(), current_user, session_user')
            res = await session.execute(query)
            row = res.fetchone()
        return web.json_response(
            dict(**row)
        )
    

    Even having:

    class Container(containers.DeclarativeContainer):
        wiring_config = containers.WiringConfiguration(modules=[".handlers"]) -- health is in handlers
        ...
    

    Without decorated routes it worked

    opened by dnp1 0
  • FastAPI async resouce not being closed

    FastAPI async resouce not being closed

    I was trying out the async resource provider to verify that it is actually closing the resource. However, I noticed that it is not closing the resource.

    After deep investigations I found out that the @inject decorator on the API makes python think that the function is not an async generator.

    FastAPI decides whether the dependency is a generator on this line https://github.com/tiangolo/fastapi/blob/master/fastapi/dependencies/utils.py#L522

    Which then tries to inspect the code using the builtin inspect function

    def is_gen_callable(call: Callable[..., Any]) -> bool:
        if inspect.isgeneratorfunction(call):
            return True
        call = getattr(call, "__call__", None)
        return inspect.isgeneratorfunction(call)
    
    def is_async_gen_callable(call: Callable[..., Any]) -> bool:
        if inspect.isasyncgenfunction(call):
            return True
        call = getattr(call, "__call__", None)
        return inspect.isasyncgenfunction(call)
    

    Which is returning false for async generators decorated with @inject

    I have attached the test code.

    I'll try investigating the @inject decorator To see whether it could be fixed

    import contextlib
    import os
    from functools import partial
    
    from dependency_injector import containers, providers, resources
    from dependency_injector.wiring import Provide, inject, Closing
    from fastapi import FastAPI, Depends
    from pydantic import BaseSettings, Field
    from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine, AsyncSession
    from sqlalchemy.orm import sessionmaker
    
    os.environ["sql_alchemy_str"] = "sqlite+aiosqlite:///database.db"
    
    
    class DatabaseSettings(BaseSettings):
        sql_alchemy_str: str = Field(env="sql_alchemy_str")
    
    
    async def make(engine=None):
        print(f"Make {engine}")
        session = sessionmaker(
            engine, expire_on_commit=False, class_=AsyncSession
        )
        yield session()
        with open("kill.txt", "w") as f:
            f.write("killed")
        print("kill")
    
    
    class DatabaseContainer(containers.DeclarativeContainer):
        config = providers.Configuration[DatabaseSettings]("DatabaseConfig")
        alchemy_engine: AsyncEngine = providers.Singleton(create_async_engine, config.sql_alchemy_str, echo=True)
        async_session = providers.Resource(make, alchemy_engine)
    
    
    app = FastAPI()
    
    
    @app.get("/Hello")
    @inject
    async def say_hi(session: AsyncSession = Depends(Closing[Provide[DatabaseContainer.async_session]], use_cache=False)):
        print(f"Got {session}")
    
    
    container = DatabaseContainer()
    container.config.from_pydantic(DatabaseSettings())
    container.wire(modules=[__name__])
    
    
    @app.on_event("startup")
    async def startup_event():
        print(container.alchemy_engine())
    
    
    opened by John98Zakaria 1
  • Configuration provider injects as dict instance when passing entire config as dependency

    Configuration provider injects as dict instance when passing entire config as dependency

    Struggling with an issue when pass providers.Configuration directly to Object. In my code I have something like global context, and I want to keep configs instance in this context directly. But when I pass providers.Configuration to context object when wiring it passes as dict instance instead of Config. Is there any way to pass Configuration instance directly or at least add this particular behavior to documentation?

    Example:

    
    class CustomContext:
        def __init__(self, config: providers.Configuration):
            self.config = config
    
    class Container(containers.DeclarativeContainer):
        config = providers.Configuration(yaml_files=['config.yml'])
    
        some_context = providers.Singleton(
            CustomContext,
            config=config
        )
    
    @inject
    def init(
            some_context: CustomContext = Provide[Container.some_context]
    ):
        # Ex. 
        isinstance(some_context.config, dict)  # -> True 
    
    opened by VStoilovskyi 0
  • Ability to use provider method/property in Singleton or Callable Provider

    Ability to use provider method/property in Singleton or Callable Provider

    Hi, probably a simple question, but I can not find a straight answer anywhere on it:

    • Is there a way to use a method of one provider in another if another provider is a Singletone or Callable provider?

    So I want to do something like this (and in an ideal way to have proper typings for mypy check):

        factory= providers.Factory(Factory)
        service= providers.Callable(factory.create_service)
    

    I already know that it will work with:

        factory= providers.Factory(Factory)
        service= providers.Callable(factory().create_service)
    

    However, I would like to make it clean and postpone factory instantiation up to the moment when service will be required

    I have seen this page about "Injecting provided object attributes" : https://python-dependency-injector.ets-labs.org/providers/provided_instance.html And it looks like a perfect solution for me, but this code doesn't work:

        factory= providers.Factory(Factory)
        service= providers.Callable(factory.provided.create_service)
    

    Maybe because 'provided' works only when it is used as a dependency for another Provider

    So, yeah, would be happy for any suggestions

    opened by rustam-ashurov-mcx 5
  • Typing and code autocomplete with multi-containers setup

    Typing and code autocomplete with multi-containers setup

    Hi, I decided to switch to set up with multiple Containers used in one main container. Copied code from example: https://python-dependency-injector.ets-labs.org/examples/application-multiple-containers.html

    So my code looks merely the same with one container that aggregates many other:

    class Container(containers.DeclarativeContainer):
        child = providers.Container(ChildContainer)
    

    And having FastAPI as the main framework I inject dependencies in a router like this:

    @router.get("")
    @inject
    async def test(logger: Logger = Depends(Provide[Container.child.logger])):
        logger.info("Oh, hi Mark")
    

    The issue is that Container.child is of Container[ChildContainer] type and even having logger on ChildContainer it is not visible anymore, therefore VS Code doesn't suggest autocomplete options (also not sure whether MyPy will be happy about it, but it is another story)

    Is there a legal and safe way to inject dependencies from ChildContainer (when it is provided via another parent container) and have all beauty of a language server functionality?

    opened by rustam-ashurov-mcx 1
Owner
ETS Labs
Expert Technical Solutions Labs
ETS Labs
A Container for the Dependency Injection in Python.

Python Dependency Injection library aiodi is a Container for the Dependency Injection in Python. Installation Use the package manager pip to install a

Denis NA 3 Jun 25, 2022
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 29 Jun 16, 2022
Run async workflows using pytest-fixtures-style dependency injection

Run async workflows using pytest-fixtures-style dependency injection

Simon Willison 27 May 30, 2022
A library for interacting with Path of Exile game and economy data, and a unique loot filter generation framework.

wraeblast A library for interfacing with Path of Exile game and economy data, and a set of item filters geared towards trade league players. Filter Ge

David Gidwani 29 Jun 5, 2022
A collection of resources/tools and analyses for the angr binary analysis framework.

Awesome angr A collection of resources/tools and analyses for the angr binary analysis framework. This page does not only collect links and external r

null 72 Jun 16, 2022
Modest utility collection for development with AIOHTTP framework.

aiohttp-things Modest utility collection for development with AIOHTTP framework. Documentation https://aiohttp-things.readthedocs.io Installation Inst

Ruslan Ilyasovich Gilfanov 1 Dec 11, 2021
✨ 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 3 Jun 4, 2021
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 27 Feb 10, 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 8 Jan 29, 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 3.9k Jun 21, 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.3k Jun 18, 2022
🔩 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 5.8k Jun 27, 2022
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 3.9k Jun 26, 2022
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 660 Jun 19, 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 599 Jun 17, 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.8k Jun 21, 2022