Skip to main content

Add your description here

Project description

ctrlstack

A Python framework for creating unified controller interfaces that can be exposed as both CLI applications and FastAPI web services.

Define your business logic once in a Controller class, and automatically generate both command-line tools and REST APIs from the same codebase.

Features

  • Single Source of Truth: Define methods once, get CLI and API automatically
  • Type Safety: Full Pydantic integration for request/response validation
  • Async Support: Native async/await support for both CLI and web endpoints
  • Flexible Routing: Organize methods into logical groups
  • Remote Controllers: Client-side proxies for seamless remote API calls
  • Authentication: Built-in API key authentication support

Quick Start

Installation

pip install ctrlstack

Basic Example

from ctrlstack import Controller, ctrl_cmd_method, ctrl_query_method
from ctrlstack.server import create_ctrl_server
from ctrlstack.cli import create_ctrl_cli

class MyController(Controller):
    @ctrl_query_method
    def get_status(self) -> str:
        return "Service is running"
    
    @ctrl_cmd_method  
    async def send_message(self, message: str) -> str:
        return f"Received: {message}"

# Create FastAPI app
server_app = create_ctrl_server(MyController())

# Create CLI app  
cli_app = create_ctrl_cli(MyController())

if __name__ == "__main__":
    cli_app()

This creates:

CLI Usage:

python app.py get-status
# Output: Service is running

python app.py send-message "Hello World"  
# Output: Received: Hello World

API Endpoints:

  • GET /query/get_status → Returns status
  • POST /cmd/send_message → Accepts JSON body with message

Remote Controller

Access your API as if it were a local controller:

from ctrlstack.remote_controller import get_remote_controller

# Create remote controller client
remote_ctrl = get_remote_controller(
    MyController, 
    url="http://localhost:8000",
    api_key="your-api-key"
)

# Use exactly like local controller
status = await remote_ctrl.get_status()
result = await remote_ctrl.send_message(Message(text="Hello from remote!"))

Dynamic Controller Building

from ctrlstack.controller_app import ControllerApp

capp = ControllerApp()

@capp.register_query()
async def health_check() -> dict:
    return {"status": "healthy", "timestamp": "2024-01-01T00:00:00Z"}

@capp.register_cmd()
async def process_data(data: dict) -> str:
    return f"Processed {len(data)} items"

# Get FastAPI server
server_app = capp.get_server_app(api_keys=["secret-key"])

# Get CLI app
cli_app = capp.get_cli_app()

Method Types

  • @ctrl_query_method: GET endpoints, read-only operations
  • @ctrl_cmd_method: POST endpoints, state-changing operations
  • @ctrl_method(type, group): Custom method type and group

Advanced Features

Custom Routing Groups

from ctrlstack import ControllerMethodType, ctrl_method

class AdminController(Controller):
    @ctrl_method(ControllerMethodType.COMMAND, "admin")
    def reset_database(self) -> str:
        return "Database reset"
    
    @ctrl_method(ControllerMethodType.QUERY, "admin")  
    def get_metrics(self) -> dict:
        return {"users": 100, "posts": 500}

# Creates routes: /admin/reset_database, /admin/get_metrics

Authentication

# Server with API key authentication
app = create_ctrl_server(
    MyController(), 
    api_keys=["secret-key-1", "secret-key-2"]
)

# Clients must include: X-API-Key: secret-key-1

Development

Prerequisites

  • Install uv.
  • Install direnv to automatically load the project virtual environment when entering it.
    • Mac: brew install direnv
    • Linux: curl -sfL https://direnv.net/install.sh | bash

Setting up the environment

Run the following:

# In the root of the repo folder
uv sync --all-extras # Installs the virtual environment at './.venv'
direnv allow # Allows the automatic running of the script './.envrc'
nbl install-hooks # Installs a git hooks that ensures that notebooks are added properly

You are now set up to develop the codebase.

Further instructions:

  • To export notebooks run nbl export.
  • To clean notebooks run nbl clean.
  • To see other available commands run just nbl.
  • To add a new dependency run uv add package-name. See the the uv documentation for more details.
  • You need to git add all 'twinned' notebooks for the commit to be validated by the git-hook. For example, if you add nbs/my-nb.ipynb, you must also add pts/my-nb.pct.py.
  • To render the documentation, run nbl render-docs. To preview it run nbl preview-docs
  • To upgrade all dependencies run uv sync --upgrade --all-extras

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

ctrlstack-0.1.0.tar.gz (10.1 kB view details)

Uploaded Source

Built Distribution

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

ctrlstack-0.1.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ctrlstack-0.1.0.tar.gz
  • Upload date:
  • Size: 10.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.11

File hashes

Hashes for ctrlstack-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3d7be526203a0e9f76811fb4f04c6e81482adcb929fa98d9a77f94ec9f0282d0
MD5 4d49b09d6f0ace4e0607d57674b997da
BLAKE2b-256 c9c8a1d3e5730151910cfd7bee37d74fe84b54f4044018c5ac599e1eb3ad1133

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ctrlstack-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.11

File hashes

Hashes for ctrlstack-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0b792f4c5607e566dedd7cfe2cac03505153a7035bef776ad0ab8c4a49a55732
MD5 955b75e0b49a4047d13d5b5a365ac00f
BLAKE2b-256 38ba814b4ffb7359896d8c0d77d2e948d933eff732b82a932f7dcf2002eeff30

See more details on using hashes here.

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