or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

arguments.mdcaching.mdconfiguration.mdcontrollers.mdextensions.mdfoundation.mdhooks.mdindex.mdinterface-handler.mdlogging.mdmail.mdoutput.mdplugins.mdtemplates.mdutilities.md

output.mddocs/

0

# Output Rendering

1

2

The output rendering system provides flexible output formatting and presentation capabilities supporting multiple formats including JSON, tabular, and template-based output. It ensures consistent data presentation across different output handlers.

3

4

## Capabilities

5

6

### Output Handler Interface

7

8

Base interface for output rendering functionality that defines the contract for rendering operations.

9

10

```python { .api }

11

class OutputHandler:

12

"""

13

Output handler interface for rendering application data.

14

15

Provides methods for rendering data structures into formatted

16

output using various presentation formats and templates.

17

"""

18

19

def render(self, data: Dict[str, Any], template: str = None) -> str:

20

"""

21

Render data using the output handler.

22

23

Args:

24

data: Dictionary of data to render

25

template: Optional template name for template-based rendering

26

27

Returns:

28

Rendered output string

29

"""

30

```

31

32

## Usage Examples

33

34

### Basic Output Rendering

35

36

```python

37

from cement import App, Controller, ex

38

39

class BaseController(Controller):

40

class Meta:

41

label = 'base'

42

43

@ex(help='show user information')

44

def user_info(self):

45

"""Show user information with basic rendering."""

46

user_data = {

47

'id': 12345,

48

'name': 'John Doe',

49

'email': 'john@example.com',

50

'status': 'active',

51

'last_login': '2023-01-15T10:30:00Z',

52

'permissions': ['read', 'write', 'admin']

53

}

54

55

# Render using configured output handler

56

output = self.app.render(user_data)

57

print(output)

58

59

@ex(help='show system status')

60

def status(self):

61

"""Show system status information."""

62

status_data = {

63

'system': 'MyApp',

64

'version': '1.0.0',

65

'uptime': '5 days, 3 hours',

66

'memory_usage': '256MB',

67

'cpu_usage': '15%',

68

'active_users': 42,

69

'services': {

70

'database': 'online',

71

'cache': 'online',

72

'queue': 'online'

73

}

74

}

75

76

output = self.app.render(status_data)

77

print(output)

78

79

class MyApp(App):

80

class Meta:

81

label = 'myapp'

82

base_controller = 'base'

83

handlers = [BaseController]

84

85

with MyApp() as app:

86

app.run()

87

88

# Usage:

89

# myapp user-info

90

# myapp status

91

```

92

93

### JSON Output Handler

94

95

```python

96

from cement import App, Controller, ex, init_defaults

97

98

CONFIG = init_defaults('myapp')

99

CONFIG['output.json'] = {

100

'indent': 2,

101

'sort_keys': True

102

}

103

104

class DataController(Controller):

105

class Meta:

106

label = 'data'

107

stacked_on = 'base'

108

stacked_type = 'nested'

109

110

@ex(help='export data as JSON')

111

def export(self):

112

"""Export application data as JSON."""

113

export_data = {

114

'export_info': {

115

'timestamp': '2023-01-15T10:30:00Z',

116

'format': 'json',

117

'version': '1.0'

118

},

119

'users': [

120

{'id': 1, 'name': 'Alice', 'role': 'admin'},

121

{'id': 2, 'name': 'Bob', 'role': 'user'},

122

{'id': 3, 'name': 'Charlie', 'role': 'user'}

123

],

124

'settings': {

125

'theme': 'dark',

126

'notifications': True,

127

'auto_backup': False

128

}

129

}

130

131

# Render as JSON

132

json_output = self.app.render(export_data)

133

print(json_output)

134

135

class BaseController(Controller):

136

class Meta:

137

label = 'base'

138

139

class MyApp(App):

140

class Meta:

141

label = 'myapp'

142

base_controller = 'base'

143

extensions = ['json']

144

output_handler = 'json'

145

config_defaults = CONFIG

146

handlers = [BaseController, DataController]

147

148

with MyApp() as app:

149

app.run()

150

151

# Usage:

152

# myapp data export

153

```

154

155

### Tabular Output Handler

156

157

```python

158

from cement import App, Controller, ex, init_defaults

159

160

CONFIG = init_defaults('myapp')

161

CONFIG['output.tabulate'] = {

162

'tablefmt': 'grid', # grid, simple, plain, html, etc.

163

'headers': 'keys'

164

}

165

166

class ReportController(Controller):

167

class Meta:

168

label = 'report'

169

stacked_on = 'base'

170

stacked_type = 'nested'

171

172

@ex(help='show user report')

173

def users(self):

174

"""Show user report in tabular format."""

175

# Data structured for tabular output

176

user_report = {

177

'users': [

178

{'ID': 1, 'Name': 'Alice Johnson', 'Email': 'alice@example.com', 'Status': 'Active'},

179

{'ID': 2, 'Name': 'Bob Smith', 'Email': 'bob@example.com', 'Status': 'Inactive'},

180

{'ID': 3, 'Name': 'Charlie Brown', 'Email': 'charlie@example.com', 'Status': 'Active'},

181

{'ID': 4, 'Name': 'Diana Prince', 'Email': 'diana@example.com', 'Status': 'Active'}

182

]

183

}

184

185

# Render as table

186

table_output = self.app.render(user_report)

187

print(table_output)

188

189

@ex(help='show system metrics')

190

def metrics(self):

191

"""Show system metrics in tabular format."""

192

metrics_data = {

193

'metrics': [

194

{'Metric': 'CPU Usage', 'Value': '15%', 'Threshold': '80%', 'Status': 'OK'},

195

{'Metric': 'Memory Usage', 'Value': '256MB', 'Threshold': '1GB', 'Status': 'OK'},

196

{'Metric': 'Disk Usage', 'Value': '45GB', 'Threshold': '100GB', 'Status': 'Warning'},

197

{'Metric': 'Active Users', 'Value': '42', 'Threshold': '100', 'Status': 'OK'}

198

]

199

}

200

201

output = self.app.render(metrics_data)

202

print(output)

203

204

class BaseController(Controller):

205

class Meta:

206

label = 'base'

207

208

class MyApp(App):

209

class Meta:

210

label = 'myapp'

211

base_controller = 'base'

212

extensions = ['tabulate']

213

output_handler = 'tabulate'

214

config_defaults = CONFIG

215

handlers = [BaseController, ReportController]

216

217

with MyApp() as app:

218

app.run()

219

220

# Usage:

221

# myapp report users

222

# myapp report metrics

223

```

224

225

### Template-Based Output

226

227

```python

228

from cement import App, Controller, ex, init_defaults

229

230

CONFIG = init_defaults('myapp')

231

CONFIG['template.jinja2'] = {

232

'template_dirs': ['./templates']

233

}

234

235

class TemplateController(Controller):

236

class Meta:

237

label = 'template'

238

stacked_on = 'base'

239

stacked_type = 'nested'

240

241

@ex(help='generate user report')

242

def user_report(self):

243

"""Generate user report using template."""

244

report_data = {

245

'title': 'User Activity Report',

246

'generated_at': '2023-01-15 10:30:00',

247

'users': [

248

{

249

'name': 'Alice Johnson',

250

'email': 'alice@example.com',

251

'last_login': '2023-01-14',

252

'actions': 25,

253

'status': 'active'

254

},

255

{

256

'name': 'Bob Smith',

257

'email': 'bob@example.com',

258

'last_login': '2023-01-10',

259

'actions': 12,

260

'status': 'inactive'

261

}

262

],

263

'summary': {

264

'total_users': 2,

265

'active_users': 1,

266

'total_actions': 37

267

}

268

}

269

270

# Render using template

271

output = self.app.render(report_data, template='user_report.txt')

272

print(output)

273

274

@ex(help='generate system summary')

275

def system_summary(self):

276

"""Generate system summary using template."""

277

system_data = {

278

'system_name': 'MyApp Production',

279

'version': '1.0.0',

280

'environment': 'production',

281

'services': [

282

{'name': 'Web Server', 'status': 'running', 'uptime': '5d 3h'},

283

{'name': 'Database', 'status': 'running', 'uptime': '10d 2h'},

284

{'name': 'Cache', 'status': 'running', 'uptime': '5d 3h'},

285

{'name': 'Queue', 'status': 'running', 'uptime': '3d 1h'}

286

],

287

'alerts': [

288

{'level': 'warning', 'message': 'Disk usage above 80%'},

289

{'level': 'info', 'message': 'Scheduled maintenance in 2 days'}

290

]

291

}

292

293

output = self.app.render(system_data, template='system_summary.txt')

294

print(output)

295

296

class BaseController(Controller):

297

class Meta:

298

label = 'base'

299

300

class MyApp(App):

301

class Meta:

302

label = 'myapp'

303

base_controller = 'base'

304

extensions = ['jinja2']

305

template_handler = 'jinja2'

306

output_handler = 'jinja2'

307

config_defaults = CONFIG

308

handlers = [BaseController, TemplateController]

309

310

with MyApp() as app:

311

app.run()

312

313

# Usage:

314

# myapp template user-report

315

# myapp template system-summary

316

317

# Example template file: templates/user_report.txt

318

"""

319

{{ title }}

320

Generated: {{ generated_at }}

321

322

User Summary:

323

- Total Users: {{ summary.total_users }}

324

- Active Users: {{ summary.active_users }}

325

- Total Actions: {{ summary.total_actions }}

326

327

User Details:

328

{% for user in users %}

329

- {{ user.name }} ({{ user.email }})

330

Last Login: {{ user.last_login }}

331

Actions: {{ user.actions }}

332

Status: {{ user.status }}

333

{% endfor %}

334

"""

335

```

336

337

### Dynamic Output Handler Selection

338

339

```python

340

from cement import App, Controller, ex

341

342

class OutputController(Controller):

343

class Meta:

344

label = 'output'

345

stacked_on = 'base'

346

stacked_type = 'nested'

347

arguments = [

348

(['--format'], {

349

'choices': ['json', 'table', 'yaml'],

350

'default': 'json',

351

'help': 'output format'

352

})

353

]

354

355

@ex(help='show data in different formats')

356

def show(self):

357

"""Show data in user-specified format."""

358

data = {

359

'application': 'MyApp',

360

'users': [

361

{'id': 1, 'name': 'Alice', 'active': True},

362

{'id': 2, 'name': 'Bob', 'active': False}

363

],

364

'stats': {

365

'total_users': 2,

366

'active_users': 1

367

}

368

}

369

370

# Get desired format from arguments

371

output_format = self.app.pargs.format

372

373

# Temporarily switch output handler

374

original_handler = self.app._meta.output_handler

375

376

if output_format == 'json':

377

self.app._setup_output_handler('json')

378

elif output_format == 'table':

379

self.app._setup_output_handler('tabulate')

380

elif output_format == 'yaml':

381

self.app._setup_output_handler('yaml')

382

383

# Render with selected handler

384

output = self.app.render(data)

385

print(output)

386

387

# Restore original handler

388

self.app._setup_output_handler(original_handler)

389

390

class BaseController(Controller):

391

class Meta:

392

label = 'base'

393

394

class MyApp(App):

395

class Meta:

396

label = 'myapp'

397

base_controller = 'base'

398

extensions = ['json', 'tabulate', 'yaml']

399

handlers = [BaseController, OutputController]

400

401

with MyApp() as app:

402

app.run()

403

404

# Usage:

405

# myapp output show --format json

406

# myapp output show --format table

407

# myapp output show --format yaml

408

```

409

410

### Custom Output Processing

411

412

```python

413

from cement import App, Controller, ex

414

import csv

415

import io

416

417

class CsvController(Controller):

418

class Meta:

419

label = 'csv'

420

stacked_on = 'base'

421

stacked_type = 'nested'

422

423

def render_csv(self, data):

424

"""Custom CSV rendering method."""

425

if not isinstance(data, dict) or 'rows' not in data:

426

raise ValueError("CSV data must contain 'rows' key")

427

428

output = io.StringIO()

429

430

# Get headers from first row or use provided headers

431

rows = data['rows']

432

if not rows:

433

return ''

434

435

headers = data.get('headers', list(rows[0].keys()))

436

437

writer = csv.DictWriter(output, fieldnames=headers)

438

writer.writeheader()

439

440

for row in rows:

441

writer.writerow(row)

442

443

return output.getvalue()

444

445

@ex(help='export data as CSV')

446

def export(self):

447

"""Export data in CSV format."""

448

csv_data = {

449

'headers': ['ID', 'Name', 'Email', 'Status'],

450

'rows': [

451

{'ID': 1, 'Name': 'Alice Johnson', 'Email': 'alice@example.com', 'Status': 'Active'},

452

{'ID': 2, 'Name': 'Bob Smith', 'Email': 'bob@example.com', 'Status': 'Inactive'},

453

{'ID': 3, 'Name': 'Charlie Brown', 'Email': 'charlie@example.com', 'Status': 'Active'}

454

]

455

}

456

457

# Use custom CSV rendering

458

csv_output = self.render_csv(csv_data)

459

print(csv_output)

460

461

@ex(

462

help='save data to CSV file',

463

arguments=[

464

(['--output', '-o'], {

465

'help': 'output file path',

466

'default': 'data.csv'

467

})

468

]

469

)

470

def save(self):

471

"""Save data to CSV file."""

472

csv_data = {

473

'rows': [

474

{'Product': 'Widget A', 'Price': 19.99, 'Stock': 100},

475

{'Product': 'Widget B', 'Price': 29.99, 'Stock': 50},

476

{'Product': 'Widget C', 'Price': 39.99, 'Stock': 25}

477

]

478

}

479

480

csv_output = self.render_csv(csv_data)

481

482

output_file = self.app.pargs.output

483

with open(output_file, 'w') as f:

484

f.write(csv_output)

485

486

print(f'Data saved to {output_file}')

487

488

class BaseController(Controller):

489

class Meta:

490

label = 'base'

491

492

class MyApp(App):

493

class Meta:

494

label = 'myapp'

495

base_controller = 'base'

496

handlers = [BaseController, CsvController]

497

498

with MyApp() as app:

499

app.run()

500

501

# Usage:

502

# myapp csv export

503

# myapp csv save --output users.csv

504

```