Metadata-Version: 2.3
Name: processpype
Version: 1.1.2
Summary: A modular application framework with built-in FastAPI integration and pluggable services
Author: Gianluca Pagliara
Author-email: pagliara.gianluca@gmail.com
Requires-Python: >=3.13,<4.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Provides-Extra: agents
Provides-Extra: all
Provides-Extra: all-py313
Provides-Extra: database
Provides-Extra: database-py313
Provides-Extra: monitoring
Provides-Extra: notifications
Provides-Extra: storage
Requires-Dist: agentspype (>=0.1.3,<0.2.0) ; extra == "agents" or extra == "all" or extra == "all-py313"
Requires-Dist: aiosmtplib (>=3.0.1,<4.0.0) ; extra == "notifications" or extra == "all" or extra == "all-py313"
Requires-Dist: aiosqlite (>=0.20.0,<0.21.0) ; extra == "database" or extra == "database-py313" or extra == "all" or extra == "all-py313"
Requires-Dist: asyncpg (>=0.29.0,<0.30.0) ; (python_version < "3.13") and (extra == "database" or extra == "all")
Requires-Dist: boto3 (>=1.37.0,<2.0.0) ; extra == "storage" or extra == "all" or extra == "all-py313"
Requires-Dist: chronopype (>=0.2.7,<0.3.0)
Requires-Dist: cronitor (==4.7.1) ; extra == "monitoring" or extra == "all" or extra == "all-py313"
Requires-Dist: eventspype (>=1.0.3,<2.0.0)
Requires-Dist: fastapi (>=0.115.6,<0.116.0)
Requires-Dist: httpx (>=0.28.1,<0.29.0)
Requires-Dist: logfire[fastapi] (>=2.11.1,<3.0.0)
Requires-Dist: psutil (>=6.1.1,<7.0.0)
Requires-Dist: pydantic (>=2.10.4,<3.0.0)
Requires-Dist: pytz (>=2024.2,<2025.0)
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
Requires-Dist: sqlalchemy (>=2.0.30,<3.0.0) ; extra == "database" or extra == "database-py313" or extra == "all" or extra == "all-py313"
Requires-Dist: telethon (>=1.34.0,<2.0.0) ; extra == "notifications" or extra == "all" or extra == "all-py313"
Requires-Dist: uvicorn (>=0.34.0,<0.35.0)
Project-URL: Repository, https://github.com/gianlucapagliara/processpype
Description-Content-Type: text/markdown

# Processpype

Processpype is a framework for building and managing an application that is composed of services.

## Architecture Overview

The core module provides the fundamental building blocks for creating and managing services in the ProcessPype framework.

### Core Components

#### 1. Application (`application.py`)
The central orchestrator that manages the lifecycle of the application and its services.

```python
from processpype.core import Application

app = await Application.create("config.yaml")
await app.start()
```

Key features:
- Async context manager support
- FastAPI integration
- Service lifecycle management
- Configuration management

#### 2. Application Manager (`manager.py`)
Handles service registration, state management, and lifecycle operations.

Key responsibilities:
- Service registration and retrieval
- Service state management
- Service startup/shutdown orchestration

#### 3. Router (`router.py`)
Provides REST API endpoints for application and service management.

Available endpoints:
- `GET /` - Application status
- `GET /services` - List registered services
- `POST /services/{service_name}/start` - Start a service
- `POST /services/{service_name}/stop` - Stop a service

#### 4. Models (`models.py`)
Core data models and enums for the application.

```python
from processpype.core.models import ServiceState

# Available states
ServiceState.STOPPED
ServiceState.STARTING
ServiceState.RUNNING
ServiceState.STOPPING
ServiceState.ERROR
```

#### 5. Configuration (`config/`)
Handles application and service configuration management using Pydantic models.

## Implementing New Services

### 1. Basic Service Structure

```python
from processpype.core.service import Service
from processpype.core.models import ServiceState

class MyService(Service):
    def __init__(self, name: str | None = None):
        super().__init__(name or "my_service")

    async def start(self) -> None:
        self.set_state(ServiceState.STARTING)
        # Initialize your service
        self.set_state(ServiceState.RUNNING)

    async def stop(self) -> None:
        self.set_state(ServiceState.STOPPING)
        # Cleanup resources
        self.set_state(ServiceState.STOPPED)
```

### 2. Adding Configuration

```python
from pydantic import BaseModel
from processpype.core.config.models import ServiceConfiguration

class MyServiceConfig(ServiceConfiguration):
    custom_field: str
    port: int = 8080

class MyService(Service):
    def configure(self, config: MyServiceConfig) -> None:
        self._config = config
        # Apply configuration
```

### 3. Adding API Routes

```python
from fastapi import APIRouter

class MyService(Service):
    def __init__(self, name: str | None = None):
        super().__init__(name or "my_service")
        self._router = APIRouter(prefix=f"/services/{self.name}")
        self._setup_routes()

    def _setup_routes(self) -> None:
        @self._router.get("/status")
        async def get_status():
            return {"state": self.state}
```

### 4. Error Handling

```python
from processpype.core.models import ServiceState

class MyService(Service):
    async def start(self) -> None:
        try:
            self.set_state(ServiceState.STARTING)
            # Initialize
            self.set_state(ServiceState.RUNNING)
        except Exception as e:
            self.set_error(str(e))
            self.set_state(ServiceState.ERROR)
            raise
```

## Service Lifecycle

1. **Registration**
```python
app = await Application.create("config.yaml")
service = app.register_service(MyService)
```

2. **Configuration**
```yaml
# config.yaml
services:
  my_service:
    enabled: true
    custom_field: "value"
    port: 8080
```

3. **Startup**
- Service state transitions: STOPPED → STARTING → RUNNING
- Configuration is applied
- Resources are initialized
- API routes are registered

4. **Runtime**
- Service handles requests
- Maintains state
- Reports health status

5. **Shutdown**
- Service state transitions: RUNNING → STOPPING → STOPPED
- Resources are cleaned up
- API routes are unregistered

## Best Practices

1. **State Management**
- Always use `set_state()` for state transitions
- Handle errors appropriately with `set_error()`
- Check state before operations

2. **Configuration**
- Use Pydantic models for configuration
- Provide sensible defaults
- Validate configuration in `configure()`

3. **Resource Management**
- Initialize resources in `start()`
- Clean up resources in `stop()`
- Use async context managers when possible

4. **Error Handling**
- Catch and handle exceptions appropriately
- Set service state to ERROR on failures
- Provide meaningful error messages

5. **API Design**
- Use FastAPI best practices
- Prefix routes with service name
- Provide OpenAPI documentation

## Logging

The framework uses structured logging via `logfire.py`:

```python
from processpype.core.logfire import get_service_logger

class MyService(Service):
    def __init__(self, name: str | None = None):
        super().__init__(name or "my_service")
        self.logger = get_service_logger(self.name)

    async def start(self) -> None:
        self.logger.info("Starting service", extra={"config": self.config.model_dump()})
```

## Testing Services

1. **Unit Tests**
```python
async def test_my_service():
    service = MyService()
    await service.start()
    assert service.state == ServiceState.RUNNING
    await service.stop()
    assert service.state == ServiceState.STOPPED
```

2. **Integration Tests**
```python
from fastapi.testclient import TestClient

async def test_my_service_api():
    app = await Application.create()
    service = app.register_service(MyService)
    client = TestClient(app.api)

    response = client.get("/services/my_service/status")
    assert response.status_code == 200
```

