Skip to main content

The Botox is a lightweight dependency injection pattern implementation for Python.

Project description

Botox

Botox is a lightweight dependency injection implementation based on Python typing. It helps deliver the configured functional objects, decreasing coupling between a class and its dependencies.

Delivery

Global variables? Proxy objects? Application context?

There should be one (and preferably only one) obvious way to do it.

Botox helps you isolate a class from the impact of different design changes and defects. Meaning that, instead of thinking about interdependence between software modules you will now find yourself spending much of your time having to focus a class on the task it is designed for.

Configuration

Monkey-patching? Decorators?

Explicit is better than implicit.

Botox allows a class the flexibility of being configurable. The class may act on anything that supports the intrinsic interface the class expects. Explicit configurations can be written separately for different situations that require different implementations of dependencies.

Usage

Now is better than never.

Botox doesn’t require any change in code behavior it can be applied to legacy code as a refactoring.

Installation

Install and update using pip:

pip install -U botox-di

Examples

Class Injection

Can be used to reduce boilerplate code in the application classes since all work to initialize or set up dependencies is handled separately.

class PaymentService:
    ...

class BillingService:
    ...

class SalesService:

    def __init__(self, payment_service: PaymentService, billing_service: BillingService):
        self.payment_service = payment_service
        self.billing_service = billing_service

    ...


injector = Injector()
injector.prepare(PaymentService)
injector.prepare(BillingService)
injector.prepare(SalesService)

sales = injector.deliver(SalesService)
sales.do_something()

The result is class that is easier to unit test in isolation using stubs or mock objects that simulate other objects.

# test_sales.py

injector.prepare(PaymentService, PaymentServiceStub)

Value Injection

Can be used when exactly one object is needed to coordinate actions across the system.

class AppSettings:
    ...

settings = AppSettings()

injector = Injector()
injector.prepare(AppSettings, settings)

assert injector.deliver(AppSettings) is settings

Lambda Injection

Can be used to wrap Proxy objects in legacy code as refactoring.

from flask import g, current_app

injector = Injector()
injector.prepare(Flask, lambda: current_app)
injector.prepare(Something, lambda: g.something)

Function Injection

Can be used to make factory functions with dependencies.

def create_api_client(settings: Settings):
    with open(settings.api_configuration_file) as file:
        key, url = file.read(...)
        return ApiClient(key, url)

injector = Injector()
injector.provide(Settings)
injector.provide(ApiClient, create_api_client)

Advanced

from aiohttp import web
from botox import Injector

class TemplateRepository:
    def get_template(self):
        return "Hello, {}!"

class HelloService:
    def __init__(self, template_repository: TemplateRepository):
        self.template_repository = template_repository

    def get_hello_message(self, name):
        template = self.template_repository.get_template()
        return template.format(name)


async def handle(request):
    service = request.app.injector.deliver(HelloService)
    name = request.match_info.get('name', "Anonymous")
    text = service.get_hello_message(name)
    return web.Response(text=text)


app = web.Application()

app.injector = Injector()
app.injector.prepare(HelloService)
app.injector.prepare(TemplateRepository)

app.add_routes([
    web.get('/', handle),
    web.get('/{name}', handle)
])

web.run_app(app)

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

botox-di-1.4.0.tar.gz (4.4 kB view details)

Uploaded Source

Built Distribution

botox_di-1.4.0-py3-none-any.whl (4.4 kB view details)

Uploaded Python 3

File details

Details for the file botox-di-1.4.0.tar.gz.

File metadata

  • Download URL: botox-di-1.4.0.tar.gz
  • Upload date:
  • Size: 4.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.11.1 setuptools/39.1.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.7.0

File hashes

Hashes for botox-di-1.4.0.tar.gz
Algorithm Hash digest
SHA256 ded50a2c5eccc13d811e662dbf9f2920d4341d188c24fee9cc5f157c4d0817d4
MD5 449bdc43bd13069f3f5da68f1a14b34c
BLAKE2b-256 765ef661443d65efc43b763e6b32b75c5fafee15883678fd26f20c6bf0ef4fc9

See more details on using hashes here.

File details

Details for the file botox_di-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: botox_di-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 4.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.11.1 setuptools/39.1.0 requests-toolbelt/0.8.0 tqdm/4.24.0 CPython/3.7.0

File hashes

Hashes for botox_di-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 efe1622455a38cea3a53f8fb1ab590ad25a262bbf0fd90652c88681d5da239a1
MD5 93f71d0f37a75f23866f89fb3ee7e963
BLAKE2b-256 00905614648cfa2b381c630962ed3127bdf9e0afa89d7dd0358c0ea1c5f77f5a

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