Skip to main content

Good enough autowiring for Python

Project description

pyautowire PyPI Linting and Tests

Lightweight dependency injection for Python that autowires into anything.

The Quick Pitch

Do you love pytest fixtures? Do you wish you could have the flexibility of fixtures without actually having to worry about the complications of using Dependency Injection? Then pyautowire is for you!

The Longer Version

Dependency Inversion is a common design pattern across a variety of languages. It most often occurs in object-oriented programming languages, where you can choose from a variety of flavours, such as constructor injection, setter injection, or interface injection [1].

The most popular dependency injection library in Python is the aptly named Dependency Injector [2], which comes with a massive variety of configuration options.

I personally primarily use Python for medium-sized pet projects, and I found those configuration options to be a bit too complex for my usecase. Specifically, there are cases where I don't necessarily want to turn everything into a class to inject dependencies into; sometimes I just want a lightweight function that I can inject values into. Enter pyautowire, for all of your good enough™️ dependency injection needs.

Installation

You can install pyautowire via pip:

pip install pyautowire

or via Poetry:

poetry add pyautowire

It is compatible with Python3.7 and above.

Usage

To use pyautowire, you need to have your injectable classes inherit from the Injectable class and use the @autowire decorator on the methods you want to inject values into. For example:

from pyautowire import Injectable, autowire

class Configuration(Injectable):
    def __init__(self, config_value: str):
        self.config_value = config_value

@autowire('configuration')
def my_function(configuration: Configuration):
    print(configuration.config_value)

if __name__ == '__main__':
    configuration = Configuration('Hello, World!').register()
    my_function()

You can see that you can call my_function without passing in any arguments; pyautowire will automatically inject them.

Admittedly, this is a rather silly example, since you could have just passed the configuration value as an argument to my_function. However, imagine you can use the configuration object across your entire application without ever using an import, having to store a global configuration object somewhere, or pass it around as an argument.

Note that you have to call register() on your Injectable objects before you can use them. You also have to specify all the arguments you would like to inject into your function in the @autowire decorator. Given enough time, I might come up with a smarter solution to automatically handle that, but for now, this works fine.

Constructor Injection

pyautowire technically supports constructor injection. I'll be honest: This is a hack at the moment. But if you really want to do it, it works:

class MyDatabase(Injectable):
    @autowire('configuration')
    def __init__(self, configuration: Configuration):
        self.db_url = configuration.db_url
        self.db_user = configuration.db_user
        self.db_password = configuration.db_password

Should I use this?

As a rule of thumb: For small projects where you want to avoid the complexity of a full-blown dependency injection library, while getting all of its benefits: sure. It is genuinely fun to work with, and it'll accelerate your workflow in rapid prototyping.

For larger projects, I would recommend using a more established library like Dependency Injector. The amount of complexity this library can handle is very limited.

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

pyautowire-0.3.1.tar.gz (16.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyautowire-0.3.1-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

Details for the file pyautowire-0.3.1.tar.gz.

File metadata

  • Download URL: pyautowire-0.3.1.tar.gz
  • Upload date:
  • Size: 16.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.12.2 Darwin/23.4.0

File hashes

Hashes for pyautowire-0.3.1.tar.gz
Algorithm Hash digest
SHA256 6d0a6e4a2887e74a363aec16f95c040b4d780092be9fcdf8d6cc31d0f1ac6375
MD5 04ed53e0c1881ca6236da9e142f809f0
BLAKE2b-256 7b8419c3521597a77216e8b04f8c1496097a48a8b7e14b211d236c8cbf4cdca8

See more details on using hashes here.

File details

Details for the file pyautowire-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: pyautowire-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 17.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.7.1 CPython/3.12.2 Darwin/23.4.0

File hashes

Hashes for pyautowire-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a19452733e082e5788a83e67730ec30de2b26d8a42063ca1df101b63c8990f67
MD5 cf08dcf24b0ed84f2149bdcfbbf792cb
BLAKE2b-256 bebd7b06475c63a31d74db3bfa4a379e511b4d92a655af248d3a4fdf7e2fce9a

See more details on using hashes here.

Supported by

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