Advanced Application Framework for Python with a focus on Command Line Interfaces
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
An advanced Application Framework for Python with a primary focus on Command Line Interfaces (CLI). Cement provides a comprehensive platform for both simple and complex command line applications with rapid development capabilities without sacrificing quality. The framework features a flexible, handler-based architecture with pluggable components including configuration management, argument parsing, logging, caching, output rendering, and controller-based command handling.
pip install cementpip install cement[cli]import cementCommon pattern for building applications:
from cement import App, Controller, exFor testing applications:
from cement import TestAppComplete import patterns:
from cement import (
App, TestApp, Controller, ex, Handler, Interface,
FrameworkError, InterfaceError, CaughtSignal,
init_defaults, minimal_logger, get_version,
misc, fs, shell
)from cement import App, Controller, ex
class BaseController(Controller):
class Meta:
label = 'base'
@ex(help='example sub command')
def command1(self):
"""Example sub command."""
print('Inside BaseController.command1()')
class MyApp(App):
class Meta:
label = 'myapp'
base_controller = 'base'
handlers = [
BaseController,
]
def main():
with MyApp() as app:
app.run()
if __name__ == '__main__':
main()Cement follows a modular, extensible architecture built around key design patterns:
App class serves as the central application container managing the entire lifecycleThis design enables cement to scale from simple single-file scripts to complex multi-tier applications while maintaining clean separation of concerns and extensibility.
Core application framework providing the main App and TestApp classes for building and testing CLI applications. Handles application lifecycle, configuration, and component management.
class App:
def __init__(self, label: str = None, **kw: Any) -> None: ...
def setup(self) -> None: ...
def run(self) -> Union[None, Any]: ...
def run_forever(self, interval: int = 1, tb: bool = True) -> None: ...
def reload(self) -> None: ...
def close(self, code: int = None) -> None: ...
def render(self, data: Any, template: str = None, out: IO = sys.stdout,
handler: str = None, **kw: Any) -> str: ...
def extend(self, member_name: str, member_object: Any) -> None: ...
def add_arg(self, *args: Any, **kw: Any) -> None: ...
def catch_signal(self, signum: int) -> None: ...
def validate_config(self) -> None: ...
def add_config_dir(self, path: str) -> None: ...
def add_config_file(self, path: str) -> None: ...
def add_plugin_dir(self, path: str) -> None: ...
def add_template_dir(self, path: str) -> None: ...
def remove_template_dir(self, path: str) -> None: ...
# Properties
@property
def label(self) -> str: ...
@property
def debug(self) -> bool: ...
@property
def quiet(self) -> bool: ...
@property
def argv(self) -> List[str]: ...
@property
def pargs(self) -> Any: ...
@property
def last_rendered(self) -> Optional[Tuple[Dict[str, Any], Optional[str]]]: ...
class TestApp(App):
"""Simplified application class optimized for testing with minimal configuration."""
passFramework architecture for defining pluggable components. Interfaces define contracts while handlers provide concrete implementations, enabling customizable behavior across all framework functionality.
class Interface:
"""Base class for defining framework interfaces."""
def __init__(self, **kw: Any) -> None: ...
def _validate(self) -> None: ...
class Handler:
"""Base class for interface implementations."""
def __init__(self, **kw: Any) -> None: ...
def _setup(self, app: App) -> None: ...
def _validate(self) -> None: ...
class InterfaceManager:
"""Manager for framework interfaces."""
def __init__(self, app: App) -> None: ...
def define(self, interface: Type[Interface]) -> None: ...
def defined(self, interface: str) -> bool: ...
def list(self) -> List[str]: ...
def get(self, interface: str, fallback: Type[Interface] = None, **kwargs: Any) -> Type[Interface]: ...
class HandlerManager:
"""Manager for handler registration and resolution."""
def __init__(self, app: App) -> None: ...
def register(self, handler_class: Type[Handler], force: bool = False) -> None: ...
def registered(self, interface: str, handler_label: str) -> bool: ...
def list(self, interface: str) -> List[Type[Handler]]: ...
def get(self, interface: str, handler_label: str, fallback: Type[Handler] = None, **kwargs: Any) -> Union[Handler, Type[Handler]]: ...
def setup(self, handler_class: Type[Handler]) -> Handler: ...
def resolve(self, interface: str, handler_def: Union[str, Handler, Type[Handler]], **kwargs: Any) -> Union[Handler, Optional[Handler]]: ...Command organization system using the argparse-based controller framework. Enables creating sub-commands, nested controllers, and exposing controller methods as CLI commands using decorators.
class Controller:
"""Base class for application controllers that handle command-line operations."""
class Meta:
label: str # Controller identifier
stacked_on: str # Parent controller for nesting
stacked_type: str # Stacking relationship type
def expose(hide: bool = False, arguments: List[ArgparseArgumentType] = [],
label: str = None, **parser_options: Any) -> Callable:
"""
Decorator to expose controller methods as CLI commands.
Parameters:
- hide: Hide command from help output
- arguments: List of argparse argument definitions
- label: Override command name (defaults to method name)
- **parser_options: Additional argparse options
"""
...
# Alias for expose decorator
ex = exposeConfiguration handling system supporting multiple file formats, default values, and hierarchical configuration merging. Integrates with argument parsing for unified application configuration.
class ConfigHandler:
def parse_file(self, file_path: str) -> bool: ...
def merge(self, dict_obj: Dict[str, Any]) -> None: ...
def get(self, section: str, key: str) -> Any: ...
def get_section_dict(self, section: str) -> Dict[str, Any]: ...
def get_sections(self) -> List[str]: ...
def add_section(self, section: str) -> None: ...
def has_section(self, section: str) -> bool: ...
def keys(self, section: str) -> List[str]: ...
def set(self, section: str, key: str, value: Any) -> None: ...Command-line argument parsing and processing system built on argparse. Provides unified argument handling that integrates with configuration management and controller systems.
class ArgumentHandler:
def add_argument(self, *args: Any, **kwargs: Any) -> None: ...
def parse(self, argv: List[str]) -> Any: ...Comprehensive logging framework with console and file output support, multiple log levels, and colorized output options. Integrates with Python's standard logging module.
class LogHandler:
def set_level(self, level: str) -> None: ...
def get_level(self) -> str: ...
def debug(self, msg: str, **kwargs: Any) -> None: ...
def info(self, msg: str, **kwargs: Any) -> None: ...
def warning(self, msg: str, **kwargs: Any) -> None: ...
def error(self, msg: str, **kwargs: Any) -> None: ...
def fatal(self, msg: str, **kwargs: Any) -> None: ...Output rendering system supporting multiple formats including JSON, tabular, and template-based output. Provides consistent data presentation across different output handlers.
class OutputHandler:
def render(self, data: Dict[str, Any], template: str = None) -> str: ...Template rendering framework supporting multiple template engines including Jinja2 and Mustache. Enables consistent template-based output generation.
class TemplateHandler:
def load(self, template_path: str) -> Any: ...
def render(self, content: str, data: Dict[str, Any]) -> str: ...Caching interface supporting multiple backends including Redis and Memcached. Provides key-value storage for improved application performance.
class CacheHandler:
def get(self, key: str) -> Any: ...
def set(self, key: str, value: Any, time: int = None) -> None: ...
def delete(self, key: str) -> None: ...
def purge(self) -> None: ...Extension point framework providing hooks throughout the application lifecycle. Enables custom functionality injection at defined points in application execution.
class HookManager:
def define(self, name: str) -> None: ...
def defined(self, name: str) -> bool: ...
def register(self, name: str, func: Callable, weight: int = 0) -> None: ...
def run(self, name: str, app: App, *args: Any, **kwargs: Any) -> None: ...Framework extension loading and management system. Enables modular functionality through well-defined extension points and automatic discovery.
class ExtensionHandler:
def load_extension(self, ext_module: str) -> None: ...
def load_extensions(self, ext_list: List[str]) -> None: ...Plugin management framework for loading and managing application plugins. Supports plugin discovery, loading, and lifecycle management.
class PluginHandler:
def load_plugin(self, plugin_name: str) -> None: ...
def load_plugins(self, plugin_list: List[str]) -> None: ...
def get_loaded_plugins(self) -> List[str]: ...
def get_enabled_plugins(self) -> List[str]: ...
def get_disabled_plugins(self) -> List[str]: ...Email functionality framework supporting SMTP-based email sending with template integration and attachment support.
class MailHandler:
def send(self, body: str, **kwargs: Any) -> bool: ...Collection of utility functions for common operations including file system operations, shell command execution, configuration helpers, and testing utilities.
# Core utility functions (cement.utils.misc)
def init_defaults(*sections: str) -> Dict[str, Any]: ...
def minimal_logger(namespace: str) -> logging.Logger: ...
def rando(salt: str = None) -> str: ...
def is_true(item: Any) -> bool: ...
# Version utility (cement.utils.version)
def get_version(version: Tuple[int, int, int, str, int] = VERSION) -> str: ...
# File system utilities (cement.utils.fs)
class Tmp:
"""Temporary file/directory context manager."""
def __init__(self, **kwargs: str) -> None: ...
def __enter__(self) -> Tmp: ...
def __exit__(self, exc_type, exc_value, traceback) -> None: ...
def abspath(path: str) -> str: ...
def join(*args: str) -> str: ...
# Shell utilities (cement.utils.shell)
def cmd(command: str, capture: bool = True, *args: Any, **kwargs: Any) -> Union[Tuple[str, str, int], int]: ...
def exec_cmd(command: List[str], *args: Any, **kwargs: Any) -> Tuple[str, str, int]: ...
def exec_cmd2(command: List[str], *args: Any, **kwargs: Any) -> int: ...
def spawn_process(target: Callable, *args: Any, **kwargs: Any) -> Process: ...
def spawn_thread(target: Callable, *args: Any, **kwargs: Any) -> Thread: ...
def prompt(text: str, options: List[str], default: str = None,
clear: bool = True, max_attempts: int = 10) -> str: ...Framework-specific exception classes for error handling and signal management.
class FrameworkError(Exception):
"""Base exception class for all framework errors."""
def __init__(self, msg: str) -> None: ...
def __str__(self) -> str: ...
class InterfaceError(FrameworkError):
"""Raised when interface validation or operations fail."""
pass
class CaughtSignal(FrameworkError):
"""Raised when the application catches a system signal."""
def __init__(self, signum: int, frame: Any) -> None: ...
@property
def signum(self) -> int: ...
@property
def frame(self) -> Any: ...The framework provides several built-in hooks for extending functionality:
pre_setup - Before application setuppost_setup - After application setuppre_run - Before application runpost_run - After application runpre_close - Before application closepost_close - After application closesignal - When signals are caughtpre_render - Before output renderingpost_render - After output renderingInstall with Tessl CLI
npx tessl i tessl/pypi-cement