or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-cement

Advanced Application Framework for Python with a focus on Command Line Interfaces

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/cement@3.0.x

To install, run

npx @tessl/cli install tessl/pypi-cement@3.0.0

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