outerbounds 0.3.55rc8__py3-none-any.whl → 0.3.133__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 +450 -0
  42. outerbounds/command_groups/cli.py +9 -5
  43. outerbounds/command_groups/local_setup_cli.py +247 -36
  44. outerbounds/command_groups/perimeters_cli.py +212 -32
  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 +93 -16
  49. outerbounds/utils/schema.py +2 -2
  50. outerbounds/utils/utils.py +19 -0
  51. outerbounds/vendor.py +159 -0
  52. {outerbounds-0.3.55rc8.dist-info → outerbounds-0.3.133.dist-info}/METADATA +17 -6
  53. outerbounds-0.3.133.dist-info/RECORD +59 -0
  54. {outerbounds-0.3.55rc8.dist-info → outerbounds-0.3.133.dist-info}/WHEEL +1 -1
  55. outerbounds-0.3.55rc8.dist-info/RECORD +0 -15
  56. {outerbounds-0.3.55rc8.dist-info → outerbounds-0.3.133.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,580 @@
1
+ import os
2
+ import re
3
+ import typing as t
4
+ from gettext import gettext as _
5
+
6
+ from .core import Argument
7
+ from .core import BaseCommand
8
+ from .core import Context
9
+ from .core import MultiCommand
10
+ from .core import Option
11
+ from .core import Parameter
12
+ from .core import ParameterSource
13
+ from .parser import split_arg_string
14
+ from .utils import echo
15
+
16
+
17
+ def shell_complete(
18
+ cli: BaseCommand,
19
+ ctx_args: t.Dict[str, t.Any],
20
+ prog_name: str,
21
+ complete_var: str,
22
+ instruction: str,
23
+ ) -> int:
24
+ """Perform shell completion for the given CLI program.
25
+
26
+ :param cli: Command being called.
27
+ :param ctx_args: Extra arguments to pass to
28
+ ``cli.make_context``.
29
+ :param prog_name: Name of the executable in the shell.
30
+ :param complete_var: Name of the environment variable that holds
31
+ the completion instruction.
32
+ :param instruction: Value of ``complete_var`` with the completion
33
+ instruction and shell, in the form ``instruction_shell``.
34
+ :return: Status code to exit with.
35
+ """
36
+ shell, _, instruction = instruction.partition("_")
37
+ comp_cls = get_completion_class(shell)
38
+
39
+ if comp_cls is None:
40
+ return 1
41
+
42
+ comp = comp_cls(cli, ctx_args, prog_name, complete_var)
43
+
44
+ if instruction == "source":
45
+ echo(comp.source())
46
+ return 0
47
+
48
+ if instruction == "complete":
49
+ echo(comp.complete())
50
+ return 0
51
+
52
+ return 1
53
+
54
+
55
+ class CompletionItem:
56
+ """Represents a completion value and metadata about the value. The
57
+ default metadata is ``type`` to indicate special shell handling,
58
+ and ``help`` if a shell supports showing a help string next to the
59
+ value.
60
+
61
+ Arbitrary parameters can be passed when creating the object, and
62
+ accessed using ``item.attr``. If an attribute wasn't passed,
63
+ accessing it returns ``None``.
64
+
65
+ :param value: The completion suggestion.
66
+ :param type: Tells the shell script to provide special completion
67
+ support for the type. Click uses ``"dir"`` and ``"file"``.
68
+ :param help: String shown next to the value if supported.
69
+ :param kwargs: Arbitrary metadata. The built-in implementations
70
+ don't use this, but custom type completions paired with custom
71
+ shell support could use it.
72
+ """
73
+
74
+ __slots__ = ("value", "type", "help", "_info")
75
+
76
+ def __init__(
77
+ self,
78
+ value: t.Any,
79
+ type: str = "plain",
80
+ help: t.Optional[str] = None,
81
+ **kwargs: t.Any,
82
+ ) -> None:
83
+ self.value = value
84
+ self.type = type
85
+ self.help = help
86
+ self._info = kwargs
87
+
88
+ def __getattr__(self, name: str) -> t.Any:
89
+ return self._info.get(name)
90
+
91
+
92
+ # Only Bash >= 4.4 has the nosort option.
93
+ _SOURCE_BASH = """\
94
+ %(complete_func)s() {
95
+ local IFS=$'\\n'
96
+ local response
97
+
98
+ response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \
99
+ %(complete_var)s=bash_complete $1)
100
+
101
+ for completion in $response; do
102
+ IFS=',' read type value <<< "$completion"
103
+
104
+ if [[ $type == 'dir' ]]; then
105
+ COMPREPLY=()
106
+ compopt -o dirnames
107
+ elif [[ $type == 'file' ]]; then
108
+ COMPREPLY=()
109
+ compopt -o default
110
+ elif [[ $type == 'plain' ]]; then
111
+ COMPREPLY+=($value)
112
+ fi
113
+ done
114
+
115
+ return 0
116
+ }
117
+
118
+ %(complete_func)s_setup() {
119
+ complete -o nosort -F %(complete_func)s %(prog_name)s
120
+ }
121
+
122
+ %(complete_func)s_setup;
123
+ """
124
+
125
+ _SOURCE_ZSH = """\
126
+ #compdef %(prog_name)s
127
+
128
+ %(complete_func)s() {
129
+ local -a completions
130
+ local -a completions_with_descriptions
131
+ local -a response
132
+ (( ! $+commands[%(prog_name)s] )) && return 1
133
+
134
+ response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \
135
+ %(complete_var)s=zsh_complete %(prog_name)s)}")
136
+
137
+ for type key descr in ${response}; do
138
+ if [[ "$type" == "plain" ]]; then
139
+ if [[ "$descr" == "_" ]]; then
140
+ completions+=("$key")
141
+ else
142
+ completions_with_descriptions+=("$key":"$descr")
143
+ fi
144
+ elif [[ "$type" == "dir" ]]; then
145
+ _path_files -/
146
+ elif [[ "$type" == "file" ]]; then
147
+ _path_files -f
148
+ fi
149
+ done
150
+
151
+ if [ -n "$completions_with_descriptions" ]; then
152
+ _describe -V unsorted completions_with_descriptions -U
153
+ fi
154
+
155
+ if [ -n "$completions" ]; then
156
+ compadd -U -V unsorted -a completions
157
+ fi
158
+ }
159
+
160
+ compdef %(complete_func)s %(prog_name)s;
161
+ """
162
+
163
+ _SOURCE_FISH = """\
164
+ function %(complete_func)s;
165
+ set -l response;
166
+
167
+ for value in (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \
168
+ COMP_CWORD=(commandline -t) %(prog_name)s);
169
+ set response $response $value;
170
+ end;
171
+
172
+ for completion in $response;
173
+ set -l metadata (string split "," $completion);
174
+
175
+ if test $metadata[1] = "dir";
176
+ __fish_complete_directories $metadata[2];
177
+ else if test $metadata[1] = "file";
178
+ __fish_complete_path $metadata[2];
179
+ else if test $metadata[1] = "plain";
180
+ echo $metadata[2];
181
+ end;
182
+ end;
183
+ end;
184
+
185
+ complete --no-files --command %(prog_name)s --arguments \
186
+ "(%(complete_func)s)";
187
+ """
188
+
189
+
190
+ class ShellComplete:
191
+ """Base class for providing shell completion support. A subclass for
192
+ a given shell will override attributes and methods to implement the
193
+ completion instructions (``source`` and ``complete``).
194
+
195
+ :param cli: Command being called.
196
+ :param prog_name: Name of the executable in the shell.
197
+ :param complete_var: Name of the environment variable that holds
198
+ the completion instruction.
199
+
200
+ .. versionadded:: 8.0
201
+ """
202
+
203
+ name: t.ClassVar[str]
204
+ """Name to register the shell as with :func:`add_completion_class`.
205
+ This is used in completion instructions (``{name}_source`` and
206
+ ``{name}_complete``).
207
+ """
208
+
209
+ source_template: t.ClassVar[str]
210
+ """Completion script template formatted by :meth:`source`. This must
211
+ be provided by subclasses.
212
+ """
213
+
214
+ def __init__(
215
+ self,
216
+ cli: BaseCommand,
217
+ ctx_args: t.Dict[str, t.Any],
218
+ prog_name: str,
219
+ complete_var: str,
220
+ ) -> None:
221
+ self.cli = cli
222
+ self.ctx_args = ctx_args
223
+ self.prog_name = prog_name
224
+ self.complete_var = complete_var
225
+
226
+ @property
227
+ def func_name(self) -> str:
228
+ """The name of the shell function defined by the completion
229
+ script.
230
+ """
231
+ safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), re.ASCII)
232
+ return f"_{safe_name}_completion"
233
+
234
+ def source_vars(self) -> t.Dict[str, t.Any]:
235
+ """Vars for formatting :attr:`source_template`.
236
+
237
+ By default this provides ``complete_func``, ``complete_var``,
238
+ and ``prog_name``.
239
+ """
240
+ return {
241
+ "complete_func": self.func_name,
242
+ "complete_var": self.complete_var,
243
+ "prog_name": self.prog_name,
244
+ }
245
+
246
+ def source(self) -> str:
247
+ """Produce the shell script that defines the completion
248
+ function. By default this ``%``-style formats
249
+ :attr:`source_template` with the dict returned by
250
+ :meth:`source_vars`.
251
+ """
252
+ return self.source_template % self.source_vars()
253
+
254
+ def get_completion_args(self) -> t.Tuple[t.List[str], str]:
255
+ """Use the env vars defined by the shell script to return a
256
+ tuple of ``args, incomplete``. This must be implemented by
257
+ subclasses.
258
+ """
259
+ raise NotImplementedError
260
+
261
+ def get_completions(
262
+ self, args: t.List[str], incomplete: str
263
+ ) -> t.List[CompletionItem]:
264
+ """Determine the context and last complete command or parameter
265
+ from the complete args. Call that object's ``shell_complete``
266
+ method to get the completions for the incomplete value.
267
+
268
+ :param args: List of complete args before the incomplete value.
269
+ :param incomplete: Value being completed. May be empty.
270
+ """
271
+ ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args)
272
+ obj, incomplete = _resolve_incomplete(ctx, args, incomplete)
273
+ return obj.shell_complete(ctx, incomplete)
274
+
275
+ def format_completion(self, item: CompletionItem) -> str:
276
+ """Format a completion item into the form recognized by the
277
+ shell script. This must be implemented by subclasses.
278
+
279
+ :param item: Completion item to format.
280
+ """
281
+ raise NotImplementedError
282
+
283
+ def complete(self) -> str:
284
+ """Produce the completion data to send back to the shell.
285
+
286
+ By default this calls :meth:`get_completion_args`, gets the
287
+ completions, then calls :meth:`format_completion` for each
288
+ completion.
289
+ """
290
+ args, incomplete = self.get_completion_args()
291
+ completions = self.get_completions(args, incomplete)
292
+ out = [self.format_completion(item) for item in completions]
293
+ return "\n".join(out)
294
+
295
+
296
+ class BashComplete(ShellComplete):
297
+ """Shell completion for Bash."""
298
+
299
+ name = "bash"
300
+ source_template = _SOURCE_BASH
301
+
302
+ def _check_version(self) -> None:
303
+ import subprocess
304
+
305
+ output = subprocess.run(
306
+ ["bash", "-c", "echo ${BASH_VERSION}"], stdout=subprocess.PIPE
307
+ )
308
+ match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode())
309
+
310
+ if match is not None:
311
+ major, minor = match.groups()
312
+
313
+ if major < "4" or major == "4" and minor < "4":
314
+ raise RuntimeError(
315
+ _(
316
+ "Shell completion is not supported for Bash"
317
+ " versions older than 4.4."
318
+ )
319
+ )
320
+ else:
321
+ raise RuntimeError(
322
+ _("Couldn't detect Bash version, shell completion is not supported.")
323
+ )
324
+
325
+ def source(self) -> str:
326
+ self._check_version()
327
+ return super().source()
328
+
329
+ def get_completion_args(self) -> t.Tuple[t.List[str], str]:
330
+ cwords = split_arg_string(os.environ["COMP_WORDS"])
331
+ cword = int(os.environ["COMP_CWORD"])
332
+ args = cwords[1:cword]
333
+
334
+ try:
335
+ incomplete = cwords[cword]
336
+ except IndexError:
337
+ incomplete = ""
338
+
339
+ return args, incomplete
340
+
341
+ def format_completion(self, item: CompletionItem) -> str:
342
+ return f"{item.type},{item.value}"
343
+
344
+
345
+ class ZshComplete(ShellComplete):
346
+ """Shell completion for Zsh."""
347
+
348
+ name = "zsh"
349
+ source_template = _SOURCE_ZSH
350
+
351
+ def get_completion_args(self) -> t.Tuple[t.List[str], str]:
352
+ cwords = split_arg_string(os.environ["COMP_WORDS"])
353
+ cword = int(os.environ["COMP_CWORD"])
354
+ args = cwords[1:cword]
355
+
356
+ try:
357
+ incomplete = cwords[cword]
358
+ except IndexError:
359
+ incomplete = ""
360
+
361
+ return args, incomplete
362
+
363
+ def format_completion(self, item: CompletionItem) -> str:
364
+ return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}"
365
+
366
+
367
+ class FishComplete(ShellComplete):
368
+ """Shell completion for Fish."""
369
+
370
+ name = "fish"
371
+ source_template = _SOURCE_FISH
372
+
373
+ def get_completion_args(self) -> t.Tuple[t.List[str], str]:
374
+ cwords = split_arg_string(os.environ["COMP_WORDS"])
375
+ incomplete = os.environ["COMP_CWORD"]
376
+ args = cwords[1:]
377
+
378
+ # Fish stores the partial word in both COMP_WORDS and
379
+ # COMP_CWORD, remove it from complete args.
380
+ if incomplete and args and args[-1] == incomplete:
381
+ args.pop()
382
+
383
+ return args, incomplete
384
+
385
+ def format_completion(self, item: CompletionItem) -> str:
386
+ if item.help:
387
+ return f"{item.type},{item.value}\t{item.help}"
388
+
389
+ return f"{item.type},{item.value}"
390
+
391
+
392
+ _available_shells: t.Dict[str, t.Type[ShellComplete]] = {
393
+ "bash": BashComplete,
394
+ "fish": FishComplete,
395
+ "zsh": ZshComplete,
396
+ }
397
+
398
+
399
+ def add_completion_class(
400
+ cls: t.Type[ShellComplete], name: t.Optional[str] = None
401
+ ) -> None:
402
+ """Register a :class:`ShellComplete` subclass under the given name.
403
+ The name will be provided by the completion instruction environment
404
+ variable during completion.
405
+
406
+ :param cls: The completion class that will handle completion for the
407
+ shell.
408
+ :param name: Name to register the class under. Defaults to the
409
+ class's ``name`` attribute.
410
+ """
411
+ if name is None:
412
+ name = cls.name
413
+
414
+ _available_shells[name] = cls
415
+
416
+
417
+ def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]:
418
+ """Look up a registered :class:`ShellComplete` subclass by the name
419
+ provided by the completion instruction environment variable. If the
420
+ name isn't registered, returns ``None``.
421
+
422
+ :param shell: Name the class is registered under.
423
+ """
424
+ return _available_shells.get(shell)
425
+
426
+
427
+ def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool:
428
+ """Determine if the given parameter is an argument that can still
429
+ accept values.
430
+
431
+ :param ctx: Invocation context for the command represented by the
432
+ parsed complete args.
433
+ :param param: Argument object being checked.
434
+ """
435
+ if not isinstance(param, Argument):
436
+ return False
437
+
438
+ assert param.name is not None
439
+ value = ctx.params[param.name]
440
+ return (
441
+ param.nargs == -1
442
+ or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE
443
+ or (
444
+ param.nargs > 1
445
+ and isinstance(value, (tuple, list))
446
+ and len(value) < param.nargs
447
+ )
448
+ )
449
+
450
+
451
+ def _start_of_option(ctx: Context, value: str) -> bool:
452
+ """Check if the value looks like the start of an option."""
453
+ if not value:
454
+ return False
455
+
456
+ c = value[0]
457
+ return c in ctx._opt_prefixes
458
+
459
+
460
+ def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool:
461
+ """Determine if the given parameter is an option that needs a value.
462
+
463
+ :param args: List of complete args before the incomplete value.
464
+ :param param: Option object being checked.
465
+ """
466
+ if not isinstance(param, Option):
467
+ return False
468
+
469
+ if param.is_flag or param.count:
470
+ return False
471
+
472
+ last_option = None
473
+
474
+ for index, arg in enumerate(reversed(args)):
475
+ if index + 1 > param.nargs:
476
+ break
477
+
478
+ if _start_of_option(ctx, arg):
479
+ last_option = arg
480
+
481
+ return last_option is not None and last_option in param.opts
482
+
483
+
484
+ def _resolve_context(
485
+ cli: BaseCommand, ctx_args: t.Dict[str, t.Any], prog_name: str, args: t.List[str]
486
+ ) -> Context:
487
+ """Produce the context hierarchy starting with the command and
488
+ traversing the complete arguments. This only follows the commands,
489
+ it doesn't trigger input prompts or callbacks.
490
+
491
+ :param cli: Command being called.
492
+ :param prog_name: Name of the executable in the shell.
493
+ :param args: List of complete args before the incomplete value.
494
+ """
495
+ ctx_args["resilient_parsing"] = True
496
+ ctx = cli.make_context(prog_name, args.copy(), **ctx_args)
497
+ args = ctx.protected_args + ctx.args
498
+
499
+ while args:
500
+ command = ctx.command
501
+
502
+ if isinstance(command, MultiCommand):
503
+ if not command.chain:
504
+ name, cmd, args = command.resolve_command(ctx, args)
505
+
506
+ if cmd is None:
507
+ return ctx
508
+
509
+ ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True)
510
+ args = ctx.protected_args + ctx.args
511
+ else:
512
+ while args:
513
+ name, cmd, args = command.resolve_command(ctx, args)
514
+
515
+ if cmd is None:
516
+ return ctx
517
+
518
+ sub_ctx = cmd.make_context(
519
+ name,
520
+ args,
521
+ parent=ctx,
522
+ allow_extra_args=True,
523
+ allow_interspersed_args=False,
524
+ resilient_parsing=True,
525
+ )
526
+ args = sub_ctx.args
527
+
528
+ ctx = sub_ctx
529
+ args = [*sub_ctx.protected_args, *sub_ctx.args]
530
+ else:
531
+ break
532
+
533
+ return ctx
534
+
535
+
536
+ def _resolve_incomplete(
537
+ ctx: Context, args: t.List[str], incomplete: str
538
+ ) -> t.Tuple[t.Union[BaseCommand, Parameter], str]:
539
+ """Find the Click object that will handle the completion of the
540
+ incomplete value. Return the object and the incomplete value.
541
+
542
+ :param ctx: Invocation context for the command represented by
543
+ the parsed complete args.
544
+ :param args: List of complete args before the incomplete value.
545
+ :param incomplete: Value being completed. May be empty.
546
+ """
547
+ # Different shells treat an "=" between a long option name and
548
+ # value differently. Might keep the value joined, return the "="
549
+ # as a separate item, or return the split name and value. Always
550
+ # split and discard the "=" to make completion easier.
551
+ if incomplete == "=":
552
+ incomplete = ""
553
+ elif "=" in incomplete and _start_of_option(ctx, incomplete):
554
+ name, _, incomplete = incomplete.partition("=")
555
+ args.append(name)
556
+
557
+ # The "--" marker tells Click to stop treating values as options
558
+ # even if they start with the option character. If it hasn't been
559
+ # given and the incomplete arg looks like an option, the current
560
+ # command will provide option name completions.
561
+ if "--" not in args and _start_of_option(ctx, incomplete):
562
+ return ctx.command, incomplete
563
+
564
+ params = ctx.command.get_params(ctx)
565
+
566
+ # If the last complete arg is an option name with an incomplete
567
+ # value, the option will provide value completions.
568
+ for param in params:
569
+ if _is_incomplete_option(ctx, args, param):
570
+ return param, incomplete
571
+
572
+ # It's not an option name or value. The first argument without a
573
+ # parsed value will provide value completions.
574
+ for param in params:
575
+ if _is_incomplete_argument(ctx, param):
576
+ return param, incomplete
577
+
578
+ # There were no unparsed arguments, the command may be a group that
579
+ # will provide command name completions.
580
+ return ctx.command, incomplete