Metadata-Version: 2.4
Name: pybooster
Version: 0.0.10
Summary: Dependency injection without the boilerplate.
Project-URL: Source, https://github.com/rmorshea/pybooster
Project-URL: Documentation, https://ryanmorshead.com/pybooster
Author-email: Ryan Morshead <ryan.morshead@gmail.com>
License: MIT License
        
        Copyright (c) 2024-present Ryan Morshead <ryan.morshead@gmail.com>
        
        Permission is hereby granted, free of charge, to any person obtaining a copy of this
        software and associated documentation files (the "Software"), to deal in the Software
        without restriction, including without limitation the rights to use, copy, modify,
        merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
        permit persons to whom the Software is furnished to do so, subject to the following
        conditions:
        
        The above copyright notice and this permission notice shall be included in all copies or
        substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
        INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
        PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
        LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
        TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
        OTHER DEALINGS IN THE SOFTWARE.
License-File: LICENSE.txt
Keywords: dependency,framework,injection
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: <4,>=3.11
Requires-Dist: paramorator<2,>=1.0.2
Requires-Dist: rustworkx<0.16,>=0.15
Requires-Dist: typing-extensions
Provides-Extra: sqlalchemy
Requires-Dist: sqlalchemy[asyncio]<3,>=2; extra == 'sqlalchemy'
Description-Content-Type: text/markdown

# PyBooster 💉

[![PyPI - Version](https://img.shields.io/pypi/v/pybooster.svg)](https://pypi.org/project/pybooster)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

> [!WARNING] This project is still under development - use at your own risk.

PyBooster - dependency injection without the boilerplate.

## Documentation

Learn more here: https://ryanmorshead.com/pybooster

## Install

```bash
pip install -U pybooster
```

## At a Glance

Getting started with PyBooster involves a few steps:

1. Define a [provider](https://ryanmorshead.com/pybooster/concepts#providers) function
    for a [dependency](https://ryanmorshead.com/pybooster/conceptsd#dependencies).
1. Add an [injector](https://ryanmorshead.com/pybooster/conceptsd#injectors) to a
    function that will use that dependency.
1. Activate a [solution](https://ryanmorshead.com/pybooster/conceptsd#solutions) and
    call the dependent function in its context.

The example below injects a `sqlite3.Connection` into a function that executes SQL:

```python
import sqlite3
from collections.abc import Iterator
from tempfile import NamedTemporaryFile

from pybooster import injector
from pybooster import provider
from pybooster import required
from pybooster import solution


@provider.contextmanager
def sqlite_connection(database: str) -> Iterator[sqlite3.Connection]:
    with sqlite3.connect(database) as conn:
        yield conn


@injector.function
def sql(cmd: str, *, conn: sqlite3.Connection = required) -> sqlite3.Cursor:
    return conn.execute(cmd)


tempfile = NamedTemporaryFile()
with solution(sqlite_connection(tempfile.name)):
    sql("CREATE TABLE example (id INTEGER PRIMARY KEY, name TEXT)")
    sql("INSERT INTO example (name) VALUES ('alice')")
    cursor = sql("SELECT * FROM example")
    assert cursor.fetchone() == (1, "alice")
```

This works by inspecting the type hints of the provider `sqlite_connection` to see that
it produces a `sqlite3.Connection`. Simarly, the signature of the dependant function
`query_database` is inspected to see that it requires a `sqlite3.Connection`. At that
point, when `query_database` is called it checks to see if there's a
`sqlite3.Connection` provider in the current solution and, if so, injects it into the
function.
