0
# Context Management
1
2
Context objects that maintain state and configuration throughout command execution, enabling communication between commands and providing access to execution metadata.
3
4
## Capabilities
5
6
### Context Class
7
8
Core context object that maintains execution state and provides command coordination.
9
10
```python { .api }
11
class Context:
12
parent: Context | None
13
command: Command
14
info_name: str | None
15
params: dict[Any, Any]
16
args: list[str]
17
protected_args: list[str]
18
obj: Any
19
default_map: Mapping[str, Any] | None
20
invoked_subcommand: str | None
21
terminal_width: int | None
22
max_content_width: int | None
23
allow_extra_args: bool
24
allow_interspersed_args: bool
25
ignore_unknown_options: bool
26
help_option_names: list[str]
27
token_normalize_func: Callable[[str], str] | None
28
resilient_parsing: bool
29
auto_envvar_prefix: str | None
30
color: bool | None
31
32
def __init__(
33
self,
34
command: Command,
35
parent: Context | None = None,
36
info_name: str | None = None,
37
obj: Any | None = None,
38
auto_envvar_prefix: str | None = None,
39
default_map: Mapping[str, Any] | None = None,
40
terminal_width: int | None = None,
41
max_content_width: int | None = None,
42
resilient_parsing: bool = False,
43
allow_extra_args: bool | None = None,
44
allow_interspersed_args: bool | None = None,
45
ignore_unknown_options: bool | None = None,
46
help_option_names: list[str] | None = None,
47
token_normalize_func: Callable[[str], str] | None = None,
48
color: bool | None = None,
49
) -> None:
50
"""
51
Context for command execution state.
52
53
Parameters:
54
- command: Command being executed
55
- parent: Parent context for nested commands
56
- info_name: Command name for help/error messages
57
- obj: User object for passing data between commands
58
- auto_envvar_prefix: Prefix for automatic environment variables
59
- default_map: Default values mapping
60
- terminal_width: Terminal width for formatting
61
- max_content_width: Maximum content width
62
- resilient_parsing: Continue parsing despite errors
63
- allow_extra_args: Allow extra command arguments
64
- allow_interspersed_args: Allow interspersed arguments
65
- ignore_unknown_options: Ignore unknown options
66
- help_option_names: Names for help options
67
- token_normalize_func: Function to normalize option names
68
- color: Enable/disable colored output
69
"""
70
71
@property
72
def meta(self) -> dict[str, Any]:
73
"""
74
Dictionary for storing arbitrary metadata.
75
76
Returns:
77
Metadata dictionary
78
"""
79
80
@property
81
def command_path(self) -> str:
82
"""
83
Full command path from root to current command.
84
85
Returns:
86
Command path string
87
"""
88
89
def fail(self, message: str) -> NoReturn:
90
"""
91
Fail with an error message and exit.
92
93
Parameters:
94
- message: Error message
95
96
Usage:
97
if not os.path.exists(filename):
98
ctx.fail(f'File {filename} does not exist')
99
"""
100
101
def scope(self, cleanup: bool = True) -> ContextManager[Context]:
102
"""
103
Create a context manager that provides a new scope.
104
105
Parameters:
106
- cleanup: Whether to cleanup on exit
107
108
Returns:
109
Context manager for scoped execution
110
111
Usage:
112
with ctx.scope() as scope_ctx:
113
# Work in scoped context
114
scope_ctx.obj = some_data
115
"""
116
117
def make_formatter(self) -> HelpFormatter:
118
"""
119
Create a help formatter for this context.
120
121
Returns:
122
HelpFormatter instance
123
"""
124
125
def call_on_close(self, f: Callable[[], Any]) -> Callable[[], Any]:
126
"""
127
Register function to call when context closes.
128
129
Parameters:
130
- f: Function to call on close
131
132
Returns:
133
The registered function
134
135
Usage:
136
def cleanup():
137
# Cleanup resources
138
pass
139
140
ctx.call_on_close(cleanup)
141
"""
142
143
def close(self) -> None:
144
"""
145
Close the context and run cleanup callbacks.
146
147
Usage:
148
ctx.close() # Usually called automatically
149
"""
150
151
def abort(self) -> NoReturn:
152
"""
153
Abort command execution immediately.
154
155
Usage:
156
if not confirm_dangerous_operation():
157
ctx.abort()
158
"""
159
160
def exit(self, code: int | str = 0) -> NoReturn:
161
"""
162
Exit with specified code.
163
164
Parameters:
165
- code: Exit code (integer or string)
166
167
Usage:
168
if success:
169
ctx.exit(0)
170
else:
171
ctx.exit(1)
172
"""
173
174
def invoke(self, callback: Command | Callable[..., Any], *args: Any, **kwargs: Any) -> Any:
175
"""
176
Invoke another command or callback with current context.
177
178
Parameters:
179
- callback: Command or function to invoke
180
- *args: Positional arguments
181
- **kwargs: Keyword arguments
182
183
Returns:
184
Callback return value
185
186
Usage:
187
# Invoke another command
188
result = ctx.invoke(other_command, arg1='value')
189
190
# Invoke function with context
191
result = ctx.invoke(my_function, ctx, param1='value')
192
"""
193
194
def forward(self, callback: Command | Callable[..., Any], *args: Any, **kwargs: Any) -> Any:
195
"""
196
Forward to another command, replacing current context.
197
198
Parameters:
199
- callback: Command or function to forward to
200
- *args: Positional arguments
201
- **kwargs: Keyword arguments
202
203
Returns:
204
Callback return value
205
"""
206
207
def find_root(self) -> Context:
208
"""
209
Find the root context in the hierarchy.
210
211
Returns:
212
Root context
213
"""
214
215
def find_object(self, object_type: type) -> Any:
216
"""
217
Find object of specific type in context hierarchy.
218
219
Parameters:
220
- object_type: Type to search for
221
222
Returns:
223
Found object or None
224
"""
225
226
def ensure_object(self, object_type: type) -> Any:
227
"""
228
Ensure object of specific type exists in context.
229
230
Parameters:
231
- object_type: Type to ensure
232
233
Returns:
234
Found or created object
235
"""
236
237
def lookup_default(self, name: str) -> Any:
238
"""
239
Look up default value for parameter.
240
241
Parameters:
242
- name: Parameter name
243
244
Returns:
245
Default value or None
246
"""
247
248
def get_usage(self) -> str:
249
"""
250
Get usage information for current command.
251
252
Returns:
253
Usage string
254
"""
255
256
def get_help(self) -> str:
257
"""
258
Get help information for current command.
259
260
Returns:
261
Help string
262
"""
263
```
264
265
### Context Access Decorators
266
267
Decorators for accessing context and context objects in command functions.
268
269
```python { .api }
270
def pass_context(f: Callable) -> Callable:
271
"""
272
Decorator that passes the current context as first argument.
273
274
Parameters:
275
- f: Function to decorate
276
277
Returns:
278
Decorated function
279
280
Usage:
281
@click.command()
282
@click.pass_context
283
def my_command(ctx, other_args):
284
click.echo(f'Command path: {ctx.command_path}')
285
if ctx.parent:
286
click.echo('Has parent context')
287
"""
288
289
def pass_obj(f: Callable) -> Callable:
290
"""
291
Decorator that passes the context object as first argument.
292
293
Parameters:
294
- f: Function to decorate
295
296
Returns:
297
Decorated function
298
299
Usage:
300
@click.command()
301
@click.pass_obj
302
def my_command(obj, other_args):
303
click.echo(f'Object: {obj}')
304
"""
305
306
def make_pass_decorator(object_type: type, ensure: bool = False) -> Callable:
307
"""
308
Create a custom pass decorator for specific object types.
309
310
Parameters:
311
- object_type: Type of object to pass
312
- ensure: Create object if it doesn't exist
313
314
Returns:
315
Pass decorator function
316
317
Usage:
318
class Config:
319
def __init__(self):
320
self.debug = False
321
322
pass_config = click.make_pass_decorator(Config, ensure=True)
323
324
@click.command()
325
@pass_config
326
def debug_command(config):
327
config.debug = True
328
"""
329
```
330
331
### Global Context Functions
332
333
Functions for managing the global context stack.
334
335
```python { .api }
336
def get_current_context(silent: bool = False) -> Context:
337
"""
338
Get the current execution context.
339
340
Parameters:
341
- silent: Return None instead of raising if no context
342
343
Returns:
344
Current context
345
346
Raises:
347
RuntimeError: If no context and not silent
348
349
Usage:
350
def helper_function():
351
ctx = click.get_current_context()
352
ctx.fail('Something went wrong')
353
"""
354
355
def push_context(ctx: Context) -> None:
356
"""
357
Push a context onto the stack.
358
359
Parameters:
360
- ctx: Context to push
361
362
Usage:
363
# Rarely used directly - handled by click framework
364
click.push_context(new_context)
365
"""
366
367
def pop_context() -> None:
368
"""
369
Pop the current context from the stack.
370
371
Usage:
372
# Rarely used directly - handled by click framework
373
click.pop_context()
374
"""
375
```
376
377
### Context Utilities
378
379
Utility functions for context management.
380
381
```python { .api }
382
def resolve_color_default(color: bool | None = None) -> bool | None:
383
"""
384
Resolve color default based on context and environment.
385
386
Parameters:
387
- color: Explicit color setting
388
389
Returns:
390
Resolved color setting
391
392
Usage:
393
# Used internally by click for color handling
394
color_enabled = click.resolve_color_default(color)
395
"""
396
```
397
398
### Context Usage Patterns
399
400
**Sharing Data Between Commands:**
401
402
```python
403
@click.group()
404
@click.option('--config', type=click.Path(exists=True))
405
@click.pass_context
406
def cli(ctx, config):
407
"""Main CLI with shared configuration."""
408
ctx.ensure_object(dict)
409
if config:
410
with open(config) as f:
411
ctx.obj = json.load(f)
412
else:
413
ctx.obj = {}
414
415
@cli.command()
416
@click.pass_obj
417
def status(config):
418
"""Show status using shared config."""
419
debug = config.get('debug', False)
420
if debug:
421
click.echo('Debug mode enabled')
422
click.echo('Status: OK')
423
```
424
425
**Custom Context Objects:**
426
427
```python
428
class AppContext:
429
def __init__(self):
430
self.debug = False
431
self.database_url = None
432
433
def get_db_connection(self):
434
# Database connection logic
435
pass
436
437
pass_app_context = click.make_pass_decorator(AppContext, ensure=True)
438
439
@click.group()
440
@click.option('--debug', is_flag=True)
441
@pass_app_context
442
def cli(app_ctx, debug):
443
app_ctx.debug = debug
444
445
@cli.command()
446
@pass_app_context
447
def migrate(app_ctx):
448
db = app_ctx.get_db_connection()
449
if app_ctx.debug:
450
click.echo('Running migrations in debug mode')
451
```
452
453
**Error Handling with Context:**
454
455
```python
456
@click.command()
457
@click.argument('filename')
458
@click.pass_context
459
def process_file(ctx, filename):
460
if not os.path.exists(filename):
461
ctx.fail(f'File {filename} does not exist')
462
463
try:
464
# Process file
465
with open(filename) as f:
466
data = f.read()
467
except PermissionError:
468
ctx.fail(f'Permission denied: {filename}')
469
except Exception as e:
470
ctx.fail(f'Error processing file: {e}')
471
```
472
473
## Utility Functions
474
475
Internal utility functions for context and parameter processing.
476
477
```python { .api }
478
def invoke_param_callback(
479
callback: Callable[[Context, Parameter, str | None], Any],
480
ctx: Context,
481
param: Parameter,
482
value: str | None,
483
) -> Any:
484
"""
485
Invoke a parameter callback function safely.
486
487
Parameters:
488
- callback: Parameter callback function
489
- ctx: Current context
490
- param: Parameter being processed
491
- value: Parameter value
492
493
Returns:
494
Result of callback invocation
495
496
Usage:
497
# Internal use - rarely needed in user code
498
result = click.invoke_param_callback(my_callback, ctx, param, value)
499
"""
500
501
def augment_usage_errors(
502
ctx: Context,
503
param: Parameter | None = None
504
) -> ContextManager[None]:
505
"""
506
Context manager to enhance usage error messages.
507
508
Parameters:
509
- ctx: Current context
510
- param: Parameter that caused the error (optional)
511
512
Usage:
513
# Internal use - enhances error reporting
514
with click.augment_usage_errors(ctx, param):
515
# Parameter processing that might fail
516
process_parameter_value()
517
"""
518
519
def iter_params_for_processing(
520
invocation_order: Sequence[Parameter],
521
declaration_order: Iterable[Parameter],
522
) -> Iterable[Parameter]:
523
"""
524
Iterate parameters in proper processing order.
525
526
Parameters:
527
- invocation_order: Order parameters were invoked
528
- declaration_order: Order parameters were declared
529
530
Yields:
531
Parameters in processing order
532
533
Usage:
534
# Internal use - parameter processing order
535
for param in click.iter_params_for_processing(invoked, declared):
536
process_parameter(param)
537
"""
538
```