0
# CLI Argument Parsing
1
2
Invoke provides a comprehensive argument parsing system that supports flags, options, positional arguments, help generation, and complex argument types with automatic CLI generation from task signatures.
3
4
## Capabilities
5
6
### Parser Class
7
8
Main CLI argument parser supporting contexts, flags, options, and positional arguments.
9
10
```python { .api }
11
class Parser:
12
"""
13
Main CLI argument parser.
14
15
Handles parsing command-line arguments into structured contexts with
16
support for flags, options, positional arguments, and help generation.
17
18
Attributes:
19
- contexts (list): List of parsing contexts
20
- initial (ParserContext): Initial parsing context
21
- ignore_unknown (bool): Whether to ignore unknown arguments
22
"""
23
24
def __init__(self, contexts=None, initial=None, ignore_unknown=False):
25
"""
26
Initialize Parser.
27
28
Parameters:
29
- contexts (list, optional): Parsing contexts to use
30
- initial (ParserContext, optional): Initial context
31
- ignore_unknown (bool): Ignore unknown arguments instead of erroring
32
"""
33
34
def parse_argv(self, argv):
35
"""
36
Parse command-line arguments.
37
38
Parameters:
39
- argv (list): Command-line arguments to parse
40
41
Returns:
42
ParseResult: Parsed arguments organized by context
43
44
Raises:
45
ParseError: If argument parsing fails
46
"""
47
48
def print_help(self, name=None, text=None):
49
"""
50
Print help text for parser.
51
52
Parameters:
53
- name (str, optional): Program name
54
- text (str, optional): Additional help text
55
"""
56
```
57
58
### Argument Class
59
60
Command-line argument definition with validation and type conversion.
61
62
```python { .api }
63
class Argument:
64
"""
65
Command-line argument definition.
66
67
Defines a single command-line argument including its names, type,
68
default value, help text, and parsing behavior.
69
70
Attributes:
71
- names (list): Argument names (including aliases)
72
- kind (type): Argument type (str, int, bool, etc.)
73
- default: Default value
74
- help (str): Help text
75
- positional (bool): Whether argument is positional
76
- optional (bool): Whether argument is optional
77
- incrementable (bool): Whether argument can be repeated to increment value
78
- iterable (bool): Whether argument accepts multiple values
79
- attr_name (str): Attribute name for storing parsed value
80
"""
81
82
def __init__(self, names=None, kind=str, default=None, help=None, positional=False, optional=None, incrementable=False, iterable=False, attr_name=None):
83
"""
84
Initialize Argument.
85
86
Parameters:
87
- names (list/str): Argument name(s)
88
- kind (type): Argument type for conversion
89
- default: Default value if not provided
90
- help (str): Help text description
91
- positional (bool): Whether this is a positional argument
92
- optional (bool): Whether argument is optional
93
- incrementable (bool): Can be repeated to increment (e.g., -vvv)
94
- iterable (bool): Accepts multiple values
95
- attr_name (str): Attribute name for parsed value storage
96
"""
97
98
@property
99
def name(self):
100
"""Primary argument name."""
101
102
@property
103
def nicknames(self):
104
"""Alternative argument names."""
105
106
@property
107
def takes_value(self):
108
"""Whether argument takes a value."""
109
110
def value_set(self, given):
111
"""
112
Set argument value with type conversion.
113
114
Parameters:
115
- given: Raw value to set
116
"""
117
118
@property
119
def value(self):
120
"""Current argument value."""
121
122
@property
123
def got_value(self):
124
"""Whether argument received a value."""
125
```
126
127
### ParserContext Class
128
129
Parser execution context containing parsed arguments for a specific command or task.
130
131
```python { .api }
132
class ParserContext:
133
"""
134
Parser context containing arguments for a specific parsing scope.
135
136
Represents the parsed arguments for a single command, task, or parsing
137
context within a larger argument parsing operation.
138
139
Attributes:
140
- name (str): Context name
141
- aliases (list): Context aliases
142
- args (list): Parsed arguments
143
- positional_args (list): Positional arguments
144
- seen_flags (set): Flags that were encountered
145
"""
146
147
def __init__(self, name=None, aliases=None, args=None):
148
"""
149
Initialize ParserContext.
150
151
Parameters:
152
- name (str, optional): Context name
153
- aliases (list, optional): Context aliases
154
- args (list, optional): Arguments for this context
155
"""
156
157
def add_arg(self, *args, **kwargs):
158
"""
159
Add argument to this context.
160
161
Parameters:
162
- *args, **kwargs: Arguments passed to Argument constructor
163
164
Returns:
165
Argument: Added argument object
166
"""
167
168
def help_tuples(self):
169
"""
170
Generate help text tuples for arguments.
171
172
Returns:
173
list: List of (names, help_text) tuples
174
"""
175
176
def as_kwargs(self):
177
"""
178
Convert parsed arguments to keyword arguments dictionary.
179
180
Returns:
181
dict: Parsed arguments as keyword arguments
182
"""
183
184
def __getitem__(self, key):
185
"""Get argument value by name."""
186
187
def __contains__(self, key):
188
"""Test if argument exists."""
189
190
def __iter__(self):
191
"""Iterate over argument names."""
192
```
193
194
### ParseResult Class
195
196
Container for complete parsing results from multiple contexts.
197
198
```python { .api }
199
class ParseResult(list):
200
"""
201
Parse result containing multiple parser contexts.
202
203
Behaves as a list of ParserContext objects representing the complete
204
parsing result from command-line arguments.
205
"""
206
207
def __getitem__(self, index):
208
"""Get context by index or name."""
209
210
def __iter__(self):
211
"""Iterate over contexts."""
212
213
def remainder(self):
214
"""Get unparsed remainder arguments."""
215
```
216
217
### Program Class
218
219
High-level CLI program management integrating parsing with task execution.
220
221
```python { .api }
222
class Program:
223
"""
224
Top-level CLI program management.
225
226
Coordinates argument parsing, task loading, help generation, and
227
task execution for complete CLI application functionality.
228
229
Attributes:
230
- name (str): Program name
231
- namespace (Collection): Task namespace
232
- config_class (type): Configuration class to use
233
- executor_class (type): Executor class to use
234
- loader_class (type): Collection loader class
235
- parser_class (type): Parser class to use
236
- config (Config): Program configuration
237
- initial_context (Context): Initial execution context
238
"""
239
240
def __init__(self, name=None, namespace=None, version=None, config_class=None, executor_class=None, loader_class=None, parser_class=None):
241
"""
242
Initialize Program.
243
244
Parameters:
245
- name (str, optional): Program name
246
- namespace (Collection, optional): Task collection
247
- version (str, optional): Program version
248
- config_class (type, optional): Config class
249
- executor_class (type, optional): Executor class
250
- loader_class (type, optional): Loader class
251
- parser_class (type, optional): Parser class
252
"""
253
254
def run(self, argv=None, exit=None):
255
"""
256
Run the program with given arguments.
257
258
Parameters:
259
- argv (list, optional): Command-line arguments
260
- exit (bool, optional): Whether to exit on completion
261
262
Returns:
263
any: Program result
264
"""
265
266
def parse_core(self, argv):
267
"""
268
Parse core program arguments.
269
270
Parameters:
271
- argv (list): Command-line arguments
272
273
Returns:
274
tuple: (core_args, task_args)
275
"""
276
277
def parse_tasks(self, args):
278
"""
279
Parse task-specific arguments.
280
281
Parameters:
282
- args (list): Task arguments to parse
283
284
Returns:
285
ParseResult: Parsed task arguments
286
"""
287
288
def execute(self, *args, **kwargs):
289
"""
290
Execute parsed tasks.
291
292
Parameters:
293
- *args, **kwargs: Execution arguments
294
"""
295
296
def print_help(self):
297
"""Print program help text."""
298
299
def print_version(self):
300
"""Print program version."""
301
302
def list_tasks(self, format='nested'):
303
"""
304
List available tasks.
305
306
Parameters:
307
- format (str): Output format ('nested', 'flat', 'json')
308
"""
309
```
310
311
## Usage Examples
312
313
### Basic Argument Parsing
314
315
```python
316
from invoke.parser import Parser, Argument, ParserContext
317
318
# Create argument definitions
319
ctx = ParserContext(name='mytask')
320
ctx.add_arg('--verbose', '-v', kind=bool, help='Verbose output')
321
ctx.add_arg('--count', '-c', kind=int, default=1, help='Repeat count')
322
ctx.add_arg('filename', positional=True, help='File to process')
323
324
# Create parser
325
parser = Parser([ctx])
326
327
# Parse arguments
328
result = parser.parse_argv(['mytask', '--verbose', '--count', '3', 'data.txt'])
329
330
# Access parsed values
331
task_ctx = result[0]
332
print(task_ctx.as_kwargs()) # {'verbose': True, 'count': 3, 'filename': 'data.txt'}
333
```
334
335
### Task Argument Integration
336
337
```python
338
from invoke import task
339
340
@task(help={'name': 'Name to greet', 'loud': 'Use uppercase'})
341
def hello(ctx, name='World', loud=False):
342
"""Say hello to someone."""
343
greeting = f"Hello {name}!"
344
if loud:
345
greeting = greeting.upper()
346
print(greeting)
347
348
# CLI usage:
349
# invoke hello --name John --loud
350
# invoke hello -n John -l
351
```
352
353
### Complex Argument Types
354
355
```python
356
from invoke import task
357
358
@task(
359
iterable=['exclude'], # Can specify multiple --exclude args
360
incrementable=['verbose'] # Can use -v, -vv, -vvv for levels
361
)
362
def process(ctx, file='data.txt', exclude=None, verbose=0, dry_run=False):
363
"""Process file with options."""
364
excludes = exclude or []
365
366
if verbose >= 1:
367
print(f"Processing {file}")
368
if verbose >= 2:
369
print(f"Excluding: {excludes}")
370
if verbose >= 3:
371
print("Debug mode enabled")
372
373
if dry_run:
374
print("Dry run - no changes made")
375
else:
376
# Do actual processing
377
pass
378
379
# CLI usage:
380
# invoke process --file data.csv --exclude logs --exclude temp -vvv --dry-run
381
```
382
383
### Custom Parser Usage
384
385
```python
386
from invoke.parser import Parser, Argument, ParserContext
387
388
# Create contexts for different commands
389
deploy_ctx = ParserContext('deploy')
390
deploy_ctx.add_arg('--env', default='staging', help='Target environment')
391
deploy_ctx.add_arg('--force', kind=bool, help='Force deployment')
392
393
test_ctx = ParserContext('test')
394
test_ctx.add_arg('--coverage', kind=bool, help='Generate coverage report')
395
test_ctx.add_arg('--pattern', help='Test pattern to run')
396
397
# Create parser with multiple contexts
398
parser = Parser([deploy_ctx, test_ctx])
399
400
# Parse different command sets
401
deploy_result = parser.parse_argv(['deploy', '--env', 'production', '--force'])
402
test_result = parser.parse_argv(['test', '--coverage', '--pattern', 'test_*.py'])
403
```
404
405
### Program Integration
406
407
```python
408
from invoke import Program, Collection, task
409
410
@task
411
def hello(ctx, name='World'):
412
"""Say hello."""
413
print(f"Hello {name}!")
414
415
@task
416
def goodbye(ctx, name='World'):
417
"""Say goodbye."""
418
print(f"Goodbye {name}!")
419
420
# Create task collection
421
ns = Collection(hello, goodbye)
422
423
# Create program
424
program = Program(name='greetings', namespace=ns, version='1.0.0')
425
426
# Run program (this handles all argument parsing)
427
if __name__ == '__main__':
428
program.run()
429
430
# CLI usage:
431
# python greetings.py hello --name John
432
# python greetings.py goodbye --name Jane
433
# python greetings.py --help
434
# python greetings.py --version
435
```
436
437
### Help Generation
438
439
```python
440
from invoke import task
441
442
@task(help={
443
'env': 'Target environment (staging, production)',
444
'force': 'Skip confirmation prompts',
445
'rollback': 'Rollback to previous version if deployment fails'
446
})
447
def deploy(ctx, env='staging', force=False, rollback=True):
448
"""
449
Deploy application to specified environment.
450
451
This command handles the complete deployment process including:
452
- Building the application
453
- Running tests
454
- Deploying to target environment
455
- Running health checks
456
"""
457
# Implementation here
458
pass
459
460
# CLI help output:
461
# invoke deploy --help
462
#
463
# Usage: invoke [--core-opts] deploy [--options] [other tasks here ...]
464
#
465
# Docstring:
466
# Deploy application to specified environment.
467
#
468
# This command handles the complete deployment process including:
469
# - Building the application
470
# - Running tests
471
# - Deploying to target environment
472
# - Running health checks
473
#
474
# Options:
475
# -e STRING, --env=STRING Target environment (staging, production)
476
# -f, --force Skip confirmation prompts
477
# -r, --rollback Rollback to previous version if deployment fails
478
```
479
480
### Error Handling
481
482
```python
483
from invoke.parser import Parser, ParserContext
484
from invoke.exceptions import ParseError
485
486
try:
487
ctx = ParserContext('task')
488
ctx.add_arg('--count', kind=int, help='Number of items')
489
490
parser = Parser([ctx])
491
result = parser.parse_argv(['task', '--count', 'not-a-number'])
492
except ParseError as e:
493
print(f"Argument parsing failed: {e}")
494
# Handle parsing error gracefully
495
```