Skip to main content

A simple dependency injection framework for Python

Project description

Dependency Injector for Python

A simple and flexible dependency injection framework for Python projects. This library allows you to define services, manage their lifecycle, and inject dependencies into your applications in a clean and structured way.

Installation

You can install this library using pip:

pip install simple-dependency-injector

Basic Usage

Loading and Compiling Services

First, load your service definitions from a YAML file or Python module and compile them:

from simple_dependency_injector import DependencyInjector

# Create an injector and load the service definitions
injector = DependencyInjector(base_path='config_path')
injector.load('services.yaml')
injector.compile()

# Access a service
service = injector.get('my_service')

Service Definition Example (services.yaml)

You can define services in a YAML file:

services:
  my_service:
    class: 'tests/services/my_module.py#MyService'
    arguments:
      - '@another_service'
    scope: singleton

  another_service:
    class: 'tests/services/another_module.py#AnotherService'
    scope: transient
  • class: The fully qualified class name to instantiate.

  • arguments: The list of dependencies to inject.

    • Service Reference (@service_name): This resolves to another service defined in the injector.
    • Tagged Services (!tagged:tag_name): This resolves to a list of services that have the specified tag.
    • Context Reference (!context): This resolves to the current DI context.
  • scope: The lifecycle of the service. Options are singleton, transient, request, or ambivalent.

Example of Argument Resolution:

services:
  my_service:
    class: 'tests/services/my_service.py#MyService'
    arguments:
      - '@another_service'
      - '!tagged:logging'
      - '!context'
    scope: singleton

When my_service is instantiated, the @another_service argument will resolve to the instance of another_service, !tagged:logging will resolve to a list of services tagged with logging, and !context will resolve to the current DI context.

Accessing Services by Tags

You can assign tags to services and resolve them by tag:

services:
  tagged_service:
    class: 'tests/services/tagged_service.py#TaggedService'
    tags:
      - 'my_tag'
    scope: singleton

You can then retrieve all services that have a specific tag:

services_with_tag = injector.get_list_with_tag('my_tag')

Linking Services

You can link services during runtime. For example, you can retrieve one service and assign its instance to another service:

injector.link('source_service', 'target_service')

This is useful when you need to dynamically replace or redirect service instances.

Using the Dependency Injector in Django

To use the dependency injector in Django, you can inject services into requests by creating a custom middleware.

1. Middleware for Dependency Injection Context

Create a middleware to add a new dependency injection context for each request:

# middlewares.py
from simple_dependency_injector import DependencyInjector

injector = DependencyInjector(base_path='config_path')
injector.load('services.yaml')
injector.compile()


class DependencyInjectorMiddleware:
  def __init__(self, get_response):
    self.get_response = get_response

  def __call__(self, request):
    request.container = injector.create_context()
    response = self.get_response(request)
    return response

2. Middleware for Logger Service

You can also create a middleware to inject services like a logger into the request context:

# middlewares.py
from .logger_service import DjangoLoggerService

class LoggerMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        request.container.set("logger_service", DjangoLoggerService(request))
        response = self.get_response(request)
        return response

3. Register the Middlewares in Django Settings

Add the middlewares to your MIDDLEWARE setting in settings.py:

# settings.py
MIDDLEWARE = [
    # Other middlewares
    'myapp.middlewares.DependencyInjectorMiddleware',
    'myapp.middlewares.LoggerMiddleware',
]

4. Accessing Services in Django Views

Now you can access the services from the request container in your Django views:

# views.py
from django.http import JsonResponse

def my_view(request):
    # Get the logger service from the DI container
    logger = request.container.get('logger_service')

    # Use the logger
    logger.log('This is a log message')

    return JsonResponse({'status': 'success'})

Advanced Features

Using Factories

You can define services using factory methods. This is useful when the service creation logic is more complex:

services:
  factory_service:
    factory:
      class: 'tests/services/my_module.py#MyFactory'
      method: create_service
    arguments:
      - 'config_value'
    scope: singleton

Contextual Dependency Injection

For services that need to maintain a request-specific state, you can create a new context per request and resolve services within that context:

# Create a context for each request
context = injector.create_context()

# Access services within that context
service = context.get('my_service')

Development

Setting Up a Development Environment

To set up a local development environment for this project, follow these steps:

  1. Fork this repository and clone it:
git clone https://github.com/yourusername/python-simple-dependency-injector.git
cd simple-dependency-injector
  1. Create a virtual environment:
python -m venv venv
  1. Activate the virtual environment:
source venv/bin/activate
  1. Install the development dependencies:
pip install -r requirements-dev.txt

Now you are ready to start working on the project. You can run tests, add new features, or fix bugs.

Check the code style

black simple_dependency_injector tests && pylint simple_dependency_injector tests

Tests

This project includes a suite of unit tests to ensure that all functionality works as expected. The tests are located in the tests directory, and you can run them using:

python -m unittest discover tests

License

This project is licensed under the MIT License. See the LICENSE file for details.

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

simple_dependency_injector-0.2.0.tar.gz (9.8 kB view details)

Uploaded Source

Built Distribution

File details

Details for the file simple_dependency_injector-0.2.0.tar.gz.

File metadata

File hashes

Hashes for simple_dependency_injector-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d8b2f225368a8db6a77ec7043a55b454fcd1b014b104ca1aa8eb40ca7af22234
MD5 426067d84b11b2c34736be44d4712fc6
BLAKE2b-256 96738040d4a0beeec8b901465137051009384cc8df15e166880ca66ebdfd1069

See more details on using hashes here.

File details

Details for the file simple_dependency_injector-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for simple_dependency_injector-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 74d846fb2461ab5f7b000839232dd8563876a50a7a07442e800b9e8188975aed
MD5 05ceb2d73f0730e087f975d2ae688f26
BLAKE2b-256 77ddfc900e95778d5c7d1a3fd6d1dccd095259f9d1d2e755b9fb0805e00db22f

See more details on using hashes here.

Supported by

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