dependency-injector

repository·master·Indexed 26 days ago

https://github.com/ets-labs/python-dependency-injector

A high-performance dependency injection framework for Python written in Cython. It provides tools for consolidating object assembly using DeclarativeContainer and DynamicContainer, supporting provider overriding, singleton management, and advanced patterns like Chained Factories and Factory of Factories.

Tokens
26.6K
Snippets
70
Records
153
Agent score
88%

What's inside dependency-injector

  1. Overview of Dependency Injector features

    master

    Dependency Injector is a high-performance dependency injection framework for Python, implemented using Cython. It facilitates the implementation of Inversion of Control (IoC) patterns through several key mechanisms:

    • Providers: Tools to assemble objects, including Factory, Singleton, Callable, Coroutine, Object, List, Dict, Configuration, Resource, Dependency, and Selector.
    • Containers: Support for both declarative and dynamic containers to consolidate object assembly.
    • Wiring: Enables injecting dependencies directly into functions and methods, facilitating integration with frameworks like Django, Flask, Aiohttp, Sanic, and FastAPI.
    • Configuration: Supports loading settings from yaml, ini, json files, pydantic settings, environment variables, and dictionaries.
    • Overriding: Allows replacing any provider with another on the fly, which is useful for testing (e.g., replacing API clients with mocks).
    • Resources: Manages initialization and configuration of resources like logging, event loops, or thread pools.
    • Asynchronous Support: Built-in support for asynchronous injections.
    • Typing: Provides mypy-friendly typing stubs.
  2. Overview of Dependency Injector key features

    master

    Dependency Injector is a high-performance Python framework for Dependency Injection and Inversion of Control (IoC). Key capabilities include:

    • Providers: A variety of provider types (Factory, Singleton, Callable, Coroutine, Object, List, Dict, Configuration, Resource, Dependency, and Selector) to assemble objects.
    • Overriding: Ability to override any provider with another on the fly, which is useful for replacing API clients with stubs during testing or environment configuration.
    • Configuration: Support for reading configuration from yaml, ini, json files, pydantic settings, environment variables, and dictionaries.
    • Resources: Tools for managing the initialization and configuration of resources like logging, event loops, or thread/process pools.
    • Containers: Support for both declarative and dynamic containers.
    • Wiring: Mechanism to inject dependencies directly into functions and methods, facilitating integration with frameworks like Django, Flask, Aiohttp, Sanic, and FastAPI.
    • Asynchronous Support: Native support for asynchronous injections.
    • Typing: Provides mypy-friendly typing stubs.
    • Performance: High-speed execution via Cython implementation.
  3. Summary of Flask integration patterns

    master

    The Flask tutorial demonstrates several core dependency-injector patterns:

    • Containers and Providers: Used to assemble services and integrate 3rd-party libraries.
    • Configuration Provider: Used to handle reading configuration from YAML files and environment variables.
    • Wiring: Used to inject dependencies directly into Flask views (e.g., the index() view).
    • Provider Overriding: Used during testing to replace real providers with mocks via the .override() method.
  4. Use Containers to manage providers

    master

    Containers are collections of providers used to organize your dependency injection logic. You can use them in several ways:

    • Centralized Management: Keeping all providers in a single container (the most common pattern).
    • Architectural Layering: Grouping providers by layer, such as creating separate Services, Models, or Forms containers.
    • Functional Grouping: Grouping providers by domain or package, such as a Users container that holds all functional parts of a users package.
  5. Summary of Dependency Injector features used in Asyncio Daemon

    master

    The Asyncio Daemon tutorial demonstrates several core patterns of the python-dependency-injector library:

    • Containers and Providers: Used to define how application components (like monitors and dispatchers) are assembled.
    • List Provider: Used to inject a collection of monitors into a single dispatcher component.
    • Configuration Provider: Used to manage application settings loaded from external files (e.g., YAML).
    • Wiring: Used to inject dependencies into functions (like main()) that are outside the container's direct control.
    • Provider Overriding: Used during testing to swap real implementations with mocks (e.g., container.http_client.override() or container.override_providers()).
  6. Understand the role of Providers in Dependency Injector

    master

    Providers are the core building blocks used to assemble object graphs. They are callables that, when invoked, create objects and automatically inject their required dependencies. This creates a cascade effect where calling one provider can trigger the instantiation and injection of multiple underlying dependencies.

    Key capabilities include:

    • Object Assembly: Automatically retrieving and injecting dependencies into new objects.
    • Overriding: Any provider can be overridden by another provider. This is a critical feature for testing (replacing real services with mocks/stubs) or switching between environments (e.g., replacing production API clients with stubs for development).
  7. Use DynamicContainer to define providers at runtime

    master
    Use dependency_injector.containers.DynamicContainer when your application structure depends on external sources (like configuration files, databases, or APIs) that are only accessible after the application has started running. Unlike static containers, you instantiate a DynamicContainer and then attach providers as attributes to the instance.
  8. Use the Selector provider for polymorphism

    master

    The Selector provider allows you to select a specific provider at runtime based on a configuration value or the result of a callable. This is useful for implementing polymorphism or switching between different implementations (e.g., different database drivers or API clients) based on environment variables or configuration settings.

    How it works:

    1. Selector: The first argument is the selector. This can be an option from a Configuration provider or any callable that returns a string.
    2. Providers: All other arguments are passed as keyword arguments. The argument names serve as the keys used for selection.
    3. Execution: When the Selector provider is called, it evaluates the selector, retrieves the corresponding string, and delegates the call to the provider matching that name.
  9. Run a Flask application with Dependency Injector

    master

    Once your application factory is defined, you can run the Flask development server by setting the FLASK_APP environment variable to the module containing your create_app function.

    Run the following commands in your terminal:

    export FLASK_APP=githubnavigator.application
    export FLASK_ENV=development
    flask run
    export FLASK_APP=githubnavigator.application
    export FLASK_ENV=development
    flask run