0
# Cement Framework
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: cement
7
- **Language**: Python
8
- **Installation**: `pip install cement`
9
- **Optional CLI Extras**: `pip install cement[cli]`
10
- **Python Support**: 3.8+
11
12
## Core Imports
13
14
```python
15
import cement
16
```
17
18
Common pattern for building applications:
19
20
```python
21
from cement import App, Controller, ex
22
```
23
24
For testing applications:
25
26
```python
27
from cement import TestApp
28
```
29
30
Complete import patterns:
31
32
```python
33
from cement import (
34
App, TestApp, Controller, ex, Handler, Interface,
35
FrameworkError, InterfaceError, CaughtSignal,
36
init_defaults, minimal_logger, get_version,
37
misc, fs, shell
38
)
39
```
40
41
## Basic Usage
42
43
```python
44
from cement import App, Controller, ex
45
46
class BaseController(Controller):
47
class Meta:
48
label = 'base'
49
50
@ex(help='example sub command')
51
def command1(self):
52
"""Example sub command."""
53
print('Inside BaseController.command1()')
54
55
class MyApp(App):
56
class Meta:
57
label = 'myapp'
58
base_controller = 'base'
59
handlers = [
60
BaseController,
61
]
62
63
def main():
64
with MyApp() as app:
65
app.run()
66
67
if __name__ == '__main__':
68
main()
69
```
70
71
## Architecture
72
73
Cement follows a modular, extensible architecture built around key design patterns:
74
75
- **Application Framework**: The `App` class serves as the central application container managing the entire lifecycle
76
- **Interface/Handler System**: Defines pluggable components where interfaces specify contracts and handlers provide implementations
77
- **Hook System**: Provides extension points throughout the application lifecycle for customization
78
- **Extension System**: Modular functionality loading through well-defined extension points
79
- **Controller System**: Command-based architecture for organizing CLI functionality into logical groups
80
81
This design enables cement to scale from simple single-file scripts to complex multi-tier applications while maintaining clean separation of concerns and extensibility.
82
83
## Capabilities
84
85
### Application Foundation
86
87
Core application framework providing the main `App` and `TestApp` classes for building and testing CLI applications. Handles application lifecycle, configuration, and component management.
88
89
```python { .api }
90
class App:
91
def __init__(self, label: str = None, **kw: Any) -> None: ...
92
def setup(self) -> None: ...
93
def run(self) -> Union[None, Any]: ...
94
def run_forever(self, interval: int = 1, tb: bool = True) -> None: ...
95
def reload(self) -> None: ...
96
def close(self, code: int = None) -> None: ...
97
def render(self, data: Any, template: str = None, out: IO = sys.stdout,
98
handler: str = None, **kw: Any) -> str: ...
99
def extend(self, member_name: str, member_object: Any) -> None: ...
100
def add_arg(self, *args: Any, **kw: Any) -> None: ...
101
def catch_signal(self, signum: int) -> None: ...
102
def validate_config(self) -> None: ...
103
def add_config_dir(self, path: str) -> None: ...
104
def add_config_file(self, path: str) -> None: ...
105
def add_plugin_dir(self, path: str) -> None: ...
106
def add_template_dir(self, path: str) -> None: ...
107
def remove_template_dir(self, path: str) -> None: ...
108
109
# Properties
110
@property
111
def label(self) -> str: ...
112
@property
113
def debug(self) -> bool: ...
114
@property
115
def quiet(self) -> bool: ...
116
@property
117
def argv(self) -> List[str]: ...
118
@property
119
def pargs(self) -> Any: ...
120
@property
121
def last_rendered(self) -> Optional[Tuple[Dict[str, Any], Optional[str]]]: ...
122
123
class TestApp(App):
124
"""Simplified application class optimized for testing with minimal configuration."""
125
pass
126
```
127
128
[Application Foundation](./foundation.md)
129
130
### Interface and Handler System
131
132
Framework architecture for defining pluggable components. Interfaces define contracts while handlers provide concrete implementations, enabling customizable behavior across all framework functionality.
133
134
```python { .api }
135
class Interface:
136
"""Base class for defining framework interfaces."""
137
def __init__(self, **kw: Any) -> None: ...
138
def _validate(self) -> None: ...
139
140
class Handler:
141
"""Base class for interface implementations."""
142
def __init__(self, **kw: Any) -> None: ...
143
def _setup(self, app: App) -> None: ...
144
def _validate(self) -> None: ...
145
146
class InterfaceManager:
147
"""Manager for framework interfaces."""
148
def __init__(self, app: App) -> None: ...
149
def define(self, interface: Type[Interface]) -> None: ...
150
def defined(self, interface: str) -> bool: ...
151
def list(self) -> List[str]: ...
152
def get(self, interface: str, fallback: Type[Interface] = None, **kwargs: Any) -> Type[Interface]: ...
153
154
class HandlerManager:
155
"""Manager for handler registration and resolution."""
156
def __init__(self, app: App) -> None: ...
157
def register(self, handler_class: Type[Handler], force: bool = False) -> None: ...
158
def registered(self, interface: str, handler_label: str) -> bool: ...
159
def list(self, interface: str) -> List[Type[Handler]]: ...
160
def get(self, interface: str, handler_label: str, fallback: Type[Handler] = None, **kwargs: Any) -> Union[Handler, Type[Handler]]: ...
161
def setup(self, handler_class: Type[Handler]) -> Handler: ...
162
def resolve(self, interface: str, handler_def: Union[str, Handler, Type[Handler]], **kwargs: Any) -> Union[Handler, Optional[Handler]]: ...
163
```
164
165
[Interface and Handler System](./interface-handler.md)
166
167
### Controllers and Commands
168
169
Command organization system using the argparse-based controller framework. Enables creating sub-commands, nested controllers, and exposing controller methods as CLI commands using decorators.
170
171
```python { .api }
172
class Controller:
173
"""Base class for application controllers that handle command-line operations."""
174
175
class Meta:
176
label: str # Controller identifier
177
stacked_on: str # Parent controller for nesting
178
stacked_type: str # Stacking relationship type
179
180
def expose(hide: bool = False, arguments: List[ArgparseArgumentType] = [],
181
label: str = None, **parser_options: Any) -> Callable:
182
"""
183
Decorator to expose controller methods as CLI commands.
184
185
Parameters:
186
- hide: Hide command from help output
187
- arguments: List of argparse argument definitions
188
- label: Override command name (defaults to method name)
189
- **parser_options: Additional argparse options
190
"""
191
...
192
193
# Alias for expose decorator
194
ex = expose
195
```
196
197
[Controllers and Commands](./controllers.md)
198
199
### Configuration Management
200
201
Configuration handling system supporting multiple file formats, default values, and hierarchical configuration merging. Integrates with argument parsing for unified application configuration.
202
203
```python { .api }
204
class ConfigHandler:
205
def parse_file(self, file_path: str) -> bool: ...
206
def merge(self, dict_obj: Dict[str, Any]) -> None: ...
207
def get(self, section: str, key: str) -> Any: ...
208
def get_section_dict(self, section: str) -> Dict[str, Any]: ...
209
def get_sections(self) -> List[str]: ...
210
def add_section(self, section: str) -> None: ...
211
def has_section(self, section: str) -> bool: ...
212
def keys(self, section: str) -> List[str]: ...
213
def set(self, section: str, key: str, value: Any) -> None: ...
214
```
215
216
[Configuration Management](./configuration.md)
217
218
### Argument Parsing
219
220
Command-line argument parsing and processing system built on argparse. Provides unified argument handling that integrates with configuration management and controller systems.
221
222
```python { .api }
223
class ArgumentHandler:
224
def add_argument(self, *args: Any, **kwargs: Any) -> None: ...
225
def parse(self, argv: List[str]) -> Any: ...
226
```
227
228
[Argument Parsing](./arguments.md)
229
230
### Logging System
231
232
Comprehensive logging framework with console and file output support, multiple log levels, and colorized output options. Integrates with Python's standard logging module.
233
234
```python { .api }
235
class LogHandler:
236
def set_level(self, level: str) -> None: ...
237
def get_level(self) -> str: ...
238
def debug(self, msg: str, **kwargs: Any) -> None: ...
239
def info(self, msg: str, **kwargs: Any) -> None: ...
240
def warning(self, msg: str, **kwargs: Any) -> None: ...
241
def error(self, msg: str, **kwargs: Any) -> None: ...
242
def fatal(self, msg: str, **kwargs: Any) -> None: ...
243
```
244
245
[Logging System](./logging.md)
246
247
### Output Rendering
248
249
Output rendering system supporting multiple formats including JSON, tabular, and template-based output. Provides consistent data presentation across different output handlers.
250
251
```python { .api }
252
class OutputHandler:
253
def render(self, data: Dict[str, Any], template: str = None) -> str: ...
254
```
255
256
[Output Rendering](./output.md)
257
258
### Template System
259
260
Template rendering framework supporting multiple template engines including Jinja2 and Mustache. Enables consistent template-based output generation.
261
262
```python { .api }
263
class TemplateHandler:
264
def load(self, template_path: str) -> Any: ...
265
def render(self, content: str, data: Dict[str, Any]) -> str: ...
266
```
267
268
[Template System](./templates.md)
269
270
### Caching System
271
272
Caching interface supporting multiple backends including Redis and Memcached. Provides key-value storage for improved application performance.
273
274
```python { .api }
275
class CacheHandler:
276
def get(self, key: str) -> Any: ...
277
def set(self, key: str, value: Any, time: int = None) -> None: ...
278
def delete(self, key: str) -> None: ...
279
def purge(self) -> None: ...
280
```
281
282
[Caching System](./caching.md)
283
284
### Hook System
285
286
Extension point framework providing hooks throughout the application lifecycle. Enables custom functionality injection at defined points in application execution.
287
288
```python { .api }
289
class HookManager:
290
def define(self, name: str) -> None: ...
291
def defined(self, name: str) -> bool: ...
292
def register(self, name: str, func: Callable, weight: int = 0) -> None: ...
293
def run(self, name: str, app: App, *args: Any, **kwargs: Any) -> None: ...
294
```
295
296
[Hook System](./hooks.md)
297
298
### Extension System
299
300
Framework extension loading and management system. Enables modular functionality through well-defined extension points and automatic discovery.
301
302
```python { .api }
303
class ExtensionHandler:
304
def load_extension(self, ext_module: str) -> None: ...
305
def load_extensions(self, ext_list: List[str]) -> None: ...
306
```
307
308
[Extension System](./extensions.md)
309
310
### Plugin System
311
312
Plugin management framework for loading and managing application plugins. Supports plugin discovery, loading, and lifecycle management.
313
314
```python { .api }
315
class PluginHandler:
316
def load_plugin(self, plugin_name: str) -> None: ...
317
def load_plugins(self, plugin_list: List[str]) -> None: ...
318
def get_loaded_plugins(self) -> List[str]: ...
319
def get_enabled_plugins(self) -> List[str]: ...
320
def get_disabled_plugins(self) -> List[str]: ...
321
```
322
323
[Plugin System](./plugins.md)
324
325
### Mail System
326
327
Email functionality framework supporting SMTP-based email sending with template integration and attachment support.
328
329
```python { .api }
330
class MailHandler:
331
def send(self, body: str, **kwargs: Any) -> bool: ...
332
```
333
334
[Mail System](./mail.md)
335
336
### Utility Functions
337
338
Collection of utility functions for common operations including file system operations, shell command execution, configuration helpers, and testing utilities.
339
340
```python { .api }
341
# Core utility functions (cement.utils.misc)
342
def init_defaults(*sections: str) -> Dict[str, Any]: ...
343
def minimal_logger(namespace: str) -> logging.Logger: ...
344
def rando(salt: str = None) -> str: ...
345
def is_true(item: Any) -> bool: ...
346
347
# Version utility (cement.utils.version)
348
def get_version(version: Tuple[int, int, int, str, int] = VERSION) -> str: ...
349
350
# File system utilities (cement.utils.fs)
351
class Tmp:
352
"""Temporary file/directory context manager."""
353
def __init__(self, **kwargs: str) -> None: ...
354
def __enter__(self) -> Tmp: ...
355
def __exit__(self, exc_type, exc_value, traceback) -> None: ...
356
357
def abspath(path: str) -> str: ...
358
def join(*args: str) -> str: ...
359
360
# Shell utilities (cement.utils.shell)
361
def cmd(command: str, capture: bool = True, *args: Any, **kwargs: Any) -> Union[Tuple[str, str, int], int]: ...
362
def exec_cmd(command: List[str], *args: Any, **kwargs: Any) -> Tuple[str, str, int]: ...
363
def exec_cmd2(command: List[str], *args: Any, **kwargs: Any) -> int: ...
364
def spawn_process(target: Callable, *args: Any, **kwargs: Any) -> Process: ...
365
def spawn_thread(target: Callable, *args: Any, **kwargs: Any) -> Thread: ...
366
def prompt(text: str, options: List[str], default: str = None,
367
clear: bool = True, max_attempts: int = 10) -> str: ...
368
```
369
370
[Utility Functions](./utilities.md)
371
372
## Exception Classes
373
374
Framework-specific exception classes for error handling and signal management.
375
376
```python { .api }
377
class FrameworkError(Exception):
378
"""Base exception class for all framework errors."""
379
def __init__(self, msg: str) -> None: ...
380
def __str__(self) -> str: ...
381
382
class InterfaceError(FrameworkError):
383
"""Raised when interface validation or operations fail."""
384
pass
385
386
class CaughtSignal(FrameworkError):
387
"""Raised when the application catches a system signal."""
388
def __init__(self, signum: int, frame: Any) -> None: ...
389
390
@property
391
def signum(self) -> int: ...
392
393
@property
394
def frame(self) -> Any: ...
395
```
396
397
## Built-in Hook Points
398
399
The framework provides several built-in hooks for extending functionality:
400
401
- `pre_setup` - Before application setup
402
- `post_setup` - After application setup
403
- `pre_run` - Before application run
404
- `post_run` - After application run
405
- `pre_close` - Before application close
406
- `post_close` - After application close
407
- `signal` - When signals are caught
408
- `pre_render` - Before output rendering
409
- `post_render` - After output rendering