Metadata-Version: 2.1
Name: wireup
Version: 0.8.2
Summary: Python Dependency Injection Library
Home-page: https://github.com/maldoinc/wireup
License: MIT
Keywords: flask,django,injector,dependency injection,dependency injection container,dependency injector
Author: Aldo Mateli
Author-email: aldo.mateli@gmail.com
Requires-Python: >=3.8,<4.0
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: FastAPI
Classifier: Framework :: Flask
Classifier: Framework :: aiohttp
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: graphlib2 (>=0.4.7,<0.5.0) ; python_version >= "3.8" and python_version < "3.9"
Description-Content-Type: text/markdown

<div align="center">
<h1>Wireup</h1>
<p>Modern Dependency Injection for Python.</p>

[![GitHub](https://img.shields.io/github/license/maldoinc/wireup)](https://github.com/maldoinc/wireup)
[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/maldoinc/wireup/run_all.yml)](https://github.com/maldoinc/wireup)
[![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/maldoinc/wireup?label=Code+Climate)](https://codeclimate.com/github/maldoinc/wireup)
[![Coverage](https://img.shields.io/codeclimate/coverage/maldoinc/wireup?label=Coverage)](https://codeclimate.com/github/maldoinc/wireup)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/wireup)](https://pypi.org/project/wireup/)
[![PyPI - Version](https://img.shields.io/pypi/v/wireup)](https://pypi.org/project/wireup/)

<p>Wireup is a performant, concise, and easy-to-use dependency injection container for Python 3.8+.</p>
</div>

---

## ⚡ Key Features
* Inject services and configuration.
* Support for interfaces and abstract classes.
* Factory pattern.
* Singleton and transient dependencies.
* Framework-agnostic.
* Simplified integration with [Django](https://maldoinc.github.io/wireup/latest/integrations/django/),
[Flask](https://maldoinc.github.io/wireup/latest/integrations/flask/), and 
[FastAPI](https://maldoinc.github.io/wireup/latest/integrations/fastapi/).

## 📋 Quickstart

Example showcasing a Redis wrapper and a weather service that calls an external API and caches results as needed.

**1. Set up**

```python
from wireup import container, initialize_container
def create_app():
    app = ...
    
    # ⬇️ Expose configuration by populating container.params.
    container.params.put("redis_url", os.environ["APP_REDIS_URL"])
    container.params.put("weather_api_key", os.environ["APP_WEATHER_API_KEY"])

    # Bulk update is possible via the "update" method.
    container.params.update(Settings().model_dump())
    
    # Start the container: This registers and initializes services.
    # `service_modules` contains top-level modules containing registrations.
    # ⬇️
    initialize_container(container, service_modules=[services])

    return app
```

**2. Register services**

Use a declarative syntax to describe services, and let the container handle the rest.

```python
from wireup import service, Inject

@service # ⬅️ Decorator tells the container this is a service.
class KeyValueStore:
                                           # This tells the container to inject the value
                                           # of the parameter during creation.
                                           # ⬇️ 
    def __init__(self, dsn: Annotated[str, Inject(param="redis_url")]):
        self.client = redis.from_url(dsn)

    def get(self, key: str) -> Any: ...
    def set(self, key: str, value: Any): ...


@service
@dataclass
class WeatherService:
    # Inject the value of the parameter to this field. ⬇️
    api_key: Annotated[str, Inject(param="weather_api_key")]
    kv_store: KeyValueStore # ⬅️ This will be injected automatically without additional metadata.

    def get_forecast(self, lat: float, lon: float) -> WeatherForecast:
        ...
```

**3. Inject**

Decorate targets where the library should perform injection.

```python
from wireup import container

@app.get("/weather/forecast")
# ⬇️ Decorating views with autowire enables the container to inject services/parameters.
@container.autowire
def get_weather_forecast_view(weather_service: WeatherService, request):
    return weather_service.get_forecast(request.lat, request.lon)
```

**Installation**

```bash
# Install using poetry:
poetry add wireup

# Install using pip:
pip install wireup
```

## 📑 Documentation

For more information [check out the documentation](https://maldoinc.github.io/wireup)

## 🎮 Demo application

A demo flask application is available at [maldoinc/wireup-demo](https://github.com/maldoinc/wireup-demo)

