outerbounds 0.3.68__py3-none-any.whl → 0.3.104__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. outerbounds/_vendor/PyYAML.LICENSE +20 -0
  2. outerbounds/_vendor/__init__.py +0 -0
  3. outerbounds/_vendor/_yaml/__init__.py +34 -0
  4. outerbounds/_vendor/click/__init__.py +73 -0
  5. outerbounds/_vendor/click/_compat.py +626 -0
  6. outerbounds/_vendor/click/_termui_impl.py +717 -0
  7. outerbounds/_vendor/click/_textwrap.py +49 -0
  8. outerbounds/_vendor/click/_winconsole.py +279 -0
  9. outerbounds/_vendor/click/core.py +2998 -0
  10. outerbounds/_vendor/click/decorators.py +497 -0
  11. outerbounds/_vendor/click/exceptions.py +287 -0
  12. outerbounds/_vendor/click/formatting.py +301 -0
  13. outerbounds/_vendor/click/globals.py +68 -0
  14. outerbounds/_vendor/click/parser.py +529 -0
  15. outerbounds/_vendor/click/py.typed +0 -0
  16. outerbounds/_vendor/click/shell_completion.py +580 -0
  17. outerbounds/_vendor/click/termui.py +787 -0
  18. outerbounds/_vendor/click/testing.py +479 -0
  19. outerbounds/_vendor/click/types.py +1073 -0
  20. outerbounds/_vendor/click/utils.py +580 -0
  21. outerbounds/_vendor/click.LICENSE +28 -0
  22. outerbounds/_vendor/vendor_any.txt +2 -0
  23. outerbounds/_vendor/yaml/__init__.py +471 -0
  24. outerbounds/_vendor/yaml/_yaml.cpython-311-darwin.so +0 -0
  25. outerbounds/_vendor/yaml/composer.py +146 -0
  26. outerbounds/_vendor/yaml/constructor.py +862 -0
  27. outerbounds/_vendor/yaml/cyaml.py +177 -0
  28. outerbounds/_vendor/yaml/dumper.py +138 -0
  29. outerbounds/_vendor/yaml/emitter.py +1239 -0
  30. outerbounds/_vendor/yaml/error.py +94 -0
  31. outerbounds/_vendor/yaml/events.py +104 -0
  32. outerbounds/_vendor/yaml/loader.py +62 -0
  33. outerbounds/_vendor/yaml/nodes.py +51 -0
  34. outerbounds/_vendor/yaml/parser.py +629 -0
  35. outerbounds/_vendor/yaml/reader.py +208 -0
  36. outerbounds/_vendor/yaml/representer.py +378 -0
  37. outerbounds/_vendor/yaml/resolver.py +245 -0
  38. outerbounds/_vendor/yaml/scanner.py +1555 -0
  39. outerbounds/_vendor/yaml/serializer.py +127 -0
  40. outerbounds/_vendor/yaml/tokens.py +129 -0
  41. outerbounds/command_groups/apps_cli.py +586 -0
  42. outerbounds/command_groups/cli.py +9 -5
  43. outerbounds/command_groups/local_setup_cli.py +1 -5
  44. outerbounds/command_groups/perimeters_cli.py +198 -25
  45. outerbounds/command_groups/tutorials_cli.py +111 -0
  46. outerbounds/command_groups/workstations_cli.py +2 -2
  47. outerbounds/utils/kubeconfig.py +2 -2
  48. outerbounds/utils/metaflowconfig.py +68 -9
  49. outerbounds/utils/schema.py +2 -2
  50. outerbounds/utils/utils.py +19 -0
  51. outerbounds/vendor.py +159 -0
  52. {outerbounds-0.3.68.dist-info → outerbounds-0.3.104.dist-info}/METADATA +14 -7
  53. outerbounds-0.3.104.dist-info/RECORD +59 -0
  54. {outerbounds-0.3.68.dist-info → outerbounds-0.3.104.dist-info}/WHEEL +1 -1
  55. outerbounds-0.3.68.dist-info/RECORD +0 -15
  56. {outerbounds-0.3.68.dist-info → outerbounds-0.3.104.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,2998 @@
1
+ import enum
2
+ import errno
3
+ import inspect
4
+ import os
5
+ import sys
6
+ import typing as t
7
+ from collections import abc
8
+ from contextlib import contextmanager
9
+ from contextlib import ExitStack
10
+ from functools import partial
11
+ from functools import update_wrapper
12
+ from gettext import gettext as _
13
+ from gettext import ngettext
14
+ from itertools import repeat
15
+
16
+ from . import types
17
+ from .exceptions import Abort
18
+ from .exceptions import BadParameter
19
+ from .exceptions import ClickException
20
+ from .exceptions import Exit
21
+ from .exceptions import MissingParameter
22
+ from .exceptions import UsageError
23
+ from .formatting import HelpFormatter
24
+ from .formatting import join_options
25
+ from .globals import pop_context
26
+ from .globals import push_context
27
+ from .parser import _flag_needs_value
28
+ from .parser import OptionParser
29
+ from .parser import split_opt
30
+ from .termui import confirm
31
+ from .termui import prompt
32
+ from .termui import style
33
+ from .utils import _detect_program_name
34
+ from .utils import _expand_args
35
+ from .utils import echo
36
+ from .utils import make_default_short_help
37
+ from .utils import make_str
38
+ from .utils import PacifyFlushWrapper
39
+
40
+ if t.TYPE_CHECKING:
41
+ import typing_extensions as te
42
+ from .shell_completion import CompletionItem
43
+
44
+ F = t.TypeVar("F", bound=t.Callable[..., t.Any])
45
+ V = t.TypeVar("V")
46
+
47
+
48
+ def _complete_visible_commands(
49
+ ctx: "Context", incomplete: str
50
+ ) -> t.Iterator[t.Tuple[str, "Command"]]:
51
+ """List all the subcommands of a group that start with the
52
+ incomplete value and aren't hidden.
53
+
54
+ :param ctx: Invocation context for the group.
55
+ :param incomplete: Value being completed. May be empty.
56
+ """
57
+ multi = t.cast(MultiCommand, ctx.command)
58
+
59
+ for name in multi.list_commands(ctx):
60
+ if name.startswith(incomplete):
61
+ command = multi.get_command(ctx, name)
62
+
63
+ if command is not None and not command.hidden:
64
+ yield name, command
65
+
66
+
67
+ def _check_multicommand(
68
+ base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False
69
+ ) -> None:
70
+ if not base_command.chain or not isinstance(cmd, MultiCommand):
71
+ return
72
+ if register:
73
+ hint = (
74
+ "It is not possible to add multi commands as children to"
75
+ " another multi command that is in chain mode."
76
+ )
77
+ else:
78
+ hint = (
79
+ "Found a multi command as subcommand to a multi command"
80
+ " that is in chain mode. This is not supported."
81
+ )
82
+ raise RuntimeError(
83
+ f"{hint}. Command {base_command.name!r} is set to chain and"
84
+ f" {cmd_name!r} was added as a subcommand but it in itself is a"
85
+ f" multi command. ({cmd_name!r} is a {type(cmd).__name__}"
86
+ f" within a chained {type(base_command).__name__} named"
87
+ f" {base_command.name!r})."
88
+ )
89
+
90
+
91
+ def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]:
92
+ return list(zip(*repeat(iter(iterable), batch_size)))
93
+
94
+
95
+ @contextmanager
96
+ def augment_usage_errors(
97
+ ctx: "Context", param: t.Optional["Parameter"] = None
98
+ ) -> t.Iterator[None]:
99
+ """Context manager that attaches extra information to exceptions."""
100
+ try:
101
+ yield
102
+ except BadParameter as e:
103
+ if e.ctx is None:
104
+ e.ctx = ctx
105
+ if param is not None and e.param is None:
106
+ e.param = param
107
+ raise
108
+ except UsageError as e:
109
+ if e.ctx is None:
110
+ e.ctx = ctx
111
+ raise
112
+
113
+
114
+ def iter_params_for_processing(
115
+ invocation_order: t.Sequence["Parameter"],
116
+ declaration_order: t.Sequence["Parameter"],
117
+ ) -> t.List["Parameter"]:
118
+ """Given a sequence of parameters in the order as should be considered
119
+ for processing and an iterable of parameters that exist, this returns
120
+ a list in the correct order as they should be processed.
121
+ """
122
+
123
+ def sort_key(item: "Parameter") -> t.Tuple[bool, float]:
124
+ try:
125
+ idx: float = invocation_order.index(item)
126
+ except ValueError:
127
+ idx = float("inf")
128
+
129
+ return not item.is_eager, idx
130
+
131
+ return sorted(declaration_order, key=sort_key)
132
+
133
+
134
+ class ParameterSource(enum.Enum):
135
+ """This is an :class:`~enum.Enum` that indicates the source of a
136
+ parameter's value.
137
+
138
+ Use :meth:`click.Context.get_parameter_source` to get the
139
+ source for a parameter by name.
140
+
141
+ .. versionchanged:: 8.0
142
+ Use :class:`~enum.Enum` and drop the ``validate`` method.
143
+
144
+ .. versionchanged:: 8.0
145
+ Added the ``PROMPT`` value.
146
+ """
147
+
148
+ COMMANDLINE = enum.auto()
149
+ """The value was provided by the command line args."""
150
+ ENVIRONMENT = enum.auto()
151
+ """The value was provided with an environment variable."""
152
+ DEFAULT = enum.auto()
153
+ """Used the default specified by the parameter."""
154
+ DEFAULT_MAP = enum.auto()
155
+ """Used a default provided by :attr:`Context.default_map`."""
156
+ PROMPT = enum.auto()
157
+ """Used a prompt to confirm a default or provide a value."""
158
+
159
+
160
+ class Context:
161
+ """The context is a special internal object that holds state relevant
162
+ for the script execution at every single level. It's normally invisible
163
+ to commands unless they opt-in to getting access to it.
164
+
165
+ The context is useful as it can pass internal objects around and can
166
+ control special execution features such as reading data from
167
+ environment variables.
168
+
169
+ A context can be used as context manager in which case it will call
170
+ :meth:`close` on teardown.
171
+
172
+ :param command: the command class for this context.
173
+ :param parent: the parent context.
174
+ :param info_name: the info name for this invocation. Generally this
175
+ is the most descriptive name for the script or
176
+ command. For the toplevel script it is usually
177
+ the name of the script, for commands below it it's
178
+ the name of the script.
179
+ :param obj: an arbitrary object of user data.
180
+ :param auto_envvar_prefix: the prefix to use for automatic environment
181
+ variables. If this is `None` then reading
182
+ from environment variables is disabled. This
183
+ does not affect manually set environment
184
+ variables which are always read.
185
+ :param default_map: a dictionary (like object) with default values
186
+ for parameters.
187
+ :param terminal_width: the width of the terminal. The default is
188
+ inherit from parent context. If no context
189
+ defines the terminal width then auto
190
+ detection will be applied.
191
+ :param max_content_width: the maximum width for content rendered by
192
+ Click (this currently only affects help
193
+ pages). This defaults to 80 characters if
194
+ not overridden. In other words: even if the
195
+ terminal is larger than that, Click will not
196
+ format things wider than 80 characters by
197
+ default. In addition to that, formatters might
198
+ add some safety mapping on the right.
199
+ :param resilient_parsing: if this flag is enabled then Click will
200
+ parse without any interactivity or callback
201
+ invocation. Default values will also be
202
+ ignored. This is useful for implementing
203
+ things such as completion support.
204
+ :param allow_extra_args: if this is set to `True` then extra arguments
205
+ at the end will not raise an error and will be
206
+ kept on the context. The default is to inherit
207
+ from the command.
208
+ :param allow_interspersed_args: if this is set to `False` then options
209
+ and arguments cannot be mixed. The
210
+ default is to inherit from the command.
211
+ :param ignore_unknown_options: instructs click to ignore options it does
212
+ not know and keeps them for later
213
+ processing.
214
+ :param help_option_names: optionally a list of strings that define how
215
+ the default help parameter is named. The
216
+ default is ``['--help']``.
217
+ :param token_normalize_func: an optional function that is used to
218
+ normalize tokens (options, choices,
219
+ etc.). This for instance can be used to
220
+ implement case insensitive behavior.
221
+ :param color: controls if the terminal supports ANSI colors or not. The
222
+ default is autodetection. This is only needed if ANSI
223
+ codes are used in texts that Click prints which is by
224
+ default not the case. This for instance would affect
225
+ help output.
226
+ :param show_default: Show the default value for commands. If this
227
+ value is not set, it defaults to the value from the parent
228
+ context. ``Command.show_default`` overrides this default for the
229
+ specific command.
230
+
231
+ .. versionchanged:: 8.1
232
+ The ``show_default`` parameter is overridden by
233
+ ``Command.show_default``, instead of the other way around.
234
+
235
+ .. versionchanged:: 8.0
236
+ The ``show_default`` parameter defaults to the value from the
237
+ parent context.
238
+
239
+ .. versionchanged:: 7.1
240
+ Added the ``show_default`` parameter.
241
+
242
+ .. versionchanged:: 4.0
243
+ Added the ``color``, ``ignore_unknown_options``, and
244
+ ``max_content_width`` parameters.
245
+
246
+ .. versionchanged:: 3.0
247
+ Added the ``allow_extra_args`` and ``allow_interspersed_args``
248
+ parameters.
249
+
250
+ .. versionchanged:: 2.0
251
+ Added the ``resilient_parsing``, ``help_option_names``, and
252
+ ``token_normalize_func`` parameters.
253
+ """
254
+
255
+ #: The formatter class to create with :meth:`make_formatter`.
256
+ #:
257
+ #: .. versionadded:: 8.0
258
+ formatter_class: t.Type["HelpFormatter"] = HelpFormatter
259
+
260
+ def __init__(
261
+ self,
262
+ command: "Command",
263
+ parent: t.Optional["Context"] = None,
264
+ info_name: t.Optional[str] = None,
265
+ obj: t.Optional[t.Any] = None,
266
+ auto_envvar_prefix: t.Optional[str] = None,
267
+ default_map: t.Optional[t.Dict[str, t.Any]] = None,
268
+ terminal_width: t.Optional[int] = None,
269
+ max_content_width: t.Optional[int] = None,
270
+ resilient_parsing: bool = False,
271
+ allow_extra_args: t.Optional[bool] = None,
272
+ allow_interspersed_args: t.Optional[bool] = None,
273
+ ignore_unknown_options: t.Optional[bool] = None,
274
+ help_option_names: t.Optional[t.List[str]] = None,
275
+ token_normalize_func: t.Optional[t.Callable[[str], str]] = None,
276
+ color: t.Optional[bool] = None,
277
+ show_default: t.Optional[bool] = None,
278
+ ) -> None:
279
+ #: the parent context or `None` if none exists.
280
+ self.parent = parent
281
+ #: the :class:`Command` for this context.
282
+ self.command = command
283
+ #: the descriptive information name
284
+ self.info_name = info_name
285
+ #: Map of parameter names to their parsed values. Parameters
286
+ #: with ``expose_value=False`` are not stored.
287
+ self.params: t.Dict[str, t.Any] = {}
288
+ #: the leftover arguments.
289
+ self.args: t.List[str] = []
290
+ #: protected arguments. These are arguments that are prepended
291
+ #: to `args` when certain parsing scenarios are encountered but
292
+ #: must be never propagated to another arguments. This is used
293
+ #: to implement nested parsing.
294
+ self.protected_args: t.List[str] = []
295
+ #: the collected prefixes of the command's options.
296
+ self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set()
297
+
298
+ if obj is None and parent is not None:
299
+ obj = parent.obj
300
+
301
+ #: the user object stored.
302
+ self.obj: t.Any = obj
303
+ self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {})
304
+
305
+ #: A dictionary (-like object) with defaults for parameters.
306
+ if (
307
+ default_map is None
308
+ and info_name is not None
309
+ and parent is not None
310
+ and parent.default_map is not None
311
+ ):
312
+ default_map = parent.default_map.get(info_name)
313
+
314
+ self.default_map: t.Optional[t.Dict[str, t.Any]] = default_map
315
+
316
+ #: This flag indicates if a subcommand is going to be executed. A
317
+ #: group callback can use this information to figure out if it's
318
+ #: being executed directly or because the execution flow passes
319
+ #: onwards to a subcommand. By default it's None, but it can be
320
+ #: the name of the subcommand to execute.
321
+ #:
322
+ #: If chaining is enabled this will be set to ``'*'`` in case
323
+ #: any commands are executed. It is however not possible to
324
+ #: figure out which ones. If you require this knowledge you
325
+ #: should use a :func:`result_callback`.
326
+ self.invoked_subcommand: t.Optional[str] = None
327
+
328
+ if terminal_width is None and parent is not None:
329
+ terminal_width = parent.terminal_width
330
+
331
+ #: The width of the terminal (None is autodetection).
332
+ self.terminal_width: t.Optional[int] = terminal_width
333
+
334
+ if max_content_width is None and parent is not None:
335
+ max_content_width = parent.max_content_width
336
+
337
+ #: The maximum width of formatted content (None implies a sensible
338
+ #: default which is 80 for most things).
339
+ self.max_content_width: t.Optional[int] = max_content_width
340
+
341
+ if allow_extra_args is None:
342
+ allow_extra_args = command.allow_extra_args
343
+
344
+ #: Indicates if the context allows extra args or if it should
345
+ #: fail on parsing.
346
+ #:
347
+ #: .. versionadded:: 3.0
348
+ self.allow_extra_args = allow_extra_args
349
+
350
+ if allow_interspersed_args is None:
351
+ allow_interspersed_args = command.allow_interspersed_args
352
+
353
+ #: Indicates if the context allows mixing of arguments and
354
+ #: options or not.
355
+ #:
356
+ #: .. versionadded:: 3.0
357
+ self.allow_interspersed_args: bool = allow_interspersed_args
358
+
359
+ if ignore_unknown_options is None:
360
+ ignore_unknown_options = command.ignore_unknown_options
361
+
362
+ #: Instructs click to ignore options that a command does not
363
+ #: understand and will store it on the context for later
364
+ #: processing. This is primarily useful for situations where you
365
+ #: want to call into external programs. Generally this pattern is
366
+ #: strongly discouraged because it's not possibly to losslessly
367
+ #: forward all arguments.
368
+ #:
369
+ #: .. versionadded:: 4.0
370
+ self.ignore_unknown_options: bool = ignore_unknown_options
371
+
372
+ if help_option_names is None:
373
+ if parent is not None:
374
+ help_option_names = parent.help_option_names
375
+ else:
376
+ help_option_names = ["--help"]
377
+
378
+ #: The names for the help options.
379
+ self.help_option_names: t.List[str] = help_option_names
380
+
381
+ if token_normalize_func is None and parent is not None:
382
+ token_normalize_func = parent.token_normalize_func
383
+
384
+ #: An optional normalization function for tokens. This is
385
+ #: options, choices, commands etc.
386
+ self.token_normalize_func: t.Optional[
387
+ t.Callable[[str], str]
388
+ ] = token_normalize_func
389
+
390
+ #: Indicates if resilient parsing is enabled. In that case Click
391
+ #: will do its best to not cause any failures and default values
392
+ #: will be ignored. Useful for completion.
393
+ self.resilient_parsing: bool = resilient_parsing
394
+
395
+ # If there is no envvar prefix yet, but the parent has one and
396
+ # the command on this level has a name, we can expand the envvar
397
+ # prefix automatically.
398
+ if auto_envvar_prefix is None:
399
+ if (
400
+ parent is not None
401
+ and parent.auto_envvar_prefix is not None
402
+ and self.info_name is not None
403
+ ):
404
+ auto_envvar_prefix = (
405
+ f"{parent.auto_envvar_prefix}_{self.info_name.upper()}"
406
+ )
407
+ else:
408
+ auto_envvar_prefix = auto_envvar_prefix.upper()
409
+
410
+ if auto_envvar_prefix is not None:
411
+ auto_envvar_prefix = auto_envvar_prefix.replace("-", "_")
412
+
413
+ self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix
414
+
415
+ if color is None and parent is not None:
416
+ color = parent.color
417
+
418
+ #: Controls if styling output is wanted or not.
419
+ self.color: t.Optional[bool] = color
420
+
421
+ if show_default is None and parent is not None:
422
+ show_default = parent.show_default
423
+
424
+ #: Show option default values when formatting help text.
425
+ self.show_default: t.Optional[bool] = show_default
426
+
427
+ self._close_callbacks: t.List[t.Callable[[], t.Any]] = []
428
+ self._depth = 0
429
+ self._parameter_source: t.Dict[str, ParameterSource] = {}
430
+ self._exit_stack = ExitStack()
431
+
432
+ def to_info_dict(self) -> t.Dict[str, t.Any]:
433
+ """Gather information that could be useful for a tool generating
434
+ user-facing documentation. This traverses the entire CLI
435
+ structure.
436
+
437
+ .. code-block:: python
438
+
439
+ with Context(cli) as ctx:
440
+ info = ctx.to_info_dict()
441
+
442
+ .. versionadded:: 8.0
443
+ """
444
+ return {
445
+ "command": self.command.to_info_dict(self),
446
+ "info_name": self.info_name,
447
+ "allow_extra_args": self.allow_extra_args,
448
+ "allow_interspersed_args": self.allow_interspersed_args,
449
+ "ignore_unknown_options": self.ignore_unknown_options,
450
+ "auto_envvar_prefix": self.auto_envvar_prefix,
451
+ }
452
+
453
+ def __enter__(self) -> "Context":
454
+ self._depth += 1
455
+ push_context(self)
456
+ return self
457
+
458
+ def __exit__(self, exc_type, exc_value, tb): # type: ignore
459
+ self._depth -= 1
460
+ if self._depth == 0:
461
+ self.close()
462
+ pop_context()
463
+
464
+ @contextmanager
465
+ def scope(self, cleanup: bool = True) -> t.Iterator["Context"]:
466
+ """This helper method can be used with the context object to promote
467
+ it to the current thread local (see :func:`get_current_context`).
468
+ The default behavior of this is to invoke the cleanup functions which
469
+ can be disabled by setting `cleanup` to `False`. The cleanup
470
+ functions are typically used for things such as closing file handles.
471
+
472
+ If the cleanup is intended the context object can also be directly
473
+ used as a context manager.
474
+
475
+ Example usage::
476
+
477
+ with ctx.scope():
478
+ assert get_current_context() is ctx
479
+
480
+ This is equivalent::
481
+
482
+ with ctx:
483
+ assert get_current_context() is ctx
484
+
485
+ .. versionadded:: 5.0
486
+
487
+ :param cleanup: controls if the cleanup functions should be run or
488
+ not. The default is to run these functions. In
489
+ some situations the context only wants to be
490
+ temporarily pushed in which case this can be disabled.
491
+ Nested pushes automatically defer the cleanup.
492
+ """
493
+ if not cleanup:
494
+ self._depth += 1
495
+ try:
496
+ with self as rv:
497
+ yield rv
498
+ finally:
499
+ if not cleanup:
500
+ self._depth -= 1
501
+
502
+ @property
503
+ def meta(self) -> t.Dict[str, t.Any]:
504
+ """This is a dictionary which is shared with all the contexts
505
+ that are nested. It exists so that click utilities can store some
506
+ state here if they need to. It is however the responsibility of
507
+ that code to manage this dictionary well.
508
+
509
+ The keys are supposed to be unique dotted strings. For instance
510
+ module paths are a good choice for it. What is stored in there is
511
+ irrelevant for the operation of click. However what is important is
512
+ that code that places data here adheres to the general semantics of
513
+ the system.
514
+
515
+ Example usage::
516
+
517
+ LANG_KEY = f'{__name__}.lang'
518
+
519
+ def set_language(value):
520
+ ctx = get_current_context()
521
+ ctx.meta[LANG_KEY] = value
522
+
523
+ def get_language():
524
+ return get_current_context().meta.get(LANG_KEY, 'en_US')
525
+
526
+ .. versionadded:: 5.0
527
+ """
528
+ return self._meta
529
+
530
+ def make_formatter(self) -> HelpFormatter:
531
+ """Creates the :class:`~click.HelpFormatter` for the help and
532
+ usage output.
533
+
534
+ To quickly customize the formatter class used without overriding
535
+ this method, set the :attr:`formatter_class` attribute.
536
+
537
+ .. versionchanged:: 8.0
538
+ Added the :attr:`formatter_class` attribute.
539
+ """
540
+ return self.formatter_class(
541
+ width=self.terminal_width, max_width=self.max_content_width
542
+ )
543
+
544
+ def with_resource(self, context_manager: t.ContextManager[V]) -> V:
545
+ """Register a resource as if it were used in a ``with``
546
+ statement. The resource will be cleaned up when the context is
547
+ popped.
548
+
549
+ Uses :meth:`contextlib.ExitStack.enter_context`. It calls the
550
+ resource's ``__enter__()`` method and returns the result. When
551
+ the context is popped, it closes the stack, which calls the
552
+ resource's ``__exit__()`` method.
553
+
554
+ To register a cleanup function for something that isn't a
555
+ context manager, use :meth:`call_on_close`. Or use something
556
+ from :mod:`contextlib` to turn it into a context manager first.
557
+
558
+ .. code-block:: python
559
+
560
+ @click.group()
561
+ @click.option("--name")
562
+ @click.pass_context
563
+ def cli(ctx):
564
+ ctx.obj = ctx.with_resource(connect_db(name))
565
+
566
+ :param context_manager: The context manager to enter.
567
+ :return: Whatever ``context_manager.__enter__()`` returns.
568
+
569
+ .. versionadded:: 8.0
570
+ """
571
+ return self._exit_stack.enter_context(context_manager)
572
+
573
+ def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]:
574
+ """Register a function to be called when the context tears down.
575
+
576
+ This can be used to close resources opened during the script
577
+ execution. Resources that support Python's context manager
578
+ protocol which would be used in a ``with`` statement should be
579
+ registered with :meth:`with_resource` instead.
580
+
581
+ :param f: The function to execute on teardown.
582
+ """
583
+ return self._exit_stack.callback(f)
584
+
585
+ def close(self) -> None:
586
+ """Invoke all close callbacks registered with
587
+ :meth:`call_on_close`, and exit all context managers entered
588
+ with :meth:`with_resource`.
589
+ """
590
+ self._exit_stack.close()
591
+ # In case the context is reused, create a new exit stack.
592
+ self._exit_stack = ExitStack()
593
+
594
+ @property
595
+ def command_path(self) -> str:
596
+ """The computed command path. This is used for the ``usage``
597
+ information on the help page. It's automatically created by
598
+ combining the info names of the chain of contexts to the root.
599
+ """
600
+ rv = ""
601
+ if self.info_name is not None:
602
+ rv = self.info_name
603
+ if self.parent is not None:
604
+ parent_command_path = [self.parent.command_path]
605
+
606
+ if isinstance(self.parent.command, Command):
607
+ for param in self.parent.command.get_params(self):
608
+ parent_command_path.extend(param.get_usage_pieces(self))
609
+
610
+ rv = f"{' '.join(parent_command_path)} {rv}"
611
+ return rv.lstrip()
612
+
613
+ def find_root(self) -> "Context":
614
+ """Finds the outermost context."""
615
+ node = self
616
+ while node.parent is not None:
617
+ node = node.parent
618
+ return node
619
+
620
+ def find_object(self, object_type: t.Type[V]) -> t.Optional[V]:
621
+ """Finds the closest object of a given type."""
622
+ node: t.Optional["Context"] = self
623
+
624
+ while node is not None:
625
+ if isinstance(node.obj, object_type):
626
+ return node.obj
627
+
628
+ node = node.parent
629
+
630
+ return None
631
+
632
+ def ensure_object(self, object_type: t.Type[V]) -> V:
633
+ """Like :meth:`find_object` but sets the innermost object to a
634
+ new instance of `object_type` if it does not exist.
635
+ """
636
+ rv = self.find_object(object_type)
637
+ if rv is None:
638
+ self.obj = rv = object_type()
639
+ return rv
640
+
641
+ @t.overload
642
+ def lookup_default(
643
+ self, name: str, call: "te.Literal[True]" = True
644
+ ) -> t.Optional[t.Any]:
645
+ ...
646
+
647
+ @t.overload
648
+ def lookup_default(
649
+ self, name: str, call: "te.Literal[False]" = ...
650
+ ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]:
651
+ ...
652
+
653
+ def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]:
654
+ """Get the default for a parameter from :attr:`default_map`.
655
+
656
+ :param name: Name of the parameter.
657
+ :param call: If the default is a callable, call it. Disable to
658
+ return the callable instead.
659
+
660
+ .. versionchanged:: 8.0
661
+ Added the ``call`` parameter.
662
+ """
663
+ if self.default_map is not None:
664
+ value = self.default_map.get(name)
665
+
666
+ if call and callable(value):
667
+ return value()
668
+
669
+ return value
670
+
671
+ return None
672
+
673
+ def fail(self, message: str) -> "te.NoReturn":
674
+ """Aborts the execution of the program with a specific error
675
+ message.
676
+
677
+ :param message: the error message to fail with.
678
+ """
679
+ raise UsageError(message, self)
680
+
681
+ def abort(self) -> "te.NoReturn":
682
+ """Aborts the script."""
683
+ raise Abort()
684
+
685
+ def exit(self, code: int = 0) -> "te.NoReturn":
686
+ """Exits the application with a given exit code."""
687
+ raise Exit(code)
688
+
689
+ def get_usage(self) -> str:
690
+ """Helper method to get formatted usage string for the current
691
+ context and command.
692
+ """
693
+ return self.command.get_usage(self)
694
+
695
+ def get_help(self) -> str:
696
+ """Helper method to get formatted help page for the current
697
+ context and command.
698
+ """
699
+ return self.command.get_help(self)
700
+
701
+ def _make_sub_context(self, command: "Command") -> "Context":
702
+ """Create a new context of the same type as this context, but
703
+ for a new command.
704
+
705
+ :meta private:
706
+ """
707
+ return type(self)(command, info_name=command.name, parent=self)
708
+
709
+ def invoke(
710
+ __self, # noqa: B902
711
+ __callback: t.Union["Command", t.Callable[..., t.Any]],
712
+ *args: t.Any,
713
+ **kwargs: t.Any,
714
+ ) -> t.Any:
715
+ """Invokes a command callback in exactly the way it expects. There
716
+ are two ways to invoke this method:
717
+
718
+ 1. the first argument can be a callback and all other arguments and
719
+ keyword arguments are forwarded directly to the function.
720
+ 2. the first argument is a click command object. In that case all
721
+ arguments are forwarded as well but proper click parameters
722
+ (options and click arguments) must be keyword arguments and Click
723
+ will fill in defaults.
724
+
725
+ Note that before Click 3.2 keyword arguments were not properly filled
726
+ in against the intention of this code and no context was created. For
727
+ more information about this change and why it was done in a bugfix
728
+ release see :ref:`upgrade-to-3.2`.
729
+
730
+ .. versionchanged:: 8.0
731
+ All ``kwargs`` are tracked in :attr:`params` so they will be
732
+ passed if :meth:`forward` is called at multiple levels.
733
+ """
734
+ if isinstance(__callback, Command):
735
+ other_cmd = __callback
736
+
737
+ if other_cmd.callback is None:
738
+ raise TypeError(
739
+ "The given command does not have a callback that can be invoked."
740
+ )
741
+ else:
742
+ __callback = other_cmd.callback
743
+
744
+ ctx = __self._make_sub_context(other_cmd)
745
+
746
+ for param in other_cmd.params:
747
+ if param.name not in kwargs and param.expose_value:
748
+ kwargs[param.name] = param.type_cast_value( # type: ignore
749
+ ctx, param.get_default(ctx)
750
+ )
751
+
752
+ # Track all kwargs as params, so that forward() will pass
753
+ # them on in subsequent calls.
754
+ ctx.params.update(kwargs)
755
+ else:
756
+ ctx = __self
757
+
758
+ with augment_usage_errors(__self):
759
+ with ctx:
760
+ return __callback(*args, **kwargs)
761
+
762
+ def forward(
763
+ __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902
764
+ ) -> t.Any:
765
+ """Similar to :meth:`invoke` but fills in default keyword
766
+ arguments from the current context if the other command expects
767
+ it. This cannot invoke callbacks directly, only other commands.
768
+
769
+ .. versionchanged:: 8.0
770
+ All ``kwargs`` are tracked in :attr:`params` so they will be
771
+ passed if ``forward`` is called at multiple levels.
772
+ """
773
+ # Can only forward to other commands, not direct callbacks.
774
+ if not isinstance(__cmd, Command):
775
+ raise TypeError("Callback is not a command.")
776
+
777
+ for param in __self.params:
778
+ if param not in kwargs:
779
+ kwargs[param] = __self.params[param]
780
+
781
+ return __self.invoke(__cmd, *args, **kwargs)
782
+
783
+ def set_parameter_source(self, name: str, source: ParameterSource) -> None:
784
+ """Set the source of a parameter. This indicates the location
785
+ from which the value of the parameter was obtained.
786
+
787
+ :param name: The name of the parameter.
788
+ :param source: A member of :class:`~click.core.ParameterSource`.
789
+ """
790
+ self._parameter_source[name] = source
791
+
792
+ def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]:
793
+ """Get the source of a parameter. This indicates the location
794
+ from which the value of the parameter was obtained.
795
+
796
+ This can be useful for determining when a user specified a value
797
+ on the command line that is the same as the default value. It
798
+ will be :attr:`~click.core.ParameterSource.DEFAULT` only if the
799
+ value was actually taken from the default.
800
+
801
+ :param name: The name of the parameter.
802
+ :rtype: ParameterSource
803
+
804
+ .. versionchanged:: 8.0
805
+ Returns ``None`` if the parameter was not provided from any
806
+ source.
807
+ """
808
+ return self._parameter_source.get(name)
809
+
810
+
811
+ class BaseCommand:
812
+ """The base command implements the minimal API contract of commands.
813
+ Most code will never use this as it does not implement a lot of useful
814
+ functionality but it can act as the direct subclass of alternative
815
+ parsing methods that do not depend on the Click parser.
816
+
817
+ For instance, this can be used to bridge Click and other systems like
818
+ argparse or docopt.
819
+
820
+ Because base commands do not implement a lot of the API that other
821
+ parts of Click take for granted, they are not supported for all
822
+ operations. For instance, they cannot be used with the decorators
823
+ usually and they have no built-in callback system.
824
+
825
+ .. versionchanged:: 2.0
826
+ Added the `context_settings` parameter.
827
+
828
+ :param name: the name of the command to use unless a group overrides it.
829
+ :param context_settings: an optional dictionary with defaults that are
830
+ passed to the context object.
831
+ """
832
+
833
+ #: The context class to create with :meth:`make_context`.
834
+ #:
835
+ #: .. versionadded:: 8.0
836
+ context_class: t.Type[Context] = Context
837
+ #: the default for the :attr:`Context.allow_extra_args` flag.
838
+ allow_extra_args = False
839
+ #: the default for the :attr:`Context.allow_interspersed_args` flag.
840
+ allow_interspersed_args = True
841
+ #: the default for the :attr:`Context.ignore_unknown_options` flag.
842
+ ignore_unknown_options = False
843
+
844
+ def __init__(
845
+ self,
846
+ name: t.Optional[str],
847
+ context_settings: t.Optional[t.Dict[str, t.Any]] = None,
848
+ ) -> None:
849
+ #: the name the command thinks it has. Upon registering a command
850
+ #: on a :class:`Group` the group will default the command name
851
+ #: with this information. You should instead use the
852
+ #: :class:`Context`\'s :attr:`~Context.info_name` attribute.
853
+ self.name = name
854
+
855
+ if context_settings is None:
856
+ context_settings = {}
857
+
858
+ #: an optional dictionary with defaults passed to the context.
859
+ self.context_settings: t.Dict[str, t.Any] = context_settings
860
+
861
+ def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]:
862
+ """Gather information that could be useful for a tool generating
863
+ user-facing documentation. This traverses the entire structure
864
+ below this command.
865
+
866
+ Use :meth:`click.Context.to_info_dict` to traverse the entire
867
+ CLI structure.
868
+
869
+ :param ctx: A :class:`Context` representing this command.
870
+
871
+ .. versionadded:: 8.0
872
+ """
873
+ return {"name": self.name}
874
+
875
+ def __repr__(self) -> str:
876
+ return f"<{self.__class__.__name__} {self.name}>"
877
+
878
+ def get_usage(self, ctx: Context) -> str:
879
+ raise NotImplementedError("Base commands cannot get usage")
880
+
881
+ def get_help(self, ctx: Context) -> str:
882
+ raise NotImplementedError("Base commands cannot get help")
883
+
884
+ def make_context(
885
+ self,
886
+ info_name: t.Optional[str],
887
+ args: t.List[str],
888
+ parent: t.Optional[Context] = None,
889
+ **extra: t.Any,
890
+ ) -> Context:
891
+ """This function when given an info name and arguments will kick
892
+ off the parsing and create a new :class:`Context`. It does not
893
+ invoke the actual command callback though.
894
+
895
+ To quickly customize the context class used without overriding
896
+ this method, set the :attr:`context_class` attribute.
897
+
898
+ :param info_name: the info name for this invocation. Generally this
899
+ is the most descriptive name for the script or
900
+ command. For the toplevel script it's usually
901
+ the name of the script, for commands below it it's
902
+ the name of the command.
903
+ :param args: the arguments to parse as list of strings.
904
+ :param parent: the parent context if available.
905
+ :param extra: extra keyword arguments forwarded to the context
906
+ constructor.
907
+
908
+ .. versionchanged:: 8.0
909
+ Added the :attr:`context_class` attribute.
910
+ """
911
+ for key, value in self.context_settings.items():
912
+ if key not in extra:
913
+ extra[key] = value
914
+
915
+ ctx = self.context_class(
916
+ self, info_name=info_name, parent=parent, **extra # type: ignore
917
+ )
918
+
919
+ with ctx.scope(cleanup=False):
920
+ self.parse_args(ctx, args)
921
+ return ctx
922
+
923
+ def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]:
924
+ """Given a context and a list of arguments this creates the parser
925
+ and parses the arguments, then modifies the context as necessary.
926
+ This is automatically invoked by :meth:`make_context`.
927
+ """
928
+ raise NotImplementedError("Base commands do not know how to parse arguments.")
929
+
930
+ def invoke(self, ctx: Context) -> t.Any:
931
+ """Given a context, this invokes the command. The default
932
+ implementation is raising a not implemented error.
933
+ """
934
+ raise NotImplementedError("Base commands are not invokable by default")
935
+
936
+ def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]:
937
+ """Return a list of completions for the incomplete value. Looks
938
+ at the names of chained multi-commands.
939
+
940
+ Any command could be part of a chained multi-command, so sibling
941
+ commands are valid at any point during command completion. Other
942
+ command classes will return more completions.
943
+
944
+ :param ctx: Invocation context for this command.
945
+ :param incomplete: Value being completed. May be empty.
946
+
947
+ .. versionadded:: 8.0
948
+ """
949
+ from outerbounds._vendor.click.shell_completion import CompletionItem
950
+
951
+ results: t.List["CompletionItem"] = []
952
+
953
+ while ctx.parent is not None:
954
+ ctx = ctx.parent
955
+
956
+ if isinstance(ctx.command, MultiCommand) and ctx.command.chain:
957
+ results.extend(
958
+ CompletionItem(name, help=command.get_short_help_str())
959
+ for name, command in _complete_visible_commands(ctx, incomplete)
960
+ if name not in ctx.protected_args
961
+ )
962
+
963
+ return results
964
+
965
+ @t.overload
966
+ def main(
967
+ self,
968
+ args: t.Optional[t.Sequence[str]] = None,
969
+ prog_name: t.Optional[str] = None,
970
+ complete_var: t.Optional[str] = None,
971
+ standalone_mode: "te.Literal[True]" = True,
972
+ **extra: t.Any,
973
+ ) -> "te.NoReturn":
974
+ ...
975
+
976
+ @t.overload
977
+ def main(
978
+ self,
979
+ args: t.Optional[t.Sequence[str]] = None,
980
+ prog_name: t.Optional[str] = None,
981
+ complete_var: t.Optional[str] = None,
982
+ standalone_mode: bool = ...,
983
+ **extra: t.Any,
984
+ ) -> t.Any:
985
+ ...
986
+
987
+ def main(
988
+ self,
989
+ args: t.Optional[t.Sequence[str]] = None,
990
+ prog_name: t.Optional[str] = None,
991
+ complete_var: t.Optional[str] = None,
992
+ standalone_mode: bool = True,
993
+ windows_expand_args: bool = True,
994
+ **extra: t.Any,
995
+ ) -> t.Any:
996
+ """This is the way to invoke a script with all the bells and
997
+ whistles as a command line application. This will always terminate
998
+ the application after a call. If this is not wanted, ``SystemExit``
999
+ needs to be caught.
1000
+
1001
+ This method is also available by directly calling the instance of
1002
+ a :class:`Command`.
1003
+
1004
+ :param args: the arguments that should be used for parsing. If not
1005
+ provided, ``sys.argv[1:]`` is used.
1006
+ :param prog_name: the program name that should be used. By default
1007
+ the program name is constructed by taking the file
1008
+ name from ``sys.argv[0]``.
1009
+ :param complete_var: the environment variable that controls the
1010
+ bash completion support. The default is
1011
+ ``"_<prog_name>_COMPLETE"`` with prog_name in
1012
+ uppercase.
1013
+ :param standalone_mode: the default behavior is to invoke the script
1014
+ in standalone mode. Click will then
1015
+ handle exceptions and convert them into
1016
+ error messages and the function will never
1017
+ return but shut down the interpreter. If
1018
+ this is set to `False` they will be
1019
+ propagated to the caller and the return
1020
+ value of this function is the return value
1021
+ of :meth:`invoke`.
1022
+ :param windows_expand_args: Expand glob patterns, user dir, and
1023
+ env vars in command line args on Windows.
1024
+ :param extra: extra keyword arguments are forwarded to the context
1025
+ constructor. See :class:`Context` for more information.
1026
+
1027
+ .. versionchanged:: 8.0.1
1028
+ Added the ``windows_expand_args`` parameter to allow
1029
+ disabling command line arg expansion on Windows.
1030
+
1031
+ .. versionchanged:: 8.0
1032
+ When taking arguments from ``sys.argv`` on Windows, glob
1033
+ patterns, user dir, and env vars are expanded.
1034
+
1035
+ .. versionchanged:: 3.0
1036
+ Added the ``standalone_mode`` parameter.
1037
+ """
1038
+ if args is None:
1039
+ args = sys.argv[1:]
1040
+
1041
+ if os.name == "nt" and windows_expand_args:
1042
+ args = _expand_args(args)
1043
+ else:
1044
+ args = list(args)
1045
+
1046
+ if prog_name is None:
1047
+ prog_name = _detect_program_name()
1048
+
1049
+ # Process shell completion requests and exit early.
1050
+ self._main_shell_completion(extra, prog_name, complete_var)
1051
+
1052
+ try:
1053
+ try:
1054
+ with self.make_context(prog_name, args, **extra) as ctx:
1055
+ rv = self.invoke(ctx)
1056
+ if not standalone_mode:
1057
+ return rv
1058
+ # it's not safe to `ctx.exit(rv)` here!
1059
+ # note that `rv` may actually contain data like "1" which
1060
+ # has obvious effects
1061
+ # more subtle case: `rv=[None, None]` can come out of
1062
+ # chained commands which all returned `None` -- so it's not
1063
+ # even always obvious that `rv` indicates success/failure
1064
+ # by its truthiness/falsiness
1065
+ ctx.exit()
1066
+ except (EOFError, KeyboardInterrupt):
1067
+ echo(file=sys.stderr)
1068
+ raise Abort() from None
1069
+ except ClickException as e:
1070
+ if not standalone_mode:
1071
+ raise
1072
+ e.show()
1073
+ sys.exit(e.exit_code)
1074
+ except OSError as e:
1075
+ if e.errno == errno.EPIPE:
1076
+ sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout))
1077
+ sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr))
1078
+ sys.exit(1)
1079
+ else:
1080
+ raise
1081
+ except Exit as e:
1082
+ if standalone_mode:
1083
+ sys.exit(e.exit_code)
1084
+ else:
1085
+ # in non-standalone mode, return the exit code
1086
+ # note that this is only reached if `self.invoke` above raises
1087
+ # an Exit explicitly -- thus bypassing the check there which
1088
+ # would return its result
1089
+ # the results of non-standalone execution may therefore be
1090
+ # somewhat ambiguous: if there are codepaths which lead to
1091
+ # `ctx.exit(1)` and to `return 1`, the caller won't be able to
1092
+ # tell the difference between the two
1093
+ return e.exit_code
1094
+ except Abort:
1095
+ if not standalone_mode:
1096
+ raise
1097
+ echo(_("Aborted!"), file=sys.stderr)
1098
+ sys.exit(1)
1099
+
1100
+ def _main_shell_completion(
1101
+ self,
1102
+ ctx_args: t.Dict[str, t.Any],
1103
+ prog_name: str,
1104
+ complete_var: t.Optional[str] = None,
1105
+ ) -> None:
1106
+ """Check if the shell is asking for tab completion, process
1107
+ that, then exit early. Called from :meth:`main` before the
1108
+ program is invoked.
1109
+
1110
+ :param prog_name: Name of the executable in the shell.
1111
+ :param complete_var: Name of the environment variable that holds
1112
+ the completion instruction. Defaults to
1113
+ ``_{PROG_NAME}_COMPLETE``.
1114
+ """
1115
+ if complete_var is None:
1116
+ complete_var = f"_{prog_name}_COMPLETE".replace("-", "_").upper()
1117
+
1118
+ instruction = os.environ.get(complete_var)
1119
+
1120
+ if not instruction:
1121
+ return
1122
+
1123
+ from .shell_completion import shell_complete
1124
+
1125
+ rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction)
1126
+ sys.exit(rv)
1127
+
1128
+ def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
1129
+ """Alias for :meth:`main`."""
1130
+ return self.main(*args, **kwargs)
1131
+
1132
+
1133
+ class Command(BaseCommand):
1134
+ """Commands are the basic building block of command line interfaces in
1135
+ Click. A basic command handles command line parsing and might dispatch
1136
+ more parsing to commands nested below it.
1137
+
1138
+ :param name: the name of the command to use unless a group overrides it.
1139
+ :param context_settings: an optional dictionary with defaults that are
1140
+ passed to the context object.
1141
+ :param callback: the callback to invoke. This is optional.
1142
+ :param params: the parameters to register with this command. This can
1143
+ be either :class:`Option` or :class:`Argument` objects.
1144
+ :param help: the help string to use for this command.
1145
+ :param epilog: like the help string but it's printed at the end of the
1146
+ help page after everything else.
1147
+ :param short_help: the short help to use for this command. This is
1148
+ shown on the command listing of the parent command.
1149
+ :param add_help_option: by default each command registers a ``--help``
1150
+ option. This can be disabled by this parameter.
1151
+ :param no_args_is_help: this controls what happens if no arguments are
1152
+ provided. This option is disabled by default.
1153
+ If enabled this will add ``--help`` as argument
1154
+ if no arguments are passed
1155
+ :param hidden: hide this command from help outputs.
1156
+
1157
+ :param deprecated: issues a message indicating that
1158
+ the command is deprecated.
1159
+
1160
+ .. versionchanged:: 8.1
1161
+ ``help``, ``epilog``, and ``short_help`` are stored unprocessed,
1162
+ all formatting is done when outputting help text, not at init,
1163
+ and is done even if not using the ``@command`` decorator.
1164
+
1165
+ .. versionchanged:: 8.0
1166
+ Added a ``repr`` showing the command name.
1167
+
1168
+ .. versionchanged:: 7.1
1169
+ Added the ``no_args_is_help`` parameter.
1170
+
1171
+ .. versionchanged:: 2.0
1172
+ Added the ``context_settings`` parameter.
1173
+ """
1174
+
1175
+ def __init__(
1176
+ self,
1177
+ name: t.Optional[str],
1178
+ context_settings: t.Optional[t.Dict[str, t.Any]] = None,
1179
+ callback: t.Optional[t.Callable[..., t.Any]] = None,
1180
+ params: t.Optional[t.List["Parameter"]] = None,
1181
+ help: t.Optional[str] = None,
1182
+ epilog: t.Optional[str] = None,
1183
+ short_help: t.Optional[str] = None,
1184
+ options_metavar: t.Optional[str] = "[OPTIONS]",
1185
+ add_help_option: bool = True,
1186
+ no_args_is_help: bool = False,
1187
+ hidden: bool = False,
1188
+ deprecated: bool = False,
1189
+ ) -> None:
1190
+ super().__init__(name, context_settings)
1191
+ #: the callback to execute when the command fires. This might be
1192
+ #: `None` in which case nothing happens.
1193
+ self.callback = callback
1194
+ #: the list of parameters for this command in the order they
1195
+ #: should show up in the help page and execute. Eager parameters
1196
+ #: will automatically be handled before non eager ones.
1197
+ self.params: t.List["Parameter"] = params or []
1198
+ self.help = help
1199
+ self.epilog = epilog
1200
+ self.options_metavar = options_metavar
1201
+ self.short_help = short_help
1202
+ self.add_help_option = add_help_option
1203
+ self.no_args_is_help = no_args_is_help
1204
+ self.hidden = hidden
1205
+ self.deprecated = deprecated
1206
+
1207
+ def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]:
1208
+ info_dict = super().to_info_dict(ctx)
1209
+ info_dict.update(
1210
+ params=[param.to_info_dict() for param in self.get_params(ctx)],
1211
+ help=self.help,
1212
+ epilog=self.epilog,
1213
+ short_help=self.short_help,
1214
+ hidden=self.hidden,
1215
+ deprecated=self.deprecated,
1216
+ )
1217
+ return info_dict
1218
+
1219
+ def get_usage(self, ctx: Context) -> str:
1220
+ """Formats the usage line into a string and returns it.
1221
+
1222
+ Calls :meth:`format_usage` internally.
1223
+ """
1224
+ formatter = ctx.make_formatter()
1225
+ self.format_usage(ctx, formatter)
1226
+ return formatter.getvalue().rstrip("\n")
1227
+
1228
+ def get_params(self, ctx: Context) -> t.List["Parameter"]:
1229
+ rv = self.params
1230
+ help_option = self.get_help_option(ctx)
1231
+
1232
+ if help_option is not None:
1233
+ rv = [*rv, help_option]
1234
+
1235
+ return rv
1236
+
1237
+ def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None:
1238
+ """Writes the usage line into the formatter.
1239
+
1240
+ This is a low-level method called by :meth:`get_usage`.
1241
+ """
1242
+ pieces = self.collect_usage_pieces(ctx)
1243
+ formatter.write_usage(ctx.command_path, " ".join(pieces))
1244
+
1245
+ def collect_usage_pieces(self, ctx: Context) -> t.List[str]:
1246
+ """Returns all the pieces that go into the usage line and returns
1247
+ it as a list of strings.
1248
+ """
1249
+ rv = [self.options_metavar] if self.options_metavar else []
1250
+
1251
+ for param in self.get_params(ctx):
1252
+ rv.extend(param.get_usage_pieces(ctx))
1253
+
1254
+ return rv
1255
+
1256
+ def get_help_option_names(self, ctx: Context) -> t.List[str]:
1257
+ """Returns the names for the help option."""
1258
+ all_names = set(ctx.help_option_names)
1259
+ for param in self.params:
1260
+ all_names.difference_update(param.opts)
1261
+ all_names.difference_update(param.secondary_opts)
1262
+ return list(all_names)
1263
+
1264
+ def get_help_option(self, ctx: Context) -> t.Optional["Option"]:
1265
+ """Returns the help option object."""
1266
+ help_options = self.get_help_option_names(ctx)
1267
+
1268
+ if not help_options or not self.add_help_option:
1269
+ return None
1270
+
1271
+ def show_help(ctx: Context, param: "Parameter", value: str) -> None:
1272
+ if value and not ctx.resilient_parsing:
1273
+ echo(ctx.get_help(), color=ctx.color)
1274
+ ctx.exit()
1275
+
1276
+ return Option(
1277
+ help_options,
1278
+ is_flag=True,
1279
+ is_eager=True,
1280
+ expose_value=False,
1281
+ callback=show_help,
1282
+ help=_("Show this message and exit."),
1283
+ )
1284
+
1285
+ def make_parser(self, ctx: Context) -> OptionParser:
1286
+ """Creates the underlying option parser for this command."""
1287
+ parser = OptionParser(ctx)
1288
+ for param in self.get_params(ctx):
1289
+ param.add_to_parser(parser, ctx)
1290
+ return parser
1291
+
1292
+ def get_help(self, ctx: Context) -> str:
1293
+ """Formats the help into a string and returns it.
1294
+
1295
+ Calls :meth:`format_help` internally.
1296
+ """
1297
+ formatter = ctx.make_formatter()
1298
+ self.format_help(ctx, formatter)
1299
+ return formatter.getvalue().rstrip("\n")
1300
+
1301
+ def get_short_help_str(self, limit: int = 45) -> str:
1302
+ """Gets short help for the command or makes it by shortening the
1303
+ long help string.
1304
+ """
1305
+ if self.short_help:
1306
+ text = inspect.cleandoc(self.short_help)
1307
+ elif self.help:
1308
+ text = make_default_short_help(self.help, limit)
1309
+ else:
1310
+ text = ""
1311
+
1312
+ if self.deprecated:
1313
+ text = _("(Deprecated) {text}").format(text=text)
1314
+
1315
+ return text.strip()
1316
+
1317
+ def format_help(self, ctx: Context, formatter: HelpFormatter) -> None:
1318
+ """Writes the help into the formatter if it exists.
1319
+
1320
+ This is a low-level method called by :meth:`get_help`.
1321
+
1322
+ This calls the following methods:
1323
+
1324
+ - :meth:`format_usage`
1325
+ - :meth:`format_help_text`
1326
+ - :meth:`format_options`
1327
+ - :meth:`format_epilog`
1328
+ """
1329
+ self.format_usage(ctx, formatter)
1330
+ self.format_help_text(ctx, formatter)
1331
+ self.format_options(ctx, formatter)
1332
+ self.format_epilog(ctx, formatter)
1333
+
1334
+ def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None:
1335
+ """Writes the help text to the formatter if it exists."""
1336
+ text = self.help if self.help is not None else ""
1337
+
1338
+ if self.deprecated:
1339
+ text = _("(Deprecated) {text}").format(text=text)
1340
+
1341
+ if text:
1342
+ text = inspect.cleandoc(text).partition("\f")[0]
1343
+ formatter.write_paragraph()
1344
+
1345
+ with formatter.indentation():
1346
+ formatter.write_text(text)
1347
+
1348
+ def format_options(self, ctx: Context, formatter: HelpFormatter) -> None:
1349
+ """Writes all the options into the formatter if they exist."""
1350
+ opts = []
1351
+ for param in self.get_params(ctx):
1352
+ rv = param.get_help_record(ctx)
1353
+ if rv is not None:
1354
+ opts.append(rv)
1355
+
1356
+ if opts:
1357
+ with formatter.section(_("Options")):
1358
+ formatter.write_dl(opts)
1359
+
1360
+ def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None:
1361
+ """Writes the epilog into the formatter if it exists."""
1362
+ if self.epilog:
1363
+ epilog = inspect.cleandoc(self.epilog)
1364
+ formatter.write_paragraph()
1365
+
1366
+ with formatter.indentation():
1367
+ formatter.write_text(epilog)
1368
+
1369
+ def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]:
1370
+ if not args and self.no_args_is_help and not ctx.resilient_parsing:
1371
+ echo(ctx.get_help(), color=ctx.color)
1372
+ ctx.exit()
1373
+
1374
+ parser = self.make_parser(ctx)
1375
+ opts, args, param_order = parser.parse_args(args=args)
1376
+
1377
+ for param in iter_params_for_processing(param_order, self.get_params(ctx)):
1378
+ value, args = param.handle_parse_result(ctx, opts, args)
1379
+
1380
+ if args and not ctx.allow_extra_args and not ctx.resilient_parsing:
1381
+ ctx.fail(
1382
+ ngettext(
1383
+ "Got unexpected extra argument ({args})",
1384
+ "Got unexpected extra arguments ({args})",
1385
+ len(args),
1386
+ ).format(args=" ".join(map(str, args)))
1387
+ )
1388
+
1389
+ ctx.args = args
1390
+ ctx._opt_prefixes.update(parser._opt_prefixes)
1391
+ return args
1392
+
1393
+ def invoke(self, ctx: Context) -> t.Any:
1394
+ """Given a context, this invokes the attached callback (if it exists)
1395
+ in the right way.
1396
+ """
1397
+ if self.deprecated:
1398
+ message = _(
1399
+ "DeprecationWarning: The command {name!r} is deprecated."
1400
+ ).format(name=self.name)
1401
+ echo(style(message, fg="red"), err=True)
1402
+
1403
+ if self.callback is not None:
1404
+ return ctx.invoke(self.callback, **ctx.params)
1405
+
1406
+ def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]:
1407
+ """Return a list of completions for the incomplete value. Looks
1408
+ at the names of options and chained multi-commands.
1409
+
1410
+ :param ctx: Invocation context for this command.
1411
+ :param incomplete: Value being completed. May be empty.
1412
+
1413
+ .. versionadded:: 8.0
1414
+ """
1415
+ from outerbounds._vendor.click.shell_completion import CompletionItem
1416
+
1417
+ results: t.List["CompletionItem"] = []
1418
+
1419
+ if incomplete and not incomplete[0].isalnum():
1420
+ for param in self.get_params(ctx):
1421
+ if (
1422
+ not isinstance(param, Option)
1423
+ or param.hidden
1424
+ or (
1425
+ not param.multiple
1426
+ and ctx.get_parameter_source(param.name) # type: ignore
1427
+ is ParameterSource.COMMANDLINE
1428
+ )
1429
+ ):
1430
+ continue
1431
+
1432
+ results.extend(
1433
+ CompletionItem(name, help=param.help)
1434
+ for name in [*param.opts, *param.secondary_opts]
1435
+ if name.startswith(incomplete)
1436
+ )
1437
+
1438
+ results.extend(super().shell_complete(ctx, incomplete))
1439
+ return results
1440
+
1441
+
1442
+ class MultiCommand(Command):
1443
+ """A multi command is the basic implementation of a command that
1444
+ dispatches to subcommands. The most common version is the
1445
+ :class:`Group`.
1446
+
1447
+ :param invoke_without_command: this controls how the multi command itself
1448
+ is invoked. By default it's only invoked
1449
+ if a subcommand is provided.
1450
+ :param no_args_is_help: this controls what happens if no arguments are
1451
+ provided. This option is enabled by default if
1452
+ `invoke_without_command` is disabled or disabled
1453
+ if it's enabled. If enabled this will add
1454
+ ``--help`` as argument if no arguments are
1455
+ passed.
1456
+ :param subcommand_metavar: the string that is used in the documentation
1457
+ to indicate the subcommand place.
1458
+ :param chain: if this is set to `True` chaining of multiple subcommands
1459
+ is enabled. This restricts the form of commands in that
1460
+ they cannot have optional arguments but it allows
1461
+ multiple commands to be chained together.
1462
+ :param result_callback: The result callback to attach to this multi
1463
+ command. This can be set or changed later with the
1464
+ :meth:`result_callback` decorator.
1465
+ """
1466
+
1467
+ allow_extra_args = True
1468
+ allow_interspersed_args = False
1469
+
1470
+ def __init__(
1471
+ self,
1472
+ name: t.Optional[str] = None,
1473
+ invoke_without_command: bool = False,
1474
+ no_args_is_help: t.Optional[bool] = None,
1475
+ subcommand_metavar: t.Optional[str] = None,
1476
+ chain: bool = False,
1477
+ result_callback: t.Optional[t.Callable[..., t.Any]] = None,
1478
+ **attrs: t.Any,
1479
+ ) -> None:
1480
+ super().__init__(name, **attrs)
1481
+
1482
+ if no_args_is_help is None:
1483
+ no_args_is_help = not invoke_without_command
1484
+
1485
+ self.no_args_is_help = no_args_is_help
1486
+ self.invoke_without_command = invoke_without_command
1487
+
1488
+ if subcommand_metavar is None:
1489
+ if chain:
1490
+ subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..."
1491
+ else:
1492
+ subcommand_metavar = "COMMAND [ARGS]..."
1493
+
1494
+ self.subcommand_metavar = subcommand_metavar
1495
+ self.chain = chain
1496
+ # The result callback that is stored. This can be set or
1497
+ # overridden with the :func:`result_callback` decorator.
1498
+ self._result_callback = result_callback
1499
+
1500
+ if self.chain:
1501
+ for param in self.params:
1502
+ if isinstance(param, Argument) and not param.required:
1503
+ raise RuntimeError(
1504
+ "Multi commands in chain mode cannot have"
1505
+ " optional arguments."
1506
+ )
1507
+
1508
+ def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]:
1509
+ info_dict = super().to_info_dict(ctx)
1510
+ commands = {}
1511
+
1512
+ for name in self.list_commands(ctx):
1513
+ command = self.get_command(ctx, name)
1514
+
1515
+ if command is None:
1516
+ continue
1517
+
1518
+ sub_ctx = ctx._make_sub_context(command)
1519
+
1520
+ with sub_ctx.scope(cleanup=False):
1521
+ commands[name] = command.to_info_dict(sub_ctx)
1522
+
1523
+ info_dict.update(commands=commands, chain=self.chain)
1524
+ return info_dict
1525
+
1526
+ def collect_usage_pieces(self, ctx: Context) -> t.List[str]:
1527
+ rv = super().collect_usage_pieces(ctx)
1528
+ rv.append(self.subcommand_metavar)
1529
+ return rv
1530
+
1531
+ def format_options(self, ctx: Context, formatter: HelpFormatter) -> None:
1532
+ super().format_options(ctx, formatter)
1533
+ self.format_commands(ctx, formatter)
1534
+
1535
+ def result_callback(self, replace: bool = False) -> t.Callable[[F], F]:
1536
+ """Adds a result callback to the command. By default if a
1537
+ result callback is already registered this will chain them but
1538
+ this can be disabled with the `replace` parameter. The result
1539
+ callback is invoked with the return value of the subcommand
1540
+ (or the list of return values from all subcommands if chaining
1541
+ is enabled) as well as the parameters as they would be passed
1542
+ to the main callback.
1543
+
1544
+ Example::
1545
+
1546
+ @click.group()
1547
+ @click.option('-i', '--input', default=23)
1548
+ def cli(input):
1549
+ return 42
1550
+
1551
+ @cli.result_callback()
1552
+ def process_result(result, input):
1553
+ return result + input
1554
+
1555
+ :param replace: if set to `True` an already existing result
1556
+ callback will be removed.
1557
+
1558
+ .. versionchanged:: 8.0
1559
+ Renamed from ``resultcallback``.
1560
+
1561
+ .. versionadded:: 3.0
1562
+ """
1563
+
1564
+ def decorator(f: F) -> F:
1565
+ old_callback = self._result_callback
1566
+
1567
+ if old_callback is None or replace:
1568
+ self._result_callback = f
1569
+ return f
1570
+
1571
+ def function(__value, *args, **kwargs): # type: ignore
1572
+ inner = old_callback(__value, *args, **kwargs) # type: ignore
1573
+ return f(inner, *args, **kwargs)
1574
+
1575
+ self._result_callback = rv = update_wrapper(t.cast(F, function), f)
1576
+ return rv
1577
+
1578
+ return decorator
1579
+
1580
+ def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None:
1581
+ """Extra format methods for multi methods that adds all the commands
1582
+ after the options.
1583
+ """
1584
+ commands = []
1585
+ for subcommand in self.list_commands(ctx):
1586
+ cmd = self.get_command(ctx, subcommand)
1587
+ # What is this, the tool lied about a command. Ignore it
1588
+ if cmd is None:
1589
+ continue
1590
+ if cmd.hidden:
1591
+ continue
1592
+
1593
+ commands.append((subcommand, cmd))
1594
+
1595
+ # allow for 3 times the default spacing
1596
+ if len(commands):
1597
+ limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands)
1598
+
1599
+ rows = []
1600
+ for subcommand, cmd in commands:
1601
+ help = cmd.get_short_help_str(limit)
1602
+ rows.append((subcommand, help))
1603
+
1604
+ if rows:
1605
+ with formatter.section(_("Commands")):
1606
+ formatter.write_dl(rows)
1607
+
1608
+ def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]:
1609
+ if not args and self.no_args_is_help and not ctx.resilient_parsing:
1610
+ echo(ctx.get_help(), color=ctx.color)
1611
+ ctx.exit()
1612
+
1613
+ rest = super().parse_args(ctx, args)
1614
+
1615
+ if self.chain:
1616
+ ctx.protected_args = rest
1617
+ ctx.args = []
1618
+ elif rest:
1619
+ ctx.protected_args, ctx.args = rest[:1], rest[1:]
1620
+
1621
+ return ctx.args
1622
+
1623
+ def invoke(self, ctx: Context) -> t.Any:
1624
+ def _process_result(value: t.Any) -> t.Any:
1625
+ if self._result_callback is not None:
1626
+ value = ctx.invoke(self._result_callback, value, **ctx.params)
1627
+ return value
1628
+
1629
+ if not ctx.protected_args:
1630
+ if self.invoke_without_command:
1631
+ # No subcommand was invoked, so the result callback is
1632
+ # invoked with the group return value for regular
1633
+ # groups, or an empty list for chained groups.
1634
+ with ctx:
1635
+ rv = super().invoke(ctx)
1636
+ return _process_result([] if self.chain else rv)
1637
+ ctx.fail(_("Missing command."))
1638
+
1639
+ # Fetch args back out
1640
+ args = [*ctx.protected_args, *ctx.args]
1641
+ ctx.args = []
1642
+ ctx.protected_args = []
1643
+
1644
+ # If we're not in chain mode, we only allow the invocation of a
1645
+ # single command but we also inform the current context about the
1646
+ # name of the command to invoke.
1647
+ if not self.chain:
1648
+ # Make sure the context is entered so we do not clean up
1649
+ # resources until the result processor has worked.
1650
+ with ctx:
1651
+ cmd_name, cmd, args = self.resolve_command(ctx, args)
1652
+ assert cmd is not None
1653
+ ctx.invoked_subcommand = cmd_name
1654
+ super().invoke(ctx)
1655
+ sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)
1656
+ with sub_ctx:
1657
+ return _process_result(sub_ctx.command.invoke(sub_ctx))
1658
+
1659
+ # In chain mode we create the contexts step by step, but after the
1660
+ # base command has been invoked. Because at that point we do not
1661
+ # know the subcommands yet, the invoked subcommand attribute is
1662
+ # set to ``*`` to inform the command that subcommands are executed
1663
+ # but nothing else.
1664
+ with ctx:
1665
+ ctx.invoked_subcommand = "*" if args else None
1666
+ super().invoke(ctx)
1667
+
1668
+ # Otherwise we make every single context and invoke them in a
1669
+ # chain. In that case the return value to the result processor
1670
+ # is the list of all invoked subcommand's results.
1671
+ contexts = []
1672
+ while args:
1673
+ cmd_name, cmd, args = self.resolve_command(ctx, args)
1674
+ assert cmd is not None
1675
+ sub_ctx = cmd.make_context(
1676
+ cmd_name,
1677
+ args,
1678
+ parent=ctx,
1679
+ allow_extra_args=True,
1680
+ allow_interspersed_args=False,
1681
+ )
1682
+ contexts.append(sub_ctx)
1683
+ args, sub_ctx.args = sub_ctx.args, []
1684
+
1685
+ rv = []
1686
+ for sub_ctx in contexts:
1687
+ with sub_ctx:
1688
+ rv.append(sub_ctx.command.invoke(sub_ctx))
1689
+ return _process_result(rv)
1690
+
1691
+ def resolve_command(
1692
+ self, ctx: Context, args: t.List[str]
1693
+ ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]:
1694
+ cmd_name = make_str(args[0])
1695
+ original_cmd_name = cmd_name
1696
+
1697
+ # Get the command
1698
+ cmd = self.get_command(ctx, cmd_name)
1699
+
1700
+ # If we can't find the command but there is a normalization
1701
+ # function available, we try with that one.
1702
+ if cmd is None and ctx.token_normalize_func is not None:
1703
+ cmd_name = ctx.token_normalize_func(cmd_name)
1704
+ cmd = self.get_command(ctx, cmd_name)
1705
+
1706
+ # If we don't find the command we want to show an error message
1707
+ # to the user that it was not provided. However, there is
1708
+ # something else we should do: if the first argument looks like
1709
+ # an option we want to kick off parsing again for arguments to
1710
+ # resolve things like --help which now should go to the main
1711
+ # place.
1712
+ if cmd is None and not ctx.resilient_parsing:
1713
+ if split_opt(cmd_name)[0]:
1714
+ self.parse_args(ctx, ctx.args)
1715
+ ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name))
1716
+ return cmd_name if cmd else None, cmd, args[1:]
1717
+
1718
+ def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]:
1719
+ """Given a context and a command name, this returns a
1720
+ :class:`Command` object if it exists or returns `None`.
1721
+ """
1722
+ raise NotImplementedError
1723
+
1724
+ def list_commands(self, ctx: Context) -> t.List[str]:
1725
+ """Returns a list of subcommand names in the order they should
1726
+ appear.
1727
+ """
1728
+ return []
1729
+
1730
+ def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]:
1731
+ """Return a list of completions for the incomplete value. Looks
1732
+ at the names of options, subcommands, and chained
1733
+ multi-commands.
1734
+
1735
+ :param ctx: Invocation context for this command.
1736
+ :param incomplete: Value being completed. May be empty.
1737
+
1738
+ .. versionadded:: 8.0
1739
+ """
1740
+ from outerbounds._vendor.click.shell_completion import CompletionItem
1741
+
1742
+ results = [
1743
+ CompletionItem(name, help=command.get_short_help_str())
1744
+ for name, command in _complete_visible_commands(ctx, incomplete)
1745
+ ]
1746
+ results.extend(super().shell_complete(ctx, incomplete))
1747
+ return results
1748
+
1749
+
1750
+ class Group(MultiCommand):
1751
+ """A group allows a command to have subcommands attached. This is
1752
+ the most common way to implement nesting in Click.
1753
+
1754
+ :param name: The name of the group command.
1755
+ :param commands: A dict mapping names to :class:`Command` objects.
1756
+ Can also be a list of :class:`Command`, which will use
1757
+ :attr:`Command.name` to create the dict.
1758
+ :param attrs: Other command arguments described in
1759
+ :class:`MultiCommand`, :class:`Command`, and
1760
+ :class:`BaseCommand`.
1761
+
1762
+ .. versionchanged:: 8.0
1763
+ The ``commmands`` argument can be a list of command objects.
1764
+ """
1765
+
1766
+ #: If set, this is used by the group's :meth:`command` decorator
1767
+ #: as the default :class:`Command` class. This is useful to make all
1768
+ #: subcommands use a custom command class.
1769
+ #:
1770
+ #: .. versionadded:: 8.0
1771
+ command_class: t.Optional[t.Type[Command]] = None
1772
+
1773
+ #: If set, this is used by the group's :meth:`group` decorator
1774
+ #: as the default :class:`Group` class. This is useful to make all
1775
+ #: subgroups use a custom group class.
1776
+ #:
1777
+ #: If set to the special value :class:`type` (literally
1778
+ #: ``group_class = type``), this group's class will be used as the
1779
+ #: default class. This makes a custom group class continue to make
1780
+ #: custom groups.
1781
+ #:
1782
+ #: .. versionadded:: 8.0
1783
+ group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None
1784
+ # Literal[type] isn't valid, so use Type[type]
1785
+
1786
+ def __init__(
1787
+ self,
1788
+ name: t.Optional[str] = None,
1789
+ commands: t.Optional[t.Union[t.Dict[str, Command], t.Sequence[Command]]] = None,
1790
+ **attrs: t.Any,
1791
+ ) -> None:
1792
+ super().__init__(name, **attrs)
1793
+
1794
+ if commands is None:
1795
+ commands = {}
1796
+ elif isinstance(commands, abc.Sequence):
1797
+ commands = {c.name: c for c in commands if c.name is not None}
1798
+
1799
+ #: The registered subcommands by their exported names.
1800
+ self.commands: t.Dict[str, Command] = commands
1801
+
1802
+ def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None:
1803
+ """Registers another :class:`Command` with this group. If the name
1804
+ is not provided, the name of the command is used.
1805
+ """
1806
+ name = name or cmd.name
1807
+ if name is None:
1808
+ raise TypeError("Command has no name.")
1809
+ _check_multicommand(self, name, cmd, register=True)
1810
+ self.commands[name] = cmd
1811
+
1812
+ @t.overload
1813
+ def command(self, __func: t.Callable[..., t.Any]) -> Command:
1814
+ ...
1815
+
1816
+ @t.overload
1817
+ def command(
1818
+ self, *args: t.Any, **kwargs: t.Any
1819
+ ) -> t.Callable[[t.Callable[..., t.Any]], Command]:
1820
+ ...
1821
+
1822
+ def command(
1823
+ self, *args: t.Any, **kwargs: t.Any
1824
+ ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]:
1825
+ """A shortcut decorator for declaring and attaching a command to
1826
+ the group. This takes the same arguments as :func:`command` and
1827
+ immediately registers the created command with this group by
1828
+ calling :meth:`add_command`.
1829
+
1830
+ To customize the command class used, set the
1831
+ :attr:`command_class` attribute.
1832
+
1833
+ .. versionchanged:: 8.1
1834
+ This decorator can be applied without parentheses.
1835
+
1836
+ .. versionchanged:: 8.0
1837
+ Added the :attr:`command_class` attribute.
1838
+ """
1839
+ from .decorators import command
1840
+
1841
+ if self.command_class and kwargs.get("cls") is None:
1842
+ kwargs["cls"] = self.command_class
1843
+
1844
+ func: t.Optional[t.Callable] = None
1845
+
1846
+ if args and callable(args[0]):
1847
+ assert (
1848
+ len(args) == 1 and not kwargs
1849
+ ), "Use 'command(**kwargs)(callable)' to provide arguments."
1850
+ (func,) = args
1851
+ args = ()
1852
+
1853
+ def decorator(f: t.Callable[..., t.Any]) -> Command:
1854
+ cmd: Command = command(*args, **kwargs)(f)
1855
+ self.add_command(cmd)
1856
+ return cmd
1857
+
1858
+ if func is not None:
1859
+ return decorator(func)
1860
+
1861
+ return decorator
1862
+
1863
+ @t.overload
1864
+ def group(self, __func: t.Callable[..., t.Any]) -> "Group":
1865
+ ...
1866
+
1867
+ @t.overload
1868
+ def group(
1869
+ self, *args: t.Any, **kwargs: t.Any
1870
+ ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]:
1871
+ ...
1872
+
1873
+ def group(
1874
+ self, *args: t.Any, **kwargs: t.Any
1875
+ ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]:
1876
+ """A shortcut decorator for declaring and attaching a group to
1877
+ the group. This takes the same arguments as :func:`group` and
1878
+ immediately registers the created group with this group by
1879
+ calling :meth:`add_command`.
1880
+
1881
+ To customize the group class used, set the :attr:`group_class`
1882
+ attribute.
1883
+
1884
+ .. versionchanged:: 8.1
1885
+ This decorator can be applied without parentheses.
1886
+
1887
+ .. versionchanged:: 8.0
1888
+ Added the :attr:`group_class` attribute.
1889
+ """
1890
+ from .decorators import group
1891
+
1892
+ func: t.Optional[t.Callable] = None
1893
+
1894
+ if args and callable(args[0]):
1895
+ assert (
1896
+ len(args) == 1 and not kwargs
1897
+ ), "Use 'group(**kwargs)(callable)' to provide arguments."
1898
+ (func,) = args
1899
+ args = ()
1900
+
1901
+ if self.group_class is not None and kwargs.get("cls") is None:
1902
+ if self.group_class is type:
1903
+ kwargs["cls"] = type(self)
1904
+ else:
1905
+ kwargs["cls"] = self.group_class
1906
+
1907
+ def decorator(f: t.Callable[..., t.Any]) -> "Group":
1908
+ cmd: Group = group(*args, **kwargs)(f)
1909
+ self.add_command(cmd)
1910
+ return cmd
1911
+
1912
+ if func is not None:
1913
+ return decorator(func)
1914
+
1915
+ return decorator
1916
+
1917
+ def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]:
1918
+ return self.commands.get(cmd_name)
1919
+
1920
+ def list_commands(self, ctx: Context) -> t.List[str]:
1921
+ return sorted(self.commands)
1922
+
1923
+
1924
+ class CommandCollection(MultiCommand):
1925
+ """A command collection is a multi command that merges multiple multi
1926
+ commands together into one. This is a straightforward implementation
1927
+ that accepts a list of different multi commands as sources and
1928
+ provides all the commands for each of them.
1929
+ """
1930
+
1931
+ def __init__(
1932
+ self,
1933
+ name: t.Optional[str] = None,
1934
+ sources: t.Optional[t.List[MultiCommand]] = None,
1935
+ **attrs: t.Any,
1936
+ ) -> None:
1937
+ super().__init__(name, **attrs)
1938
+ #: The list of registered multi commands.
1939
+ self.sources: t.List[MultiCommand] = sources or []
1940
+
1941
+ def add_source(self, multi_cmd: MultiCommand) -> None:
1942
+ """Adds a new multi command to the chain dispatcher."""
1943
+ self.sources.append(multi_cmd)
1944
+
1945
+ def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]:
1946
+ for source in self.sources:
1947
+ rv = source.get_command(ctx, cmd_name)
1948
+
1949
+ if rv is not None:
1950
+ if self.chain:
1951
+ _check_multicommand(self, cmd_name, rv)
1952
+
1953
+ return rv
1954
+
1955
+ return None
1956
+
1957
+ def list_commands(self, ctx: Context) -> t.List[str]:
1958
+ rv: t.Set[str] = set()
1959
+
1960
+ for source in self.sources:
1961
+ rv.update(source.list_commands(ctx))
1962
+
1963
+ return sorted(rv)
1964
+
1965
+
1966
+ def _check_iter(value: t.Any) -> t.Iterator[t.Any]:
1967
+ """Check if the value is iterable but not a string. Raises a type
1968
+ error, or return an iterator over the value.
1969
+ """
1970
+ if isinstance(value, str):
1971
+ raise TypeError
1972
+
1973
+ return iter(value)
1974
+
1975
+
1976
+ class Parameter:
1977
+ r"""A parameter to a command comes in two versions: they are either
1978
+ :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently
1979
+ not supported by design as some of the internals for parsing are
1980
+ intentionally not finalized.
1981
+
1982
+ Some settings are supported by both options and arguments.
1983
+
1984
+ :param param_decls: the parameter declarations for this option or
1985
+ argument. This is a list of flags or argument
1986
+ names.
1987
+ :param type: the type that should be used. Either a :class:`ParamType`
1988
+ or a Python type. The later is converted into the former
1989
+ automatically if supported.
1990
+ :param required: controls if this is optional or not.
1991
+ :param default: the default value if omitted. This can also be a callable,
1992
+ in which case it's invoked when the default is needed
1993
+ without any arguments.
1994
+ :param callback: A function to further process or validate the value
1995
+ after type conversion. It is called as ``f(ctx, param, value)``
1996
+ and must return the value. It is called for all sources,
1997
+ including prompts.
1998
+ :param nargs: the number of arguments to match. If not ``1`` the return
1999
+ value is a tuple instead of single value. The default for
2000
+ nargs is ``1`` (except if the type is a tuple, then it's
2001
+ the arity of the tuple). If ``nargs=-1``, all remaining
2002
+ parameters are collected.
2003
+ :param metavar: how the value is represented in the help page.
2004
+ :param expose_value: if this is `True` then the value is passed onwards
2005
+ to the command callback and stored on the context,
2006
+ otherwise it's skipped.
2007
+ :param is_eager: eager values are processed before non eager ones. This
2008
+ should not be set for arguments or it will inverse the
2009
+ order of processing.
2010
+ :param envvar: a string or list of strings that are environment variables
2011
+ that should be checked.
2012
+ :param shell_complete: A function that returns custom shell
2013
+ completions. Used instead of the param's type completion if
2014
+ given. Takes ``ctx, param, incomplete`` and must return a list
2015
+ of :class:`~click.shell_completion.CompletionItem` or a list of
2016
+ strings.
2017
+
2018
+ .. versionchanged:: 8.0
2019
+ ``process_value`` validates required parameters and bounded
2020
+ ``nargs``, and invokes the parameter callback before returning
2021
+ the value. This allows the callback to validate prompts.
2022
+ ``full_process_value`` is removed.
2023
+
2024
+ .. versionchanged:: 8.0
2025
+ ``autocompletion`` is renamed to ``shell_complete`` and has new
2026
+ semantics described above. The old name is deprecated and will
2027
+ be removed in 8.1, until then it will be wrapped to match the
2028
+ new requirements.
2029
+
2030
+ .. versionchanged:: 8.0
2031
+ For ``multiple=True, nargs>1``, the default must be a list of
2032
+ tuples.
2033
+
2034
+ .. versionchanged:: 8.0
2035
+ Setting a default is no longer required for ``nargs>1``, it will
2036
+ default to ``None``. ``multiple=True`` or ``nargs=-1`` will
2037
+ default to ``()``.
2038
+
2039
+ .. versionchanged:: 7.1
2040
+ Empty environment variables are ignored rather than taking the
2041
+ empty string value. This makes it possible for scripts to clear
2042
+ variables if they can't unset them.
2043
+
2044
+ .. versionchanged:: 2.0
2045
+ Changed signature for parameter callback to also be passed the
2046
+ parameter. The old callback format will still work, but it will
2047
+ raise a warning to give you a chance to migrate the code easier.
2048
+ """
2049
+
2050
+ param_type_name = "parameter"
2051
+
2052
+ def __init__(
2053
+ self,
2054
+ param_decls: t.Optional[t.Sequence[str]] = None,
2055
+ type: t.Optional[t.Union[types.ParamType, t.Any]] = None,
2056
+ required: bool = False,
2057
+ default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None,
2058
+ callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None,
2059
+ nargs: t.Optional[int] = None,
2060
+ multiple: bool = False,
2061
+ metavar: t.Optional[str] = None,
2062
+ expose_value: bool = True,
2063
+ is_eager: bool = False,
2064
+ envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None,
2065
+ shell_complete: t.Optional[
2066
+ t.Callable[
2067
+ [Context, "Parameter", str],
2068
+ t.Union[t.List["CompletionItem"], t.List[str]],
2069
+ ]
2070
+ ] = None,
2071
+ ) -> None:
2072
+ self.name, self.opts, self.secondary_opts = self._parse_decls(
2073
+ param_decls or (), expose_value
2074
+ )
2075
+ self.type = types.convert_type(type, default)
2076
+
2077
+ # Default nargs to what the type tells us if we have that
2078
+ # information available.
2079
+ if nargs is None:
2080
+ if self.type.is_composite:
2081
+ nargs = self.type.arity
2082
+ else:
2083
+ nargs = 1
2084
+
2085
+ self.required = required
2086
+ self.callback = callback
2087
+ self.nargs = nargs
2088
+ self.multiple = multiple
2089
+ self.expose_value = expose_value
2090
+ self.default = default
2091
+ self.is_eager = is_eager
2092
+ self.metavar = metavar
2093
+ self.envvar = envvar
2094
+ self._custom_shell_complete = shell_complete
2095
+
2096
+ if __debug__:
2097
+ if self.type.is_composite and nargs != self.type.arity:
2098
+ raise ValueError(
2099
+ f"'nargs' must be {self.type.arity} (or None) for"
2100
+ f" type {self.type!r}, but it was {nargs}."
2101
+ )
2102
+
2103
+ # Skip no default or callable default.
2104
+ check_default = default if not callable(default) else None
2105
+
2106
+ if check_default is not None:
2107
+ if multiple:
2108
+ try:
2109
+ # Only check the first value against nargs.
2110
+ check_default = next(_check_iter(check_default), None)
2111
+ except TypeError:
2112
+ raise ValueError(
2113
+ "'default' must be a list when 'multiple' is true."
2114
+ ) from None
2115
+
2116
+ # Can be None for multiple with empty default.
2117
+ if nargs != 1 and check_default is not None:
2118
+ try:
2119
+ _check_iter(check_default)
2120
+ except TypeError:
2121
+ if multiple:
2122
+ message = (
2123
+ "'default' must be a list of lists when 'multiple' is"
2124
+ " true and 'nargs' != 1."
2125
+ )
2126
+ else:
2127
+ message = "'default' must be a list when 'nargs' != 1."
2128
+
2129
+ raise ValueError(message) from None
2130
+
2131
+ if nargs > 1 and len(check_default) != nargs:
2132
+ subject = "item length" if multiple else "length"
2133
+ raise ValueError(
2134
+ f"'default' {subject} must match nargs={nargs}."
2135
+ )
2136
+
2137
+ def to_info_dict(self) -> t.Dict[str, t.Any]:
2138
+ """Gather information that could be useful for a tool generating
2139
+ user-facing documentation.
2140
+
2141
+ Use :meth:`click.Context.to_info_dict` to traverse the entire
2142
+ CLI structure.
2143
+
2144
+ .. versionadded:: 8.0
2145
+ """
2146
+ return {
2147
+ "name": self.name,
2148
+ "param_type_name": self.param_type_name,
2149
+ "opts": self.opts,
2150
+ "secondary_opts": self.secondary_opts,
2151
+ "type": self.type.to_info_dict(),
2152
+ "required": self.required,
2153
+ "nargs": self.nargs,
2154
+ "multiple": self.multiple,
2155
+ "default": self.default,
2156
+ "envvar": self.envvar,
2157
+ }
2158
+
2159
+ def __repr__(self) -> str:
2160
+ return f"<{self.__class__.__name__} {self.name}>"
2161
+
2162
+ def _parse_decls(
2163
+ self, decls: t.Sequence[str], expose_value: bool
2164
+ ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]:
2165
+ raise NotImplementedError()
2166
+
2167
+ @property
2168
+ def human_readable_name(self) -> str:
2169
+ """Returns the human readable name of this parameter. This is the
2170
+ same as the name for options, but the metavar for arguments.
2171
+ """
2172
+ return self.name # type: ignore
2173
+
2174
+ def make_metavar(self) -> str:
2175
+ if self.metavar is not None:
2176
+ return self.metavar
2177
+
2178
+ metavar = self.type.get_metavar(self)
2179
+
2180
+ if metavar is None:
2181
+ metavar = self.type.name.upper()
2182
+
2183
+ if self.nargs != 1:
2184
+ metavar += "..."
2185
+
2186
+ return metavar
2187
+
2188
+ @t.overload
2189
+ def get_default(
2190
+ self, ctx: Context, call: "te.Literal[True]" = True
2191
+ ) -> t.Optional[t.Any]:
2192
+ ...
2193
+
2194
+ @t.overload
2195
+ def get_default(
2196
+ self, ctx: Context, call: bool = ...
2197
+ ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]:
2198
+ ...
2199
+
2200
+ def get_default(
2201
+ self, ctx: Context, call: bool = True
2202
+ ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]:
2203
+ """Get the default for the parameter. Tries
2204
+ :meth:`Context.lookup_default` first, then the local default.
2205
+
2206
+ :param ctx: Current context.
2207
+ :param call: If the default is a callable, call it. Disable to
2208
+ return the callable instead.
2209
+
2210
+ .. versionchanged:: 8.0.2
2211
+ Type casting is no longer performed when getting a default.
2212
+
2213
+ .. versionchanged:: 8.0.1
2214
+ Type casting can fail in resilient parsing mode. Invalid
2215
+ defaults will not prevent showing help text.
2216
+
2217
+ .. versionchanged:: 8.0
2218
+ Looks at ``ctx.default_map`` first.
2219
+
2220
+ .. versionchanged:: 8.0
2221
+ Added the ``call`` parameter.
2222
+ """
2223
+ value = ctx.lookup_default(self.name, call=False) # type: ignore
2224
+
2225
+ if value is None:
2226
+ value = self.default
2227
+
2228
+ if call and callable(value):
2229
+ value = value()
2230
+
2231
+ return value
2232
+
2233
+ def add_to_parser(self, parser: OptionParser, ctx: Context) -> None:
2234
+ raise NotImplementedError()
2235
+
2236
+ def consume_value(
2237
+ self, ctx: Context, opts: t.Mapping[str, t.Any]
2238
+ ) -> t.Tuple[t.Any, ParameterSource]:
2239
+ value = opts.get(self.name) # type: ignore
2240
+ source = ParameterSource.COMMANDLINE
2241
+
2242
+ if value is None:
2243
+ value = self.value_from_envvar(ctx)
2244
+ source = ParameterSource.ENVIRONMENT
2245
+
2246
+ if value is None:
2247
+ value = ctx.lookup_default(self.name) # type: ignore
2248
+ source = ParameterSource.DEFAULT_MAP
2249
+
2250
+ if value is None:
2251
+ value = self.get_default(ctx)
2252
+ source = ParameterSource.DEFAULT
2253
+
2254
+ return value, source
2255
+
2256
+ def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any:
2257
+ """Convert and validate a value against the option's
2258
+ :attr:`type`, :attr:`multiple`, and :attr:`nargs`.
2259
+ """
2260
+ if value is None:
2261
+ return () if self.multiple or self.nargs == -1 else None
2262
+
2263
+ def check_iter(value: t.Any) -> t.Iterator:
2264
+ try:
2265
+ return _check_iter(value)
2266
+ except TypeError:
2267
+ # This should only happen when passing in args manually,
2268
+ # the parser should construct an iterable when parsing
2269
+ # the command line.
2270
+ raise BadParameter(
2271
+ _("Value must be an iterable."), ctx=ctx, param=self
2272
+ ) from None
2273
+
2274
+ if self.nargs == 1 or self.type.is_composite:
2275
+ convert: t.Callable[[t.Any], t.Any] = partial(
2276
+ self.type, param=self, ctx=ctx
2277
+ )
2278
+ elif self.nargs == -1:
2279
+
2280
+ def convert(value: t.Any) -> t.Tuple:
2281
+ return tuple(self.type(x, self, ctx) for x in check_iter(value))
2282
+
2283
+ else: # nargs > 1
2284
+
2285
+ def convert(value: t.Any) -> t.Tuple:
2286
+ value = tuple(check_iter(value))
2287
+
2288
+ if len(value) != self.nargs:
2289
+ raise BadParameter(
2290
+ ngettext(
2291
+ "Takes {nargs} values but 1 was given.",
2292
+ "Takes {nargs} values but {len} were given.",
2293
+ len(value),
2294
+ ).format(nargs=self.nargs, len=len(value)),
2295
+ ctx=ctx,
2296
+ param=self,
2297
+ )
2298
+
2299
+ return tuple(self.type(x, self, ctx) for x in value)
2300
+
2301
+ if self.multiple:
2302
+ return tuple(convert(x) for x in check_iter(value))
2303
+
2304
+ return convert(value)
2305
+
2306
+ def value_is_missing(self, value: t.Any) -> bool:
2307
+ if value is None:
2308
+ return True
2309
+
2310
+ if (self.nargs != 1 or self.multiple) and value == ():
2311
+ return True
2312
+
2313
+ return False
2314
+
2315
+ def process_value(self, ctx: Context, value: t.Any) -> t.Any:
2316
+ value = self.type_cast_value(ctx, value)
2317
+
2318
+ if self.required and self.value_is_missing(value):
2319
+ raise MissingParameter(ctx=ctx, param=self)
2320
+
2321
+ if self.callback is not None:
2322
+ value = self.callback(ctx, self, value)
2323
+
2324
+ return value
2325
+
2326
+ def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]:
2327
+ if self.envvar is None:
2328
+ return None
2329
+
2330
+ if isinstance(self.envvar, str):
2331
+ rv = os.environ.get(self.envvar)
2332
+
2333
+ if rv:
2334
+ return rv
2335
+ else:
2336
+ for envvar in self.envvar:
2337
+ rv = os.environ.get(envvar)
2338
+
2339
+ if rv:
2340
+ return rv
2341
+
2342
+ return None
2343
+
2344
+ def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]:
2345
+ rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx)
2346
+
2347
+ if rv is not None and self.nargs != 1:
2348
+ rv = self.type.split_envvar_value(rv)
2349
+
2350
+ return rv
2351
+
2352
+ def handle_parse_result(
2353
+ self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str]
2354
+ ) -> t.Tuple[t.Any, t.List[str]]:
2355
+ with augment_usage_errors(ctx, param=self):
2356
+ value, source = self.consume_value(ctx, opts)
2357
+ ctx.set_parameter_source(self.name, source) # type: ignore
2358
+
2359
+ try:
2360
+ value = self.process_value(ctx, value)
2361
+ except Exception:
2362
+ if not ctx.resilient_parsing:
2363
+ raise
2364
+
2365
+ value = None
2366
+
2367
+ if self.expose_value:
2368
+ ctx.params[self.name] = value # type: ignore
2369
+
2370
+ return value, args
2371
+
2372
+ def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]:
2373
+ pass
2374
+
2375
+ def get_usage_pieces(self, ctx: Context) -> t.List[str]:
2376
+ return []
2377
+
2378
+ def get_error_hint(self, ctx: Context) -> str:
2379
+ """Get a stringified version of the param for use in error messages to
2380
+ indicate which param caused the error.
2381
+ """
2382
+ hint_list = self.opts or [self.human_readable_name]
2383
+ return " / ".join(f"'{x}'" for x in hint_list)
2384
+
2385
+ def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]:
2386
+ """Return a list of completions for the incomplete value. If a
2387
+ ``shell_complete`` function was given during init, it is used.
2388
+ Otherwise, the :attr:`type`
2389
+ :meth:`~click.types.ParamType.shell_complete` function is used.
2390
+
2391
+ :param ctx: Invocation context for this command.
2392
+ :param incomplete: Value being completed. May be empty.
2393
+
2394
+ .. versionadded:: 8.0
2395
+ """
2396
+ if self._custom_shell_complete is not None:
2397
+ results = self._custom_shell_complete(ctx, self, incomplete)
2398
+
2399
+ if results and isinstance(results[0], str):
2400
+ from outerbounds._vendor.click.shell_completion import CompletionItem
2401
+
2402
+ results = [CompletionItem(c) for c in results]
2403
+
2404
+ return t.cast(t.List["CompletionItem"], results)
2405
+
2406
+ return self.type.shell_complete(ctx, self, incomplete)
2407
+
2408
+
2409
+ class Option(Parameter):
2410
+ """Options are usually optional values on the command line and
2411
+ have some extra features that arguments don't have.
2412
+
2413
+ All other parameters are passed onwards to the parameter constructor.
2414
+
2415
+ :param show_default: Show the default value for this option in its
2416
+ help text. Values are not shown by default, unless
2417
+ :attr:`Context.show_default` is ``True``. If this value is a
2418
+ string, it shows that string in parentheses instead of the
2419
+ actual value. This is particularly useful for dynamic options.
2420
+ For single option boolean flags, the default remains hidden if
2421
+ its value is ``False``.
2422
+ :param show_envvar: Controls if an environment variable should be
2423
+ shown on the help page. Normally, environment variables are not
2424
+ shown.
2425
+ :param prompt: If set to ``True`` or a non empty string then the
2426
+ user will be prompted for input. If set to ``True`` the prompt
2427
+ will be the option name capitalized.
2428
+ :param confirmation_prompt: Prompt a second time to confirm the
2429
+ value if it was prompted for. Can be set to a string instead of
2430
+ ``True`` to customize the message.
2431
+ :param prompt_required: If set to ``False``, the user will be
2432
+ prompted for input only when the option was specified as a flag
2433
+ without a value.
2434
+ :param hide_input: If this is ``True`` then the input on the prompt
2435
+ will be hidden from the user. This is useful for password input.
2436
+ :param is_flag: forces this option to act as a flag. The default is
2437
+ auto detection.
2438
+ :param flag_value: which value should be used for this flag if it's
2439
+ enabled. This is set to a boolean automatically if
2440
+ the option string contains a slash to mark two options.
2441
+ :param multiple: if this is set to `True` then the argument is accepted
2442
+ multiple times and recorded. This is similar to ``nargs``
2443
+ in how it works but supports arbitrary number of
2444
+ arguments.
2445
+ :param count: this flag makes an option increment an integer.
2446
+ :param allow_from_autoenv: if this is enabled then the value of this
2447
+ parameter will be pulled from an environment
2448
+ variable in case a prefix is defined on the
2449
+ context.
2450
+ :param help: the help string.
2451
+ :param hidden: hide this option from help outputs.
2452
+
2453
+ .. versionchanged:: 8.1.0
2454
+ Help text indentation is cleaned here instead of only in the
2455
+ ``@option`` decorator.
2456
+
2457
+ .. versionchanged:: 8.1.0
2458
+ The ``show_default`` parameter overrides
2459
+ ``Context.show_default``.
2460
+
2461
+ .. versionchanged:: 8.1.0
2462
+ The default of a single option boolean flag is not shown if the
2463
+ default value is ``False``.
2464
+
2465
+ .. versionchanged:: 8.0.1
2466
+ ``type`` is detected from ``flag_value`` if given.
2467
+ """
2468
+
2469
+ param_type_name = "option"
2470
+
2471
+ def __init__(
2472
+ self,
2473
+ param_decls: t.Optional[t.Sequence[str]] = None,
2474
+ show_default: t.Union[bool, str, None] = None,
2475
+ prompt: t.Union[bool, str] = False,
2476
+ confirmation_prompt: t.Union[bool, str] = False,
2477
+ prompt_required: bool = True,
2478
+ hide_input: bool = False,
2479
+ is_flag: t.Optional[bool] = None,
2480
+ flag_value: t.Optional[t.Any] = None,
2481
+ multiple: bool = False,
2482
+ count: bool = False,
2483
+ allow_from_autoenv: bool = True,
2484
+ type: t.Optional[t.Union[types.ParamType, t.Any]] = None,
2485
+ help: t.Optional[str] = None,
2486
+ hidden: bool = False,
2487
+ show_choices: bool = True,
2488
+ show_envvar: bool = False,
2489
+ **attrs: t.Any,
2490
+ ) -> None:
2491
+ if help:
2492
+ help = inspect.cleandoc(help)
2493
+
2494
+ default_is_missing = "default" not in attrs
2495
+ super().__init__(param_decls, type=type, multiple=multiple, **attrs)
2496
+
2497
+ if prompt is True:
2498
+ if self.name is None:
2499
+ raise TypeError("'name' is required with 'prompt=True'.")
2500
+
2501
+ prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize()
2502
+ elif prompt is False:
2503
+ prompt_text = None
2504
+ else:
2505
+ prompt_text = prompt
2506
+
2507
+ self.prompt = prompt_text
2508
+ self.confirmation_prompt = confirmation_prompt
2509
+ self.prompt_required = prompt_required
2510
+ self.hide_input = hide_input
2511
+ self.hidden = hidden
2512
+
2513
+ # If prompt is enabled but not required, then the option can be
2514
+ # used as a flag to indicate using prompt or flag_value.
2515
+ self._flag_needs_value = self.prompt is not None and not self.prompt_required
2516
+
2517
+ if is_flag is None:
2518
+ if flag_value is not None:
2519
+ # Implicitly a flag because flag_value was set.
2520
+ is_flag = True
2521
+ elif self._flag_needs_value:
2522
+ # Not a flag, but when used as a flag it shows a prompt.
2523
+ is_flag = False
2524
+ else:
2525
+ # Implicitly a flag because flag options were given.
2526
+ is_flag = bool(self.secondary_opts)
2527
+ elif is_flag is False and not self._flag_needs_value:
2528
+ # Not a flag, and prompt is not enabled, can be used as a
2529
+ # flag if flag_value is set.
2530
+ self._flag_needs_value = flag_value is not None
2531
+
2532
+ if is_flag and default_is_missing and not self.required:
2533
+ self.default: t.Union[t.Any, t.Callable[[], t.Any]] = False
2534
+
2535
+ if flag_value is None:
2536
+ flag_value = not self.default
2537
+
2538
+ if is_flag and type is None:
2539
+ # Re-guess the type from the flag value instead of the
2540
+ # default.
2541
+ self.type = types.convert_type(None, flag_value)
2542
+
2543
+ self.is_flag: bool = is_flag
2544
+ self.is_bool_flag = is_flag and isinstance(self.type, types.BoolParamType)
2545
+ self.flag_value: t.Any = flag_value
2546
+
2547
+ # Counting
2548
+ self.count = count
2549
+ if count:
2550
+ if type is None:
2551
+ self.type = types.IntRange(min=0)
2552
+ if default_is_missing:
2553
+ self.default = 0
2554
+
2555
+ self.allow_from_autoenv = allow_from_autoenv
2556
+ self.help = help
2557
+ self.show_default = show_default
2558
+ self.show_choices = show_choices
2559
+ self.show_envvar = show_envvar
2560
+
2561
+ if __debug__:
2562
+ if self.nargs == -1:
2563
+ raise TypeError("nargs=-1 is not supported for options.")
2564
+
2565
+ if self.prompt and self.is_flag and not self.is_bool_flag:
2566
+ raise TypeError("'prompt' is not valid for non-boolean flag.")
2567
+
2568
+ if not self.is_bool_flag and self.secondary_opts:
2569
+ raise TypeError("Secondary flag is not valid for non-boolean flag.")
2570
+
2571
+ if self.is_bool_flag and self.hide_input and self.prompt is not None:
2572
+ raise TypeError(
2573
+ "'prompt' with 'hide_input' is not valid for boolean flag."
2574
+ )
2575
+
2576
+ if self.count:
2577
+ if self.multiple:
2578
+ raise TypeError("'count' is not valid with 'multiple'.")
2579
+
2580
+ if self.is_flag:
2581
+ raise TypeError("'count' is not valid with 'is_flag'.")
2582
+
2583
+ if self.multiple and self.is_flag:
2584
+ raise TypeError("'multiple' is not valid with 'is_flag', use 'count'.")
2585
+
2586
+ def to_info_dict(self) -> t.Dict[str, t.Any]:
2587
+ info_dict = super().to_info_dict()
2588
+ info_dict.update(
2589
+ help=self.help,
2590
+ prompt=self.prompt,
2591
+ is_flag=self.is_flag,
2592
+ flag_value=self.flag_value,
2593
+ count=self.count,
2594
+ hidden=self.hidden,
2595
+ )
2596
+ return info_dict
2597
+
2598
+ def _parse_decls(
2599
+ self, decls: t.Sequence[str], expose_value: bool
2600
+ ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]:
2601
+ opts = []
2602
+ secondary_opts = []
2603
+ name = None
2604
+ possible_names = []
2605
+
2606
+ for decl in decls:
2607
+ if decl.isidentifier():
2608
+ if name is not None:
2609
+ raise TypeError(f"Name '{name}' defined twice")
2610
+ name = decl
2611
+ else:
2612
+ split_char = ";" if decl[:1] == "/" else "/"
2613
+ if split_char in decl:
2614
+ first, second = decl.split(split_char, 1)
2615
+ first = first.rstrip()
2616
+ if first:
2617
+ possible_names.append(split_opt(first))
2618
+ opts.append(first)
2619
+ second = second.lstrip()
2620
+ if second:
2621
+ secondary_opts.append(second.lstrip())
2622
+ if first == second:
2623
+ raise ValueError(
2624
+ f"Boolean option {decl!r} cannot use the"
2625
+ " same flag for true/false."
2626
+ )
2627
+ else:
2628
+ possible_names.append(split_opt(decl))
2629
+ opts.append(decl)
2630
+
2631
+ if name is None and possible_names:
2632
+ possible_names.sort(key=lambda x: -len(x[0])) # group long options first
2633
+ name = possible_names[0][1].replace("-", "_").lower()
2634
+ if not name.isidentifier():
2635
+ name = None
2636
+
2637
+ if name is None:
2638
+ if not expose_value:
2639
+ return None, opts, secondary_opts
2640
+ raise TypeError("Could not determine name for option")
2641
+
2642
+ if not opts and not secondary_opts:
2643
+ raise TypeError(
2644
+ f"No options defined but a name was passed ({name})."
2645
+ " Did you mean to declare an argument instead? Did"
2646
+ f" you mean to pass '--{name}'?"
2647
+ )
2648
+
2649
+ return name, opts, secondary_opts
2650
+
2651
+ def add_to_parser(self, parser: OptionParser, ctx: Context) -> None:
2652
+ if self.multiple:
2653
+ action = "append"
2654
+ elif self.count:
2655
+ action = "count"
2656
+ else:
2657
+ action = "store"
2658
+
2659
+ if self.is_flag:
2660
+ action = f"{action}_const"
2661
+
2662
+ if self.is_bool_flag and self.secondary_opts:
2663
+ parser.add_option(
2664
+ obj=self, opts=self.opts, dest=self.name, action=action, const=True
2665
+ )
2666
+ parser.add_option(
2667
+ obj=self,
2668
+ opts=self.secondary_opts,
2669
+ dest=self.name,
2670
+ action=action,
2671
+ const=False,
2672
+ )
2673
+ else:
2674
+ parser.add_option(
2675
+ obj=self,
2676
+ opts=self.opts,
2677
+ dest=self.name,
2678
+ action=action,
2679
+ const=self.flag_value,
2680
+ )
2681
+ else:
2682
+ parser.add_option(
2683
+ obj=self,
2684
+ opts=self.opts,
2685
+ dest=self.name,
2686
+ action=action,
2687
+ nargs=self.nargs,
2688
+ )
2689
+
2690
+ def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]:
2691
+ if self.hidden:
2692
+ return None
2693
+
2694
+ any_prefix_is_slash = False
2695
+
2696
+ def _write_opts(opts: t.Sequence[str]) -> str:
2697
+ nonlocal any_prefix_is_slash
2698
+
2699
+ rv, any_slashes = join_options(opts)
2700
+
2701
+ if any_slashes:
2702
+ any_prefix_is_slash = True
2703
+
2704
+ if not self.is_flag and not self.count:
2705
+ rv += f" {self.make_metavar()}"
2706
+
2707
+ return rv
2708
+
2709
+ rv = [_write_opts(self.opts)]
2710
+
2711
+ if self.secondary_opts:
2712
+ rv.append(_write_opts(self.secondary_opts))
2713
+
2714
+ help = self.help or ""
2715
+ extra = []
2716
+
2717
+ if self.show_envvar:
2718
+ envvar = self.envvar
2719
+
2720
+ if envvar is None:
2721
+ if (
2722
+ self.allow_from_autoenv
2723
+ and ctx.auto_envvar_prefix is not None
2724
+ and self.name is not None
2725
+ ):
2726
+ envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}"
2727
+
2728
+ if envvar is not None:
2729
+ var_str = (
2730
+ envvar
2731
+ if isinstance(envvar, str)
2732
+ else ", ".join(str(d) for d in envvar)
2733
+ )
2734
+ extra.append(_("env var: {var}").format(var=var_str))
2735
+
2736
+ # Temporarily enable resilient parsing to avoid type casting
2737
+ # failing for the default. Might be possible to extend this to
2738
+ # help formatting in general.
2739
+ resilient = ctx.resilient_parsing
2740
+ ctx.resilient_parsing = True
2741
+
2742
+ try:
2743
+ default_value = self.get_default(ctx, call=False)
2744
+ finally:
2745
+ ctx.resilient_parsing = resilient
2746
+
2747
+ show_default = False
2748
+ show_default_is_str = False
2749
+
2750
+ if self.show_default is not None:
2751
+ if isinstance(self.show_default, str):
2752
+ show_default_is_str = show_default = True
2753
+ else:
2754
+ show_default = self.show_default
2755
+ elif ctx.show_default is not None:
2756
+ show_default = ctx.show_default
2757
+
2758
+ if show_default_is_str or (show_default and (default_value is not None)):
2759
+ if show_default_is_str:
2760
+ default_string = f"({self.show_default})"
2761
+ elif isinstance(default_value, (list, tuple)):
2762
+ default_string = ", ".join(str(d) for d in default_value)
2763
+ elif inspect.isfunction(default_value):
2764
+ default_string = _("(dynamic)")
2765
+ elif self.is_bool_flag and self.secondary_opts:
2766
+ # For boolean flags that have distinct True/False opts,
2767
+ # use the opt without prefix instead of the value.
2768
+ default_string = split_opt(
2769
+ (self.opts if self.default else self.secondary_opts)[0]
2770
+ )[1]
2771
+ elif self.is_bool_flag and not self.secondary_opts and not default_value:
2772
+ default_string = ""
2773
+ else:
2774
+ default_string = str(default_value)
2775
+
2776
+ if default_string:
2777
+ extra.append(_("default: {default}").format(default=default_string))
2778
+
2779
+ if (
2780
+ isinstance(self.type, types._NumberRangeBase)
2781
+ # skip count with default range type
2782
+ and not (self.count and self.type.min == 0 and self.type.max is None)
2783
+ ):
2784
+ range_str = self.type._describe_range()
2785
+
2786
+ if range_str:
2787
+ extra.append(range_str)
2788
+
2789
+ if self.required:
2790
+ extra.append(_("required"))
2791
+
2792
+ if extra:
2793
+ extra_str = "; ".join(extra)
2794
+ help = f"{help} [{extra_str}]" if help else f"[{extra_str}]"
2795
+
2796
+ return ("; " if any_prefix_is_slash else " / ").join(rv), help
2797
+
2798
+ @t.overload
2799
+ def get_default(
2800
+ self, ctx: Context, call: "te.Literal[True]" = True
2801
+ ) -> t.Optional[t.Any]:
2802
+ ...
2803
+
2804
+ @t.overload
2805
+ def get_default(
2806
+ self, ctx: Context, call: bool = ...
2807
+ ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]:
2808
+ ...
2809
+
2810
+ def get_default(
2811
+ self, ctx: Context, call: bool = True
2812
+ ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]:
2813
+ # If we're a non boolean flag our default is more complex because
2814
+ # we need to look at all flags in the same group to figure out
2815
+ # if we're the default one in which case we return the flag
2816
+ # value as default.
2817
+ if self.is_flag and not self.is_bool_flag:
2818
+ for param in ctx.command.params:
2819
+ if param.name == self.name and param.default:
2820
+ return param.flag_value # type: ignore
2821
+
2822
+ return None
2823
+
2824
+ return super().get_default(ctx, call=call)
2825
+
2826
+ def prompt_for_value(self, ctx: Context) -> t.Any:
2827
+ """This is an alternative flow that can be activated in the full
2828
+ value processing if a value does not exist. It will prompt the
2829
+ user until a valid value exists and then returns the processed
2830
+ value as result.
2831
+ """
2832
+ assert self.prompt is not None
2833
+
2834
+ # Calculate the default before prompting anything to be stable.
2835
+ default = self.get_default(ctx)
2836
+
2837
+ # If this is a prompt for a flag we need to handle this
2838
+ # differently.
2839
+ if self.is_bool_flag:
2840
+ return confirm(self.prompt, default)
2841
+
2842
+ return prompt(
2843
+ self.prompt,
2844
+ default=default,
2845
+ type=self.type,
2846
+ hide_input=self.hide_input,
2847
+ show_choices=self.show_choices,
2848
+ confirmation_prompt=self.confirmation_prompt,
2849
+ value_proc=lambda x: self.process_value(ctx, x),
2850
+ )
2851
+
2852
+ def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]:
2853
+ rv = super().resolve_envvar_value(ctx)
2854
+
2855
+ if rv is not None:
2856
+ return rv
2857
+
2858
+ if (
2859
+ self.allow_from_autoenv
2860
+ and ctx.auto_envvar_prefix is not None
2861
+ and self.name is not None
2862
+ ):
2863
+ envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}"
2864
+ rv = os.environ.get(envvar)
2865
+
2866
+ if rv:
2867
+ return rv
2868
+
2869
+ return None
2870
+
2871
+ def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]:
2872
+ rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx)
2873
+
2874
+ if rv is None:
2875
+ return None
2876
+
2877
+ value_depth = (self.nargs != 1) + bool(self.multiple)
2878
+
2879
+ if value_depth > 0:
2880
+ rv = self.type.split_envvar_value(rv)
2881
+
2882
+ if self.multiple and self.nargs != 1:
2883
+ rv = batch(rv, self.nargs)
2884
+
2885
+ return rv
2886
+
2887
+ def consume_value(
2888
+ self, ctx: Context, opts: t.Mapping[str, "Parameter"]
2889
+ ) -> t.Tuple[t.Any, ParameterSource]:
2890
+ value, source = super().consume_value(ctx, opts)
2891
+
2892
+ # The parser will emit a sentinel value if the option can be
2893
+ # given as a flag without a value. This is different from None
2894
+ # to distinguish from the flag not being given at all.
2895
+ if value is _flag_needs_value:
2896
+ if self.prompt is not None and not ctx.resilient_parsing:
2897
+ value = self.prompt_for_value(ctx)
2898
+ source = ParameterSource.PROMPT
2899
+ else:
2900
+ value = self.flag_value
2901
+ source = ParameterSource.COMMANDLINE
2902
+
2903
+ elif (
2904
+ self.multiple
2905
+ and value is not None
2906
+ and any(v is _flag_needs_value for v in value)
2907
+ ):
2908
+ value = [self.flag_value if v is _flag_needs_value else v for v in value]
2909
+ source = ParameterSource.COMMANDLINE
2910
+
2911
+ # The value wasn't set, or used the param's default, prompt if
2912
+ # prompting is enabled.
2913
+ elif (
2914
+ source in {None, ParameterSource.DEFAULT}
2915
+ and self.prompt is not None
2916
+ and (self.required or self.prompt_required)
2917
+ and not ctx.resilient_parsing
2918
+ ):
2919
+ value = self.prompt_for_value(ctx)
2920
+ source = ParameterSource.PROMPT
2921
+
2922
+ return value, source
2923
+
2924
+
2925
+ class Argument(Parameter):
2926
+ """Arguments are positional parameters to a command. They generally
2927
+ provide fewer features than options but can have infinite ``nargs``
2928
+ and are required by default.
2929
+
2930
+ All parameters are passed onwards to the parameter constructor.
2931
+ """
2932
+
2933
+ param_type_name = "argument"
2934
+
2935
+ def __init__(
2936
+ self,
2937
+ param_decls: t.Sequence[str],
2938
+ required: t.Optional[bool] = None,
2939
+ **attrs: t.Any,
2940
+ ) -> None:
2941
+ if required is None:
2942
+ if attrs.get("default") is not None:
2943
+ required = False
2944
+ else:
2945
+ required = attrs.get("nargs", 1) > 0
2946
+
2947
+ if "multiple" in attrs:
2948
+ raise TypeError("__init__() got an unexpected keyword argument 'multiple'.")
2949
+
2950
+ super().__init__(param_decls, required=required, **attrs)
2951
+
2952
+ if __debug__:
2953
+ if self.default is not None and self.nargs == -1:
2954
+ raise TypeError("'default' is not supported for nargs=-1.")
2955
+
2956
+ @property
2957
+ def human_readable_name(self) -> str:
2958
+ if self.metavar is not None:
2959
+ return self.metavar
2960
+ return self.name.upper() # type: ignore
2961
+
2962
+ def make_metavar(self) -> str:
2963
+ if self.metavar is not None:
2964
+ return self.metavar
2965
+ var = self.type.get_metavar(self)
2966
+ if not var:
2967
+ var = self.name.upper() # type: ignore
2968
+ if not self.required:
2969
+ var = f"[{var}]"
2970
+ if self.nargs != 1:
2971
+ var += "..."
2972
+ return var
2973
+
2974
+ def _parse_decls(
2975
+ self, decls: t.Sequence[str], expose_value: bool
2976
+ ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]:
2977
+ if not decls:
2978
+ if not expose_value:
2979
+ return None, [], []
2980
+ raise TypeError("Could not determine name for argument")
2981
+ if len(decls) == 1:
2982
+ name = arg = decls[0]
2983
+ name = name.replace("-", "_").lower()
2984
+ else:
2985
+ raise TypeError(
2986
+ "Arguments take exactly one parameter declaration, got"
2987
+ f" {len(decls)}."
2988
+ )
2989
+ return name, [arg], []
2990
+
2991
+ def get_usage_pieces(self, ctx: Context) -> t.List[str]:
2992
+ return [self.make_metavar()]
2993
+
2994
+ def get_error_hint(self, ctx: Context) -> str:
2995
+ return f"'{self.make_metavar()}'"
2996
+
2997
+ def add_to_parser(self, parser: OptionParser, ctx: Context) -> None:
2998
+ parser.add_argument(dest=self.name, nargs=self.nargs, obj=self)