CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-cyclopts

Intuitive, easy CLIs based on type hints.

Pending
Overview
Eval results
Files

advanced-features.mddocs/

Advanced Features

Extended functionality including interactive editing, token manipulation, custom dispatching, and help system customization.

Capabilities

Interactive Text Editing

Launch external text editors for interactive input.

def edit(
    text: str = "",
    editor: str | None = None,
    suffix: str = ".txt",
    require_save: bool = True,
    require_change: bool = False
) -> str:
    """
    Launch text editor for interactive editing.
    
    Parameters
    ----------
    text
        Initial text content for editor
    editor
        Editor command to use. If None, uses $EDITOR environment variable
    suffix
        File suffix for temporary file
    require_save
        Whether user must save the file
    require_change
        Whether user must change the content
        
    Returns
    -------
    str
        Edited text content
        
    Raises
    ------
    EditorNotFoundError
        If no editor is available
    EditorDidNotSaveError
        If user didn't save and require_save=True
    EditorDidNotChangeError
        If user didn't change content and require_change=True
    """

Token Utilities

Utilities for working with command-line tokens and parsing.

def env_var_split(value: str, type_: type) -> list[str]:
    """
    Split environment variable value based on target type.
    
    Parameters
    ----------
    value
        Environment variable string value
    type_
        Target type that determines splitting behavior
        
    Returns
    -------
    list[str]
        List of string tokens for conversion
    """

def default_name_transform(name: str) -> str:
    """
    Convert Python identifier to CLI token format.
    
    Parameters
    ----------
    name
        Python identifier (e.g., "my_parameter")
        
    Returns
    -------
    str
        CLI token format (e.g., "--my-parameter")
    """

UNSET: object
"""Sentinel value indicating no data provided."""

Help System Customization

Rich panel creation for custom help and error display.

def CycloptsPanel(
    content: str,
    *,
    title: str | None = None,
    border_style: str = "red",
    padding: tuple[int, int] = (0, 1),
    **kwargs
) -> Panel:
    """
    Create Rich panel for Cyclopts help and error display.
    
    Parameters
    ----------
    content
        Panel content text
    title
        Panel title
    border_style
        Rich border style name
    padding
        Panel padding (vertical, horizontal)
    **kwargs
        Additional Rich Panel parameters
        
    Returns
    -------
    Panel
        Rich Panel object for display
    """

Custom Dispatching Protocol

Protocol for implementing custom command dispatching logic.

class Dispatcher:
    def __call__(
        self,
        command: Callable[..., Any],
        bound: inspect.BoundArguments,
        ignored: dict[str, Any],
        /
    ) -> Any:
        """
        Custom dispatcher protocol for command execution.
        
        Parameters
        ----------
        command
            Function to dispatch/execute
        bound
            Bound arguments from parsing
        ignored
            Ignored/unused arguments
            
        Returns
        -------
        Any
            Result of function execution
        """

Advanced App Configuration

Extended configuration options for App customization.

class CycloptsConfig:
    def __init__(
        self,
        *,
        console: Console | None = None,
        show: bool = True,
        group: Group | None = None,
        name: str | tuple[str, ...] | None = None,
        help: str | None = None,
        negative: str | Iterable[str] | None = None,
        converter: Callable | None = None,
        validator: Callable | list[Callable] | None = None,
        env_var: str | Iterable[str] | None = None,
        **kwargs
    ):
        """
        Advanced configuration options for Cyclopts components.
        
        Parameters
        ----------
        console
            Rich console for output
        show
            Whether to show in help
        group
            Grouping configuration
        name
            Name override
        help
            Help text
        negative
            Negative flag names
        converter
            Custom converter function
        validator
            Validation functions
        env_var
            Environment variable names
        """

Interactive Shell Mode

Start interactive shell for applications.

def interactive_shell(app: App) -> None:
    """
    Start interactive shell mode for an application.
    
    Parameters
    ----------
    app
        App instance to run in interactive mode
    """

Version Handling

Flexible version display and management.

def version_print(app: App) -> None:
    """
    Print application version information.
    
    Parameters
    ----------
    app
        App instance with version information
    """

def resolve_version_format(version: str | Callable[[], str]) -> str:
    """
    Resolve version string from string or callable.
    
    Parameters
    ----------
    version
        Version string or callable that returns version
        
    Returns
    -------
    str
        Resolved version string
    """

Usage Examples

Interactive Text Editing

from cyclopts import App, edit

app = App()

@app.command
def create_message():
    """Create a message using text editor."""
    content = edit(
        text="# Enter your message here\n",
        suffix=".md",
        require_change=True
    )
    print("Message created:")
    print(content)

@app.command
def edit_config():
    """Edit configuration interactively."""
    current_config = '{"timeout": 30, "retries": 3}'
    new_config = edit(
        text=current_config,
        suffix=".json",
        require_save=True
    )
    print("Updated configuration:")
    print(new_config)

Custom Dispatcher

from cyclopts import App
from cyclopts.protocols import Dispatcher
import asyncio
import inspect

class AsyncDispatcher:
    """Custom dispatcher that handles async functions."""
    
    def __call__(self, func, bound_arguments, app):
        if inspect.iscoroutinefunction(func):
            return asyncio.run(func(*bound_arguments.args, **bound_arguments.kwargs))
        else:
            return func(*bound_arguments.args, **bound_arguments.kwargs)

app = App(dispatcher=AsyncDispatcher())

@app.command
async def async_task(duration: int = 5):
    """Run an async task."""
    print(f"Starting async task for {duration} seconds...")
    await asyncio.sleep(duration)
    print("Async task completed!")

Rich Help Customization

from cyclopts import App, CycloptsPanel, Group
from rich.panel import Panel

# Custom group with panel styling
custom_group = Group(
    "advanced",
    "Advanced Options",
    "Advanced configuration and debugging options",
    panel=Panel.fit("Advanced Settings", border_style="blue")
)

app = App(group_parameters=custom_group)

@app.command
def deploy(
    service: str,
    debug: bool = False,
    dry_run: bool = False
):
    """Deploy service with custom help styling."""
    if debug:
        print("Debug mode enabled")
    if dry_run:
        print("Dry run mode - no actual deployment")
    print(f"Deploying {service}")

Interactive Shell Mode

from cyclopts import App

app = App(name="myshell")

@app.command
def status():
    """Show system status."""
    print("System is running")

@app.command  
def restart():
    """Restart the system."""
    print("Restarting...")

@app.command
def shell():
    """Start interactive shell."""
    app.interactive_shell()

if __name__ == "__main__":
    app()

Environment Variable Integration

from cyclopts import App, env_var_split
import os

app = App()

@app.command
def process_files():
    """Process files from environment variable."""
    file_list_env = os.getenv("FILE_LIST", "")
    if file_list_env:
        files = env_var_split(file_list_env, list[str])
        print(f"Processing {len(files)} files:")
        for file in files:
            print(f"  - {file}")
    else:
        print("No files specified in FILE_LIST environment variable")

# Usage: FILE_LIST="file1.txt,file2.txt,file3.txt" python script.py process-files

Custom Name Transformation

from cyclopts import App

def custom_name_transform(name: str) -> str:
    """Transform Python names to UPPERCASE CLI names."""
    return f"--{name.upper().replace('_', '-')}"

app = App(name_transform=custom_name_transform)

@app.command
def process_data(
    input_file: str,
    max_workers: int = 4,
    enable_caching: bool = False
):
    """Process data with custom name transformation."""
    # CLI will have --INPUT-FILE, --MAX-WORKERS, --ENABLE-CACHING
    print(f"Processing {input_file} with {max_workers} workers")
    if enable_caching:
        print("Caching enabled")

Install with Tessl CLI

npx tessl i tessl/pypi-cyclopts

docs

advanced-features.md

arguments-parameters.md

configuration.md

core-app.md

exceptions.md

index.md

types-validation.md

tile.json