Metadata-Version: 2.1
Name: signalr-zero
Version: 1.0.0
Summary: Zero-dependency Python SignalR JSON hub client — pure stdlib, mTLS/PFX, auto-reconnect
Author-email: Abhishek Kumar <ipsabhi423@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/Abhishek-Kumar/signalr-zero
Project-URL: Repository, https://github.com/Abhishek-Kumar/signalr-zero
Project-URL: Issues, https://github.com/Abhishek-Kumar/signalr-zero/issues
Keywords: signalr,websocket,realtime,hub,aspnetcore,financial,trading,market-data,mtls,pfx
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
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: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# signalr-zero

**Zero-dependency Python SignalR JSON hub client.**  
Pure stdlib · mTLS / PFX support · Auto-reconnect · Thread-safe · Python 3.8+

```
pip install signalr-zero
```

[![PyPI version](https://img.shields.io/pypi/v/signalr-zero)](https://pypi.org/project/signalr-zero/)
[![Python](https://img.shields.io/pypi/pyversions/signalr-zero)](https://pypi.org/project/signalr-zero/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

---

## Why signalr-zero?

| Feature | signalr-zero | Other libraries |
|---|---|---|
| External pip dependencies | **0** | 3 – 8 |
| PFX / PKCS12 mTLS | ✅ built-in | ❌ manual |
| Auto-reconnect | ✅ | partial |
| Thread-safe sends | ✅ | varies |
| Python 3.8 – 3.12 | ✅ | varies |
| Zero C extensions | ✅ | varies |

---

## Quick Start

```python
from signalr_zero import SignalRClient

client = SignalRClient(
    url     = "https://hub.example.com",
    hub     = "/events",
    api_key = "YOUR-API-KEY",
)

@client.on("OnMessage")
def handle(data: dict) -> None:
    print(data)

client.run()    # blocks — Ctrl-C to stop
```

---

## With mTLS (PFX / PKCS12 certificate)

For enterprise APIs that require mutual TLS authentication:

```python
from signalr_zero import SignalRClient

client = SignalRClient(
    url          = "https://api.example.com/service",
    hub          = "/hub",
    api_key      = "YOUR-API-KEY",
    pfx_path     = "/path/to/client.pfx",
    pfx_password = "pfx-passphrase",
    subscribe    = "Subscribe",       # hub method to invoke after connect
    subscribe_args = [],              # arguments for the subscribe call
)

@client.on("OnData")
def on_data(data: dict) -> None:
    print(f"Received: {data}")

@client.on_connect
def connected() -> None:
    print("Connected!")

@client.on_disconnect
def disconnected() -> None:
    print("Disconnected — will auto-reconnect…")

client.run()
```

> **Windows note:** Use a raw string or forward slashes for `pfx_path`:
> ```python
> pfx_path = r"C:\certs\client.pfx"      # raw string  ✅
> pfx_path = "C:/certs/client.pfx"       # forward slash ✅
> pfx_path = "C:\certs\client.pfx"       # backslash — DON'T ❌
> ```

---

## With PEM files (alternative to PFX)

```python
client = SignalRClient(
    url      = "https://api.example.com/service",
    hub      = "/hub",
    cert_pem = "/path/to/client.crt",
    key_pem  = "/path/to/client.key",
)
```

---

## Stop from another thread

```python
import threading, time

def stop_after(seconds):
    time.sleep(seconds)
    client.stop()

threading.Thread(target=stop_after, args=(30,), daemon=True).start()
client.run()
```

---

## Send a hub invocation

```python
@client.on_connect
def on_connected():
    client.invoke("SendMessage", ["hello", "world"])
```

---

## Enable logging

```python
import logging
logging.basicConfig(level=logging.INFO)   # or DEBUG for raw frames
```

---

## All Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `url` | `str` | **required** | Base server URL (`https://` or `http://`) |
| `hub` | `str` | **required** | Hub route, e.g. `/notifier` |
| `api_key` | `str` | `""` | Sent as `X-API-Key` + `Authorization: Bearer` |
| `pfx_path` | `str` | `None` | Path to `.pfx` / `.p12` for mTLS |
| `pfx_password` | `str` | `None` | PFX passphrase |
| `cert_pem` | `str` | `None` | PEM cert path (alternative to pfx) |
| `key_pem` | `str` | `None` | PEM key path (alternative to pfx) |
| `subscribe` | `str` | `None` | Hub method to invoke after connecting |
| `subscribe_args` | `list` | `[]` | Arguments for the subscribe invocation |
| `reconnect` | `bool` | `True` | Auto-reconnect on disconnect |
| `reconnect_delay` | `float` | `5.0` | Seconds between reconnect attempts |
| `ping_interval` | `float` | `20.0` | Keep-alive ping interval (seconds) |
| `timeout` | `float` | `60.0` | Socket timeout (seconds) |
| `verify_ssl` | `bool` | `False` | Verify server TLS certificate |

---

## System Requirements

| Requirement | Detail |
|---|---|
| Python | 3.8+ |
| `openssl` CLI | Required **only** when using `pfx_path`. Pre-installed on Linux/macOS. Windows: [OpenSSL for Windows](https://slproweb.com/products/Win32OpenSSL.html) |

---

## How it works

`signalr-zero` implements the [ASP.NET Core SignalR JSON Hub Protocol](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md) from scratch using only Python's standard library:

1. **Negotiate** — `POST /hub/negotiate` to get a connection token
2. **WebSocket** — RFC 6455 WebSocket upgrade (pure stdlib)
3. **Handshake** — `{"protocol":"json","version":1}` → server ACK
4. **Subscribe** — optional hub method invocation
5. **Receive loop** — dispatches messages to `@client.on()` handlers
6. **Ping loop** — background thread sends keep-alive pings
7. **Reconnect** — auto-reconnects with configurable delay

---

## License

MIT © [Abhishek Kumar](mailto:ipsabhi423@gmail.com)
