Skip to main content

Python SDK for OperRouter - DataSource and LLM operations

Project description

py-operrouter

Python SDK for OperRouter - A unified SDK for DataSource and LLM operations with multiple transport options.

Features

  • โœ… Three Transport Layers: HTTP (JSON-RPC), gRPC (Protobuf), FFI (Direct Rust calls)
  • ๐Ÿ”Œ DataSource Support: PostgreSQL, MySQL, MongoDB, Redis, Kafka
  • ๐Ÿค– LLM Integration: OpenAI, Claude, Ollama
  • โšก Async/Await: Full async support with type hints
  • ๐Ÿ›ก๏ธ Type Safe: Complete type definitions with dataclasses
  • ๐Ÿ“ฆ Zero Dependencies: FFI client uses only Python stdlib (ctypes)

Installation

Basic Installation

# Install from source
cd sdks/py-operrouter
pip install -e .

Dependencies

  • HTTP Client: Requires httpx>=0.24.0
  • gRPC Client: Requires grpcio>=1.50.0, protobuf>=4.21.0
  • FFI Client: No external dependencies (uses ctypes)
# Install with all transport layers
pip install -e ".[http,grpc]"

# Or install individually
pip install httpx  # For HTTP client
pip install grpcio protobuf  # For gRPC client

Building FFI Library (for FFI Client)

cd ../../bridges/operrouter-core-ffi
cargo build --release

The FFI client will automatically search for the library in common locations. You can also set OPERROUTER_FFI_PATH to specify the library path.

Quick Start

HTTP Client (JSON-RPC)

import asyncio
from py_operrouter import HTTPClient, DataSourceConfig

async def main():
    # Create HTTP client
    client = HTTPClient("http://localhost:8080")
    
    # Test connection
    ping_resp = await client.ping()
    print(f"Server alive: {ping_resp.success}")
    
    # Create datasource
    config = DataSourceConfig(
        driver="postgres",
        host="localhost",
        port=5432,
        database="mydb",
        username="user",
        password="pass"
    )
    
    create_resp = await client.create_datasource("my_db", config)
    
    # Query data
    query_resp = await client.query_datasource("my_db", "SELECT * FROM users")
    print(f"Found {len(query_resp.rows)} rows")
    
    # Close connection
    await client.close_datasource("my_db")

asyncio.run(main())

gRPC Client (High Performance)

import asyncio
from py_operrouter import GRPCClient, LLMConfig, ChatMessage

async def main():
    # Create gRPC client
    client = GRPCClient("localhost:50051")
    
    try:
        # Create LLM instance
        config = LLMConfig(
            provider="openai",
            model="gpt-3.5-turbo",
            api_key="sk-..."
        )
        
        await client.create_llm("my_llm", config)
        
        # Chat with LLM
        messages = [
            ChatMessage(role="system", content="You are helpful."),
            ChatMessage(role="user", content="Hello!")
        ]
        
        chat_resp = await client.chat_llm("my_llm", messages)
        print(f"Response: {chat_resp.text}")
        
        # Cleanup
        await client.close_llm("my_llm")
    
    finally:
        # Always close gRPC channel
        await client.close()

asyncio.run(main())

FFI Client (Direct Rust Calls - Zero Overhead)

import asyncio
from py_operrouter import FFIClient, DataSourceConfig

async def main():
    # Create FFI client (no network, direct Rust calls)
    client = FFIClient()
    
    # Test FFI connection
    ping_resp = await client.ping()
    print(f"FFI core alive: {ping_resp.success}")
    
    # Create MongoDB datasource
    config = DataSourceConfig(
        driver="mongodb",
        host="localhost",
        port=27017,
        database="testdb"
    )
    
    await client.create_datasource("my_mongo", config)
    
    # Query MongoDB
    query_resp = await client.query_datasource(
        "my_mongo",
        '{"find": "users", "limit": 10}'
    )
    
    print(f"Found {len(query_resp.rows)} documents")

asyncio.run(main())

API Reference

Client Classes

All three clients implement the same OperRouterClient protocol:

  • HTTPClient(base_url: str) - JSON-RPC 2.0 over HTTP
  • GRPCClient(address: str) - gRPC with Protobuf
  • FFIClient(lib_path: Optional[str] = None) - Direct Rust FFI calls

Core Methods

# Test connection
await client.ping() -> PingResponse

# Validate TOML config
await client.validate_config(config_str: str) -> ConfigResponse

# Load operator config
await client.load_config(config_str: str) -> ConfigResponse

# Get metadata
await client.get_metadata(name: str) -> Metadata

DataSource Methods

# Create datasource
await client.create_datasource(
    name: str,
    config: DataSourceConfig
) -> DataSourceResponse

# Query (SELECT)
await client.query_datasource(
    name: str,
    query: str
) -> DataSourceQueryResponse

# Execute (DDL/DML)
await client.execute_datasource(
    name: str,
    statement: str
) -> DataSourceResponse

# Insert row
await client.insert_datasource(
    name: str,
    data: Dict[str, Any]
) -> DataSourceResponse

# Check health
await client.ping_datasource(name: str) -> DataSourceResponse

# Close connection
await client.close_datasource(name: str) -> DataSourceResponse

LLM Methods

# Create LLM instance
await client.create_llm(
    name: str,
    config: LLMConfig
) -> LLMResponse

# Generate completion
await client.generate_llm(
    name: str,
    prompt: str
) -> LLMGenerateResponse

# Chat conversation
await client.chat_llm(
    name: str,
    messages: List[ChatMessage]
) -> LLMChatResponse

# Get embeddings
await client.embedding_llm(
    name: str,
    text: str
) -> LLMEmbeddingResponse

# Check health
await client.ping_llm(name: str) -> LLMResponse

# Close instance
await client.close_llm(name: str) -> LLMResponse

Configuration Types

DataSource Configuration

from py_operrouter import DataSourceConfig

config = DataSourceConfig(
    driver="postgres",      # postgres, mysql, mongodb, redis, kafka
    host="localhost",       # Database host
    port=5432,             # Database port
    database="mydb",       # Database name
    username="user",       # Optional username
    password="pass",       # Optional password
    options={}             # Optional driver-specific options
)

LLM Configuration

from py_operrouter import LLMConfig

config = LLMConfig(
    provider="openai",     # openai, claude, ollama
    model="gpt-3.5-turbo", # Model name
    api_key="sk-...",      # API key (not needed for Ollama)
    base_url=None,         # Optional custom endpoint
    options={}             # Optional provider-specific options
)

Chat Messages

from py_operrouter import ChatMessage

messages = [
    ChatMessage(role="system", content="You are helpful."),
    ChatMessage(role="user", content="Hello!"),
    ChatMessage(role="assistant", content="Hi there!"),
]

Transport Comparison

Feature HTTP gRPC FFI
Protocol JSON-RPC 2.0 Protobuf Direct calls
Performance Good Better Best
Network Required Required Not needed
Setup Easiest Moderate Complex
Use Case Web services Microservices Embedded/CLI
Streaming No Yes (future) No
Dependencies httpx grpcio, protobuf None

When to Use Each

  • HTTP Client: Best for web applications, REST APIs, simple integrations
  • gRPC Client: Best for microservices, high-performance RPC, future streaming support
  • FFI Client: Best for CLI tools, embedded systems, maximum performance

Examples

See the examples/ directory for complete working examples:

  • datasource_http.py - PostgreSQL operations via HTTP
  • datasource_grpc.py - MySQL operations via gRPC
  • datasource_ffi.py - MongoDB operations via FFI
  • llm_http.py - OpenAI integration via HTTP
  • llm_grpc.py - Claude integration via gRPC
  • llm_ffi.py - Ollama integration via FFI

Run any example:

# HTTP examples (requires server on localhost:8080)
python examples/datasource_http.py
export OPENAI_API_KEY='sk-...'
python examples/llm_http.py

# gRPC examples (requires server on localhost:50051)
python examples/datasource_grpc.py
export CLAUDE_API_KEY='sk-...'
python examples/llm_grpc.py

# FFI examples (requires built library, no server)
python examples/datasource_ffi.py
python examples/llm_ffi.py

Development

Running Tests

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=py_operrouter --cov-report=html

Code Quality

# Format code
black src/ examples/

# Type checking
mypy src/

# Linting
ruff check src/

Building

# Build wheel
python -m build

# Install locally
pip install dist/py_operrouter-*.whl

Troubleshooting

Import Errors

# Make sure SDK is installed
pip install -e .

# Verify installation
python -c "from py_operrouter import HTTPClient; print('OK')"

gRPC Proto Files Not Found

# Generate proto files
cd ../..
buf generate --path proto/operrouter.proto

# Verify proto files
ls sdks/py-operrouter/gen/proto/operrouter_pb2.py

FFI Library Not Found

# Build FFI library
cd ../../bridges/operrouter-core-ffi
cargo build --release

# Or set library path
export OPERROUTER_FFI_PATH="/path/to/liboperrouter_core_ffi.so"

# Check library exists
ls ../../bridges/operrouter-core-ffi/target/release/liboperrouter_core_ffi.*

Server Connection Errors

# Start HTTP server
cd ../../bridges/operrouter-core-http
cargo run --release  # Runs on :8080

# Start gRPC server
cd ../../bridges/operrouter-core-grpc
cargo run --release  # Runs on :50051

Architecture

py-operrouter/
โ”œโ”€โ”€ src/py_operrouter/
โ”‚   โ”œโ”€โ”€ __init__.py          # Main exports
โ”‚   โ”œโ”€โ”€ types.py             # Type definitions (10 dataclasses)
โ”‚   โ””โ”€โ”€ client/
โ”‚       โ”œโ”€โ”€ __init__.py      # Client exports
โ”‚       โ”œโ”€โ”€ http_client.py   # HTTP JSON-RPC client (310 lines)
โ”‚       โ”œโ”€โ”€ grpc_client.py   # gRPC Protobuf client (420 lines)
โ”‚       โ””โ”€โ”€ ffi_client.py    # FFI ctypes client (420 lines)
โ”œโ”€โ”€ examples/
โ”‚   โ”œโ”€โ”€ README.md            # Examples documentation
โ”‚   โ”œโ”€โ”€ datasource_http.py   # HTTP DataSource demo
โ”‚   โ”œโ”€โ”€ datasource_grpc.py   # gRPC DataSource demo
โ”‚   โ”œโ”€โ”€ datasource_ffi.py    # FFI DataSource demo
โ”‚   โ”œโ”€โ”€ llm_http.py          # HTTP LLM demo
โ”‚   โ”œโ”€โ”€ llm_grpc.py          # gRPC LLM demo
โ”‚   โ””โ”€โ”€ llm_ffi.py           # FFI LLM demo
โ”œโ”€โ”€ gen/proto/               # Generated protobuf files
โ”œโ”€โ”€ pyproject.toml           # Modern Python packaging
โ””โ”€โ”€ README.md                # This file

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for new features
  4. Ensure code passes black, mypy, and ruff
  5. Submit a pull request

License

See the main repository LICENSE file.

Related Projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_operrouter-0.1.0.tar.gz (33.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_operrouter-0.1.0-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file py_operrouter-0.1.0.tar.gz.

File metadata

  • Download URL: py_operrouter-0.1.0.tar.gz
  • Upload date:
  • Size: 33.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for py_operrouter-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9a3d182100e63fede8330598bebb4a3c2cfb99812426940873be0599d473e78d
MD5 fa89fd94c3a93d736c26b97b64b5ffd9
BLAKE2b-256 b002b3da8d5e258dc0eae6111c711e955888403e767f89cbad08c2688a12d42e

See more details on using hashes here.

Provenance

The following attestation bundles were made for py_operrouter-0.1.0.tar.gz:

Publisher: python-publish.yml on operrouter/py-operrouter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file py_operrouter-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: py_operrouter-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for py_operrouter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90b8b86d34ad17857abfe50afba3592cd7be7d50fe572ae0ff255714d45ef067
MD5 8128324a1efe3f5a70ac24778deb9509
BLAKE2b-256 e1ea23c61443add1432e581537d45150bb3c4e438b0124e6dcea29a6288a7221

See more details on using hashes here.

Provenance

The following attestation bundles were made for py_operrouter-0.1.0-py3-none-any.whl:

Publisher: python-publish.yml on operrouter/py-operrouter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page