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

arguments.mddocs/

0

# Argument Parsing

1

2

The argument parsing system provides command-line argument processing built on Python's argparse module. It offers unified argument handling that integrates with configuration management and controller systems.

3

4

## Capabilities

5

6

### Argument Handler Interface

7

8

Base interface for argument parsing functionality that defines the contract for command-line argument operations.

9

10

```python { .api }

11

class ArgumentHandler:

12

"""

13

Argument handler interface for parsing command-line arguments.

14

15

Provides methods for adding arguments, parsing command-line input,

16

and integrating with the application configuration system.

17

"""

18

19

def add_argument(self, *args: Any, **kwargs: Any) -> None:

20

"""

21

Add a command-line argument.

22

23

Args:

24

*args: Positional arguments (e.g., '--verbose', '-v')

25

**kwargs: Keyword arguments (help, action, type, etc.)

26

"""

27

28

def parse(self, argv: List[str]) -> Any:

29

"""

30

Parse command-line arguments.

31

32

Args:

33

argv: List of command-line arguments to parse

34

35

Returns:

36

Parsed arguments object

37

"""

38

```

39

40

## Usage Examples

41

42

### Basic Argument Parsing

43

44

```python

45

from cement import App, Controller, ex

46

47

class BaseController(Controller):

48

class Meta:

49

label = 'base'

50

arguments = [

51

(['--verbose', '-v'], {

52

'help': 'verbose output',

53

'action': 'store_true'

54

}),

55

(['--config'], {

56

'help': 'configuration file path',

57

'dest': 'config_file'

58

})

59

]

60

61

def _default(self):

62

"""Default action when no sub-command specified."""

63

if self.app.pargs.verbose:

64

print('Verbose mode enabled')

65

66

if hasattr(self.app.pargs, 'config_file') and self.app.pargs.config_file:

67

print(f'Using config: {self.app.pargs.config_file}')

68

69

class MyApp(App):

70

class Meta:

71

label = 'myapp'

72

base_controller = 'base'

73

handlers = [BaseController]

74

75

with MyApp() as app:

76

app.run()

77

78

# Usage:

79

# myapp --verbose

80

# myapp --config /path/to/config.conf

81

```

82

83

### Command-Specific Arguments

84

85

```python

86

from cement import App, Controller, ex

87

88

class FileController(Controller):

89

class Meta:

90

label = 'file'

91

stacked_on = 'base'

92

stacked_type = 'nested'

93

94

@ex(

95

help='process files',

96

arguments=[

97

(['files'], {

98

'nargs': '+',

99

'help': 'files to process'

100

}),

101

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

102

'help': 'output directory',

103

'default': './output'

104

}),

105

(['--format'], {

106

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

107

'default': 'json',

108

'help': 'output format'

109

}),

110

(['--recursive', '-r'], {

111

'action': 'store_true',

112

'help': 'process directories recursively'

113

})

114

]

115

)

116

def process(self):

117

"""Process files with various options."""

118

files = self.app.pargs.files

119

output_dir = self.app.pargs.output

120

format_type = self.app.pargs.format

121

recursive = self.app.pargs.recursive

122

123

print(f'Processing {len(files)} files')

124

print(f'Output directory: {output_dir}')

125

print(f'Format: {format_type}')

126

print(f'Recursive: {recursive}')

127

128

for file_path in files:

129

print(f'Processing: {file_path}')

130

131

class BaseController(Controller):

132

class Meta:

133

label = 'base'

134

135

class MyApp(App):

136

class Meta:

137

label = 'myapp'

138

base_controller = 'base'

139

handlers = [BaseController, FileController]

140

141

with MyApp() as app:

142

app.run()

143

144

# Usage:

145

# myapp file process file1.txt file2.txt --format yaml --recursive

146

```

147

148

### Global vs Local Arguments

149

150

```python

151

from cement import App, Controller, ex

152

153

class BaseController(Controller):

154

class Meta:

155

label = 'base'

156

# Global arguments available to all commands

157

arguments = [

158

(['--debug'], {

159

'action': 'store_true',

160

'help': 'enable debug mode'

161

}),

162

(['--log-level'], {

163

'choices': ['DEBUG', 'INFO', 'WARNING', 'ERROR'],

164

'default': 'INFO',

165

'help': 'set logging level'

166

})

167

]

168

169

@ex(

170

help='show application status',

171

# Command-specific arguments

172

arguments=[

173

(['--detailed'], {

174

'action': 'store_true',

175

'help': 'show detailed status'

176

})

177

]

178

)

179

def status(self):

180

"""Show application status."""

181

# Access global arguments

182

debug = self.app.pargs.debug

183

log_level = self.app.pargs.log_level

184

185

# Access command-specific arguments

186

detailed = self.app.pargs.detailed

187

188

print(f'Debug mode: {debug}')

189

print(f'Log level: {log_level}')

190

191

if detailed:

192

print('Detailed status information...')

193

194

class MyApp(App):

195

class Meta:

196

label = 'myapp'

197

base_controller = 'base'

198

handlers = [BaseController]

199

200

with MyApp() as app:

201

app.run()

202

203

# Usage:

204

# myapp --debug --log-level DEBUG status --detailed

205

```

206

207

### Argument Validation

208

209

```python

210

from cement import App, Controller, ex

211

import os

212

213

def validate_file_exists(value):

214

"""Custom argument type that validates file exists."""

215

if not os.path.exists(value):

216

raise argparse.ArgumentTypeError(f"File '{value}' does not exist")

217

return value

218

219

def validate_positive_int(value):

220

"""Custom argument type that validates positive integers."""

221

try:

222

ivalue = int(value)

223

if ivalue <= 0:

224

raise argparse.ArgumentTypeError(f"'{value}' must be a positive integer")

225

return ivalue

226

except ValueError:

227

raise argparse.ArgumentTypeError(f"'{value}' is not a valid integer")

228

229

class BaseController(Controller):

230

class Meta:

231

label = 'base'

232

233

@ex(

234

help='backup file',

235

arguments=[

236

(['source'], {

237

'type': validate_file_exists,

238

'help': 'source file to backup'

239

}),

240

(['--destination'], {

241

'help': 'backup destination path'

242

}),

243

(['--max-backups'], {

244

'type': validate_positive_int,

245

'default': 5,

246

'help': 'maximum number of backups to keep'

247

})

248

]

249

)

250

def backup(self):

251

"""Backup a file with validation."""

252

source = self.app.pargs.source

253

destination = self.app.pargs.destination or f"{source}.bak"

254

max_backups = self.app.pargs.max_backups

255

256

print(f'Backing up {source} to {destination}')

257

print(f'Keeping maximum {max_backups} backups')

258

259

class MyApp(App):

260

class Meta:

261

label = 'myapp'

262

base_controller = 'base'

263

handlers = [BaseController]

264

265

with MyApp() as app:

266

app.run()

267

268

# Usage:

269

# myapp backup /path/to/file.txt --max-backups 10

270

```

271

272

### Environment Variable Integration

273

274

```python

275

from cement import App, Controller, ex

276

import os

277

278

class BaseController(Controller):

279

class Meta:

280

label = 'base'

281

arguments = [

282

(['--database-url'], {

283

'help': 'database connection URL',

284

'default': os.getenv('DATABASE_URL', 'sqlite:///app.db'),

285

'dest': 'database_url'

286

}),

287

(['--api-key'], {

288

'help': 'API key for external service',

289

'default': os.getenv('API_KEY'),

290

'dest': 'api_key'

291

}),

292

(['--workers'], {

293

'type': int,

294

'help': 'number of worker processes',

295

'default': int(os.getenv('WORKERS', '4')),

296

'dest': 'worker_count'

297

})

298

]

299

300

@ex(help='show configuration')

301

def config(self):

302

"""Show current configuration from args/env."""

303

print(f'Database URL: {self.app.pargs.database_url}')

304

print(f'API Key: {"***" if self.app.pargs.api_key else "Not set"}')

305

print(f'Workers: {self.app.pargs.worker_count}')

306

307

class MyApp(App):

308

class Meta:

309

label = 'myapp'

310

base_controller = 'base'

311

handlers = [BaseController]

312

313

with MyApp() as app:

314

app.run()

315

316

# Environment variables take precedence:

317

# DATABASE_URL=postgresql://... myapp config

318

# myapp config --database-url mysql://...

319

```

320

321

### Complex Argument Patterns

322

323

```python

324

from cement import App, Controller, ex

325

import argparse

326

327

class DeployController(Controller):

328

class Meta:

329

label = 'deploy'

330

stacked_on = 'base'

331

stacked_type = 'nested'

332

333

@ex(

334

help='deploy application',

335

arguments=[

336

(['environment'], {

337

'choices': ['development', 'staging', 'production'],

338

'help': 'deployment environment'

339

}),

340

(['--version'], {

341

'help': 'application version to deploy'

342

}),

343

(['--config-file'], {

344

'action': 'append',

345

'help': 'configuration files (can be specified multiple times)'

346

}),

347

(['--dry-run'], {

348

'action': 'store_true',

349

'help': 'show what would be deployed without actually deploying'

350

}),

351

(['--force'], {

352

'action': 'store_true',

353

'help': 'force deployment even if validation fails'

354

}),

355

(['--exclude'], {

356

'action': 'append',

357

'help': 'exclude specific components from deployment'

358

}),

359

(['--timeout'], {

360

'type': int,

361

'default': 300,

362

'help': 'deployment timeout in seconds'

363

})

364

]

365

)

366

def start(self):

367

"""Start deployment process."""

368

env = self.app.pargs.environment

369

version = self.app.pargs.version or 'latest'

370

config_files = self.app.pargs.config_file or []

371

dry_run = self.app.pargs.dry_run

372

force = self.app.pargs.force

373

excludes = self.app.pargs.exclude or []

374

timeout = self.app.pargs.timeout

375

376

print(f'Deploying to {env} environment')

377

print(f'Version: {version}')

378

print(f'Config files: {config_files}')

379

print(f'Dry run: {dry_run}')

380

print(f'Force: {force}')

381

print(f'Excludes: {excludes}')

382

print(f'Timeout: {timeout}s')

383

384

class BaseController(Controller):

385

class Meta:

386

label = 'base'

387

388

class MyApp(App):

389

class Meta:

390

label = 'myapp'

391

base_controller = 'base'

392

handlers = [BaseController, DeployController]

393

394

with MyApp() as app:

395

app.run()

396

397

# Usage:

398

# myapp deploy production --version 1.2.3 --config-file prod.conf --config-file secrets.conf --exclude monitoring --dry-run

399

```