pyautowire


Namepyautowire JSON
Version 0.3.1 PyPI version JSON
download
home_pagehttps://github.com/twaslowski/py-autowire
SummaryGood enough autowiring for Python
upload_time2024-04-09 07:39:49
maintainerNone
docs_urlNone
authorTobias Waslowski
requires_python<4.0,>=3.7
licensegpl3
keywords dependency injection autowire fixture
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # pyautowire ![PyPI](https://img.shields.io/pypi/v/pyautowire) ![Linting and Tests](https://github.com/twaslowski/py-autowire/actions/workflows/test.yml/badge.svg)

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]](https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection).

The most popular dependency injection library in Python is the aptly named `Dependency Injector`
[[2]](https://github.com/ets-labs/python-dependency-injector), 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:

```bash
pip install pyautowire
```

or via Poetry:

```bash
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:

```python
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:

```python
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.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/twaslowski/py-autowire",
    "name": "pyautowire",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.7",
    "maintainer_email": null,
    "keywords": "dependency injection, autowire, fixture",
    "author": "Tobias Waslowski",
    "author_email": "tobias.waslowski@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/7b/84/19c3521597a77216e8b04f8c1496097a48a8b7e14b211d236c8cbf4cdca8/pyautowire-0.3.1.tar.gz",
    "platform": null,
    "description": "# pyautowire ![PyPI](https://img.shields.io/pypi/v/pyautowire) ![Linting and Tests](https://github.com/twaslowski/py-autowire/actions/workflows/test.yml/badge.svg)\n\nLightweight dependency injection for Python that autowires into _anything_.\n\n## The Quick Pitch\n\nDo you love `pytest` fixtures? Do you wish you could have the flexibility of fixtures without actually having to worry\nabout the complications of using Dependency Injection? Then `pyautowire` is for you!\n\n## The Longer Version\n\nDependency Inversion is a common design pattern across a variety of languages. It most often occurs in object-oriented\nprogramming languages, where you can choose from a variety of flavours, such as constructor injection, setter injection,\nor interface injection [[1]](https://martinfowler.com/articles/injection.html#FormsOfDependencyInjection).\n\nThe most popular dependency injection library in Python is the aptly named `Dependency Injector`\n[[2]](https://github.com/ets-labs/python-dependency-injector), which comes with a massive variety of configuration\noptions.\n\nI personally primarily use Python for medium-sized pet projects, and I found those configuration options to be a bit\ntoo complex for my usecase. Specifically, there are cases where I don't necessarily want to turn everything into a\nclass to inject dependencies into; sometimes I just want a lightweight function that I can inject values into.\nEnter `pyautowire`, for all of your _good enough\u2122\ufe0f_ dependency injection needs.\n\n## Installation\n\nYou can install `pyautowire` via pip:\n\n```bash\npip install pyautowire\n```\n\nor via Poetry:\n\n```bash\npoetry add pyautowire\n```\n\nIt is compatible with Python3.7 and above.\n\n## Usage\n\nTo use `pyautowire`, you need to have your injectable classes inherit from the `Injectable` class and use the\n`@autowire` decorator on the methods you want to inject values into. For example:\n\n```python\nfrom pyautowire import Injectable, autowire\n\nclass Configuration(Injectable):\n    def __init__(self, config_value: str):\n        self.config_value = config_value\n\n@autowire('configuration')\ndef my_function(configuration: Configuration):\n    print(configuration.config_value)\n\nif __name__ == '__main__':\n    configuration = Configuration('Hello, World!').register()\n    my_function()\n```\n\nYou can see that you can call `my_function` without passing in any arguments; `pyautowire` will automatically inject them.\n\nAdmittedly, this is a rather silly example, since you could have just passed the configuration value as an argument to `my_function`.\nHowever, imagine you can use the `configuration` object across your entire application without ever using an `import`,\nhaving to store a global configuration object somewhere, or pass it around as an argument.\n\nNote that you **have** to call `register()` on your `Injectable` objects before you can use them.\nYou also **have** to specify all the arguments you would like to inject into your function in the `@autowire` decorator.\nGiven enough time, I might come up with a smarter solution to automatically handle that, but for now, this works fine.\n\n## Constructor Injection\n\n`pyautowire` _technically_ supports constructor injection. I'll be honest: This is a hack at the moment. But if you\nreally want to do it, it works:\n\n```python\nclass MyDatabase(Injectable):\n    @autowire('configuration')\n    def __init__(self, configuration: Configuration):\n        self.db_url = configuration.db_url\n        self.db_user = configuration.db_user\n        self.db_password = configuration.db_password\n```\n\n# Should I use this?\n\nAs a rule of thumb: For small projects where you want to avoid the complexity of a full-blown dependency injection library,\nwhile getting all of its benefits: sure. It is genuinely fun to work with, and it'll accelerate your workflow in rapid prototyping.\n\nFor larger projects, I would recommend using a more established library like `Dependency Injector`. The amount of complexity\nthis library can handle is very limited.\n",
    "bugtrack_url": null,
    "license": "gpl3",
    "summary": "Good enough autowiring for Python",
    "version": "0.3.1",
    "project_urls": {
        "Documentation": "https://github.com/twaslowski/py-autowire",
        "Homepage": "https://github.com/twaslowski/py-autowire",
        "Repository": "https://github.com/twaslowski/py-autowire"
    },
    "split_keywords": [
        "dependency injection",
        " autowire",
        " fixture"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bebd7b06475c63a31d74db3bfa4a379e511b4d92a655af248d3a4fdf7e2fce9a",
                "md5": "cf08dcf24b0ed84f2149bdcfbbf792cb",
                "sha256": "a19452733e082e5788a83e67730ec30de2b26d8a42063ca1df101b63c8990f67"
            },
            "downloads": -1,
            "filename": "pyautowire-0.3.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "cf08dcf24b0ed84f2149bdcfbbf792cb",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.7",
            "size": 17861,
            "upload_time": "2024-04-09T07:39:48",
            "upload_time_iso_8601": "2024-04-09T07:39:48.114534Z",
            "url": "https://files.pythonhosted.org/packages/be/bd/7b06475c63a31d74db3bfa4a379e511b4d92a655af248d3a4fdf7e2fce9a/pyautowire-0.3.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7b8419c3521597a77216e8b04f8c1496097a48a8b7e14b211d236c8cbf4cdca8",
                "md5": "04ed53e0c1881ca6236da9e142f809f0",
                "sha256": "6d0a6e4a2887e74a363aec16f95c040b4d780092be9fcdf8d6cc31d0f1ac6375"
            },
            "downloads": -1,
            "filename": "pyautowire-0.3.1.tar.gz",
            "has_sig": false,
            "md5_digest": "04ed53e0c1881ca6236da9e142f809f0",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.7",
            "size": 16509,
            "upload_time": "2024-04-09T07:39:49",
            "upload_time_iso_8601": "2024-04-09T07:39:49.285262Z",
            "url": "https://files.pythonhosted.org/packages/7b/84/19c3521597a77216e8b04f8c1496097a48a8b7e14b211d236c8cbf4cdca8/pyautowire-0.3.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-09 07:39:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "twaslowski",
    "github_project": "py-autowire",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pyautowire"
}
        
Elapsed time: 0.26341s