Metadata-Version: 2.4
Name: python-hookups
Version: 0.1.0
Summary: A generic, type-safe hook and signal system for Python projects with Pydantic validation.
Project-URL: Homepage, https://github.com/rzk.ssr/python-hookups
Project-URL: Repository, https://github.com/rzk.ssr/python-hookups
Project-URL: Documentation, https://github.com/rzk.ssr/python-hookups#readme
Project-URL: Issues, https://github.com/rzk.ssr/python-hookups/issues
Author-email: Sasri <sasri.develop@gmail.com>
License: MIT
Keywords: events,hooks,plugins,pydantic,signals
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Requires-Dist: pydantic>=2.0.0
Description-Content-Type: text/markdown

# Python Hookups

A generic, type-safe hook and signal system for Python projects. It supports automatic discovery of extension points (hooks) and event-driven signals with both synchronous and asynchronous support.

## Features

-   **Type-safe Hooks**: Register functions with specific names and execution orders.
-   **Professional Signals**: Standalone signal implementation with `sync` and `async` sending.
-   **Automatic Discovery**: Automatically finds and imports `hookups` submodules in your packages.
-   **CLI Support**: Inspect registered hooks and signals from the command line.
-   **Modern Python**: Built with Python 3.12+, Pydantic validation, and `uv` package management.

## Installation

```bash
# Using uv (recommended)
uv add python-hookups

# Using pip
pip install python-hookups
```

## Usage

### 1. Hook System

Hooks are used when you want to allow other parts of your application (or plugins) to provide values or execute logic at specific points.

#### Registration

```python
from hookups import register_hookup

@register_hookup("UI_MENU_HOOKUP", order=10)
def my_menu_item():
    return {"label": "My Plugin", "url": "/plugin"}
```

#### Discovery and Execution

```python
from hookups import set_scan_paths, discover_hookups, get_hookups

# 1. Configure where to look for 'hookups' submodules
set_scan_paths(["my_app.plugins", "my_app.extensions"])

# 2. Discover and load all hookups
discover_hookups()

# 3. Get and execute hooks
hooks = get_hookups("UI_MENU_HOOKUP")
for hook in hooks:
    result = hook()
    print(result)
```

### 2. Signal System

Signals are used for "fire-and-forget" events. They support both synchronous and asynchronous receivers.

#### Definition

```python
from hookups import Signal

user_registered = Signal(name="user_registered")
```

#### Connection

```python
from hookups import receiver

@receiver(user_registered)
async def send_welcome_email(sender, username, **kwargs):
    print(f"Sending welcome email to {username}...")

@receiver(user_registered)
def log_registration(sender, username, **kwargs):
    print(f"Audit log: {username} joined.")
```

#### Sending

```python
# Asynchronous sending (handles both sync and async receivers)
await user_registered.send_async(sender=None, username="Alice")

# Synchronous sending (for sync-only contexts)
user_registered.send(sender=None, username="Alice")

# Robust sending (continues even if receivers raise exceptions)
await user_registered.send_async_robust(sender=None, username="Alice")
```

## CLI Usage

You can list all registered hooks and signals using the built-in CLI.

```bash
# List all registered hooks
python main.py --list hooks

# List all registered signals and their receivers
python main.py --list signals
```

## Example Project

Check out the `example/` directory for a complete working demonstration of how to structure a project with plugins using `python-hookups`.

```bash
uv run python example/app.py
```

## Development

```bash
# Run tests
uv run pytest

# Run tests with coverage
uv run pytest --cov=hookups
```
