CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-cleo

Cleo allows you to create beautiful and testable command-line interfaces.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

commands.mddocs/

Command Development System

The command development system provides the foundation for creating individual CLI commands with arguments, options, and business logic. Commands inherit from base classes and define their interface through class attributes and method implementations.

Capabilities

Base Command Structure

Abstract base class that defines the fundamental command interface and lifecycle.

class BaseCommand:
    name: str | None = None           # Command name (required)
    description: str = ""             # Short description for help
    help: str = ""                   # Detailed help text
    enabled: bool = True             # Whether command is enabled
    hidden: bool = False             # Whether to hide from command lists
    
    def configure(self) -> None:
        """Configure the command definition. Called during initialization."""
    
    def execute(self, io: IO) -> int:
        """
        Execute the command with provided IO.
        
        Args:
            io (IO): Input/output interface
            
        Returns:
            int: Exit code (0 for success)
        """
    
    def run(self, io: IO) -> int:
        """
        Run the command through the full lifecycle.
        
        Args:
            io (IO): Input/output interface
            
        Returns:
            int: Exit code from execution
        """

Full-Featured Command Class

Complete command implementation with UI helpers and convenience methods.

class Command(BaseCommand):
    arguments: ClassVar[list[Argument]] = []    # Command arguments definition
    options: ClassVar[list[Option]] = []        # Command options definition  
    aliases: ClassVar[list[str]] = []           # Command aliases
    usages: ClassVar[list[str]] = []            # Usage examples
    commands: ClassVar[list[BaseCommand]] = []  # Sub-commands
    
    def __init__(self) -> None: ...
    
    @property
    def io(self) -> IO:
        """Get the IO interface for this command."""
    
    def handle(self) -> int:
        """
        Command business logic implementation (abstract).
        
        Returns:
            int: Exit code (0 for success)
        """
        
    # Command execution methods
    def call(self, name: str, args: str | None = None) -> int: ...
    def call_silent(self, name: str, args: str | None = None) -> int: ...
    
    # User interaction methods  
    def confirm(self, question: str, default: bool = False, true_answer_regex: str = r"(?i)^y") -> bool: ...
    def ask(self, question: str | Question, default: Any | None = None) -> Any: ...
    def secret(self, question: str | Question, default: Any | None = None) -> Any: ...
    def choice(self, question: str, choices: list[str], default: Any | None = None, 
               attempts: int | None = None, multiple: bool = False) -> Any: ...
    
    # Output methods
    def write(self, text: str, style: str | None = None) -> None: ...
    def line_error(self, text: str, style: str | None = None, verbosity: Verbosity = Verbosity.NORMAL) -> None: ...
    def info(self, text: str) -> None: ...
    def comment(self, text: str) -> None: ...
    def question(self, text: str) -> None: ...
    def overwrite(self, text: str) -> None: ...
    
    # Table rendering
    def table(self, header: str | None = None, rows: Rows | None = None, style: str | None = None) -> Table: ...
    def table_separator(self) -> TableSeparator: ...
    def render_table(self, headers: str, rows: Rows, style: str | None = None) -> None: ...
    
    # Progress indicators
    def progress_bar(self, max: int = 0) -> ProgressBar: ...
    def progress_indicator(self, fmt: str | None = None, interval: int = 100, values: list[str] | None = None) -> ProgressIndicator: ...
    def spin(self, start_message: str, end_message: str, fmt: str | None = None, 
             interval: int = 100, values: list[str] | None = None) -> ContextManager[ProgressIndicator]: ...
    
    # Styling
    def add_style(self, name: str, fg: str | None = None, bg: str | None = None, options: list[str] | None = None) -> None: ...
    
    # Utility
    def create_question(self, question: str, type: Literal["choice", "confirmation"] | None = None, **kwargs: Any) -> Question: ...

Argument and Option Access

Access command arguments and options provided by the user.

def argument(self, name: str) -> Any:
    """
    Get an argument value by name.
    
    Args:
        name (str): Argument name
        
    Returns:
        Any: Argument value or None if not provided
    """

def option(self, name: str) -> Any:
    """
    Get an option value by name.
    
    Args:
        name (str): Option name
        
    Returns:
        Any: Option value, default value, or None
    """

Argument and Option Definition Helpers

Helper functions to create argument and option definitions for commands.

def argument(name: str, description: str | None = None, optional: bool = False, 
             multiple: bool = False, default: Any | None = None) -> Argument:
    """
    Create an argument definition.
    
    Args:
        name (str): Argument name
        description (str | None): Help description
        optional (bool): Whether argument is optional
        multiple (bool): Whether argument accepts multiple values
        default (Any | None): Default value for optional arguments
        
    Returns:
        Argument: Configured argument definition
    """

def option(long_name: str, short_name: str | None = None, description: str | None = None,
           flag: bool = True, value_required: bool = True, multiple: bool = False,
           default: Any | None = None) -> Option:
    """
    Create an option definition.
    
    Args:
        long_name (str): Long option name (--option)
        short_name (str | None): Short option name (-o)  
        description (str | None): Help description
        flag (bool): Whether this is a boolean flag
        value_required (bool): Whether option requires a value
        multiple (bool): Whether option accepts multiple values
        default (Any | None): Default value
        
    Returns:
        Option: Configured option definition
    """

Output and Interaction Methods

Methods for producing output and interacting with users.

def line(self, text: str, style: str | None = None, verbosity: Verbosity = Verbosity.NORMAL) -> None:
    """
    Write a line of text to output.
    
    Args:
        text (str): Text to output
        style (str | None): Style name for formatting
        verbosity (Verbosity | None): Minimum verbosity level
    """

def write(self, text: str, new_line: bool = False, verbosity: Verbosity | None = None) -> None:
    """
    Write text to output.
    
    Args:
        text (str): Text to output
        new_line (bool): Whether to add a newline
        verbosity (Verbosity | None): Minimum verbosity level
    """

def confirm(self, question: str, default: bool = False) -> bool:
    """
    Ask a yes/no confirmation question.
    
    Args:
        question (str): Question text
        default (bool): Default answer
        
    Returns:
        bool: User's answer
    """

def ask(self, question: str | Question, default: Any | None = None) -> Any:
    """
    Ask a question and get user input.
    
    Args:
        question (str | Question): Question text or Question object
        default (Any | None): Default answer
        
    Returns:
        Any: User's answer
    """

def choice(self, question: str, choices: list[str], default: Any | None = None) -> Any:
    """
    Ask a multiple choice question.
    
    Args:
        question (str): Question text
        choices (list[str]): Available choices
        default (Any | None): Default choice
        
    Returns:
        Any: Selected choice
    """

Command Execution and Control Flow

Methods for controlling command execution and calling other commands.

def call(self, command: str, args: str = "") -> int:
    """
    Call another command from this command.
    
    Args:
        command (str): Command name to call
        args (str): Arguments to pass to the command
        
    Returns:
        int: Exit code from called command
    """

def call_silent(self, command: str, args: str = "") -> int:
    """
    Call another command silently (suppressing output).
    
    Args:
        command (str): Command name to call
        args (str): Arguments to pass
        
    Returns:
        int: Exit code from called command
    """

Style and Formatting Methods

Methods for adding custom styles and formatting output.

def add_style(self, name: str, fg: str | None = None, bg: str | None = None, 
              options: list[str] | None = None) -> None:
    """
    Add a custom style for text formatting.
    
    Args:
        name (str): Style name
        fg (str | None): Foreground color
        bg (str | None): Background color
        options (list[str] | None): Formatting options (bold, underscore, etc.)
    """

Input Definition Components

Argument Class

Defines command arguments with validation and type information.

class Argument:
    def __init__(self, name: str, required: bool = True, is_list: bool = False,
                 description: str | None = None, default: Any | None = None): ...
    
    @property 
    def name(self) -> str: ...
    
    @property
    def is_required(self) -> bool: ...
    
    @property
    def is_optional(self) -> bool: ...
    
    @property
    def is_list(self) -> bool: ...
    
    @property
    def description(self) -> str: ...
    
    @property
    def default(self) -> Any: ...

Option Class

Defines command options with flags, values, and validation.

class Option:
    def __init__(self, name: str, shortcut: str | None = None, flag: bool = True,
                 requires_value: bool = True, is_list: bool = False,
                 description: str | None = None, default: Any | None = None): ...
    
    @property
    def name(self) -> str: ...
    
    @property
    def shortcut(self) -> str: ...
    
    @property
    def is_flag(self) -> bool: ...
    
    @property
    def requires_value(self) -> bool: ...
    
    @property
    def is_list(self) -> bool: ...
    
    @property
    def description(self) -> str: ...
    
    @property
    def default(self) -> Any: ...

Usage Examples

Basic Command

from cleo.commands.command import Command
from cleo.helpers import argument, option

class ProcessCommand(Command):
    name = "process"
    description = "Process data files"
    arguments = [
        argument("input_file", description="Input file path"),
        argument("output_file", description="Output file path", optional=True)
    ]
    options = [
        option("format", "f", description="Output format", flag=False, default="json"),
        option("verbose", "v", description="Verbose output", flag=True)
    ]
    
    def handle(self):
        input_file = self.argument("input_file")
        output_file = self.argument("output_file") or f"{input_file}.processed"
        format = self.option("format")
        verbose = self.option("verbose")
        
        if verbose:
            self.line(f"Processing <info>{input_file}</info>")
            
        # Process the file
        result = self.process_file(input_file, format)
        
        # Write output
        with open(output_file, 'w') as f:
            f.write(result)
            
        self.line(f"<comment>Processed data written to {output_file}</comment>")
        
        return 0
    
    def process_file(self, file_path, format):
        # Implementation here
        return "processed data"

Interactive Command with Questions

class ConfigCommand(Command):
    name = "config"
    description = "Configure application settings"
    
    def handle(self):
        # Get configuration values interactively
        host = self.ask("Database host", "localhost")
        port = self.ask("Database port", 5432)
        
        # Confirm settings
        if self.confirm(f"Connect to {host}:{port}?", True):
            # Multiple choice for environment
            env = self.choice(
                "Environment",
                ["development", "staging", "production"],
                "development"
            )
            
            self.line(f"<info>Configuration saved for {env} environment</info>")
        else:
            self.line("<error>Configuration cancelled</error>")
            return 1
            
        return 0

Command with Sub-commands

class DatabaseCommand(Command):
    name = "db"
    description = "Database management commands"
    
    def handle(self):
        # Show available sub-commands
        self.line("Available database commands:")
        self.line("  db:migrate - Run database migrations")
        self.line("  db:seed    - Seed database with test data")
        self.line("  db:reset   - Reset database")
        
        return 0

class MigrateCommand(Command):
    name = "db:migrate"
    description = "Run database migrations"
    
    def handle(self):
        self.line("Running migrations...")
        # Migration logic here
        self.line("<info>Migrations completed</info>")
        return 0

Command Calling Other Commands

class DeployCommand(Command):
    name = "deploy"
    description = "Deploy the application"
    
    def handle(self):
        self.line("Starting deployment...")
        
        # Run tests first
        if self.call("test") != 0:
            self.line("<error>Tests failed, aborting deployment</error>")
            return 1
            
        # Build the application
        self.call("build", "--production")
        
        # Deploy silently
        result = self.call_silent("upload", "--target production")
        
        if result == 0:
            self.line("<info>Deployment successful!</info>")
        else:
            self.line("<error>Deployment failed</error>")
            
        return result

Install with Tessl CLI

npx tessl i tessl/pypi-cleo

docs

application.md

commands.md

exceptions.md

index.md

io.md

styling.md

testing.md

ui.md

tile.json