Metadata-Version: 2.4
Name: pico-fastapi
Version: 0.1.0
Summary: Pico-ioc integration for FastAPI. Adds Spring Boot-style controllers, autoconfiguration, and scopes (request, websocket, session).
Author-email: David Perez Cabrera <dperezcabrera@gmail.com>
License: MIT License
        
        Copyright (c) 2025 David Pérez Cabrera
        
        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.
        
Project-URL: Homepage, https://github.com/dperezcabrera/pico-fastapi
Project-URL: Repository, https://github.com/dperezcabrera/pico-fastapi
Project-URL: Issue Tracker, https://github.com/dperezcabrera/pico-fastapi/issues
Keywords: ioc,di,dependency injection,fastapi,inversion of control,spring boot,controller
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pico-ioc>=2.0
Requires-Dist: fastapi>=0.100
Provides-Extra: session
Requires-Dist: starlette-session; extra == "session"
Provides-Extra: run
Requires-Dist: uvicorn[standard]; extra == "run"
Dynamic: license-file

# 📦 pico-fastapi

[![PyPI](https://img.shields.io/pypi/v/pico-fastapi.svg)](https://pypi.org/project/pico-fastapi/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/dperezcabrera/pico-fastapi)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
![CI (tox matrix)](https://github.com/dperezcabrera/pico-ioc/actions/workflows/ci.yml/badge.svg)
[![codecov](https://codecov.io/gh/dperezcabrera/pico-fastapi/branch/main/graph/badge.svg)](https://codecov.io/gh/dperezcabrera/pico-fastapi)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-fastapi&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-fastapi)
[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-fastapi&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-fastapi)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-fastapi&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-fastapi)

**pico-fastapi** integrates **Pico-IoC** with **FastAPI**, enabling *constructor-based dependency injection*, scoped lifecycles, and clean architectural boundaries — without global state or FastAPI dependency functions.

> 🐍 Requires **Python 3.10+**  
> ✅ Fully async-compatible  
> ✅ Real IoC (constructor injection, not function injection)  
> ✅ Works with request, session, and websocket scopes  

---

## 🎯 Why pico-fastapi?

FastAPI’s built-in dependency system is function-based, which makes business logic tightly coupled to the framework.

`pico-fastapi` moves dependency resolution to the **IoC container**.

| Concern | FastAPI Default | pico-fastapi |
|--------|----------------|--------------|
| Dependency injection | Function-based | Constructor-based |
| Architecture | Framework-driven | Domain-driven |
| Testing | Must simulate DI functions | Component overrides at container init |
| Scopes | Manual or ad-hoc | `singleton`, `request`, `session`, `websocket` |

---

## 🧱 Core Features

- `@controller` class-based routing
- `@get`, `@post`, `@websocket`, etc.
- Constructor injection for controllers & services
- Automatic registration into FastAPI
- Scoped resolution via middleware (`request`, `session`, `websocket`)
- Full compatibility with Pico-IoC features: overrides, profiles, interceptors, cleanup

---

## 📦 Installation

```bash
pip install pico-fastapi
````

Also requires:

```bash
pip install pico-ioc fastapi
```

---

## 🚀 Quick Example

```python
# controllers.py
from pico_fastapi import controller, get

@controller(prefix="/api")
class ApiController:
    def __init__(self, service: "MyService"):
        self.service = service

    @get("/hello")
    async def hello(self):
        return {"msg": self.service.greet()}
```

```python
# services.py
class MyService:
    def greet(self) -> str:
        return "hello from service"
```

```python
# main.py
from pico_ioc import init
from fastapi import FastAPI

container = init(
    modules=[
        "controllers",
        "services",
        "pico_fastapi.factory",
    ]
)

app = container.get(FastAPI)  # ✅ retrieve the fully configured app
```

---

## 💬 WebSocket Example

```python
from pico_fastapi import controller, websocket
from fastapi import WebSocket

@controller
class ChatController:
    async def __init__(self):
        pass

    @websocket("/ws")
    async def chat(self, websocket: WebSocket):
        await websocket.accept()
        while True:
            message = await websocket.receive_text()
            await websocket.send_text(f"Echo: {message}")
```

---

## 🧪 Testing with Overrides

```python
from pico_ioc import init
from fastapi import FastAPI
from fastapi.testclient import TestClient

class FakeService:
    def greet(self) -> str:
        return "test"

container = init(
    modules=["controllers", "services", "pico_fastapi.factory"],
    overrides={ "MyService": FakeService() }
)

app = container.get(FastAPI)
client = TestClient(app)

assert client.get("/api/hello").json() == {"msg": "test"}
```

---

## ⚙️ How It Works

* `@controller` classes are registered automatically
* HTTP/WebSocket handlers are wrapped in a request or websocket scope
* All dependencies (services, config, state) are resolved through Pico-IoC
* Cleanup happens at application shutdown via lifespan integration

No global state. No implicit singletons. No magic.

---

## 📝 License

MIT — See `LICENSE`.


