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,787 @@
1
+ import inspect
2
+ import io
3
+ import itertools
4
+ import os
5
+ import sys
6
+ import typing as t
7
+ from gettext import gettext as _
8
+
9
+ from ._compat import isatty
10
+ from ._compat import strip_ansi
11
+ from ._compat import WIN
12
+ from .exceptions import Abort
13
+ from .exceptions import UsageError
14
+ from .globals import resolve_color_default
15
+ from .types import Choice
16
+ from .types import convert_type
17
+ from .types import ParamType
18
+ from .utils import echo
19
+ from .utils import LazyFile
20
+
21
+ if t.TYPE_CHECKING:
22
+ from ._termui_impl import ProgressBar
23
+
24
+ V = t.TypeVar("V")
25
+
26
+ # The prompt functions to use. The doc tools currently override these
27
+ # functions to customize how they work.
28
+ visible_prompt_func: t.Callable[[str], str] = input
29
+
30
+ _ansi_colors = {
31
+ "black": 30,
32
+ "red": 31,
33
+ "green": 32,
34
+ "yellow": 33,
35
+ "blue": 34,
36
+ "magenta": 35,
37
+ "cyan": 36,
38
+ "white": 37,
39
+ "reset": 39,
40
+ "bright_black": 90,
41
+ "bright_red": 91,
42
+ "bright_green": 92,
43
+ "bright_yellow": 93,
44
+ "bright_blue": 94,
45
+ "bright_magenta": 95,
46
+ "bright_cyan": 96,
47
+ "bright_white": 97,
48
+ }
49
+ _ansi_reset_all = "\033[0m"
50
+
51
+
52
+ def hidden_prompt_func(prompt: str) -> str:
53
+ import getpass
54
+
55
+ return getpass.getpass(prompt)
56
+
57
+
58
+ def _build_prompt(
59
+ text: str,
60
+ suffix: str,
61
+ show_default: bool = False,
62
+ default: t.Optional[t.Any] = None,
63
+ show_choices: bool = True,
64
+ type: t.Optional[ParamType] = None,
65
+ ) -> str:
66
+ prompt = text
67
+ if type is not None and show_choices and isinstance(type, Choice):
68
+ prompt += f" ({', '.join(map(str, type.choices))})"
69
+ if default is not None and show_default:
70
+ prompt = f"{prompt} [{_format_default(default)}]"
71
+ return f"{prompt}{suffix}"
72
+
73
+
74
+ def _format_default(default: t.Any) -> t.Any:
75
+ if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"):
76
+ return default.name # type: ignore
77
+
78
+ return default
79
+
80
+
81
+ def prompt(
82
+ text: str,
83
+ default: t.Optional[t.Any] = None,
84
+ hide_input: bool = False,
85
+ confirmation_prompt: t.Union[bool, str] = False,
86
+ type: t.Optional[t.Union[ParamType, t.Any]] = None,
87
+ value_proc: t.Optional[t.Callable[[str], t.Any]] = None,
88
+ prompt_suffix: str = ": ",
89
+ show_default: bool = True,
90
+ err: bool = False,
91
+ show_choices: bool = True,
92
+ ) -> t.Any:
93
+ """Prompts a user for input. This is a convenience function that can
94
+ be used to prompt a user for input later.
95
+
96
+ If the user aborts the input by sending an interrupt signal, this
97
+ function will catch it and raise a :exc:`Abort` exception.
98
+
99
+ :param text: the text to show for the prompt.
100
+ :param default: the default value to use if no input happens. If this
101
+ is not given it will prompt until it's aborted.
102
+ :param hide_input: if this is set to true then the input value will
103
+ be hidden.
104
+ :param confirmation_prompt: Prompt a second time to confirm the
105
+ value. Can be set to a string instead of ``True`` to customize
106
+ the message.
107
+ :param type: the type to use to check the value against.
108
+ :param value_proc: if this parameter is provided it's a function that
109
+ is invoked instead of the type conversion to
110
+ convert a value.
111
+ :param prompt_suffix: a suffix that should be added to the prompt.
112
+ :param show_default: shows or hides the default value in the prompt.
113
+ :param err: if set to true the file defaults to ``stderr`` instead of
114
+ ``stdout``, the same as with echo.
115
+ :param show_choices: Show or hide choices if the passed type is a Choice.
116
+ For example if type is a Choice of either day or week,
117
+ show_choices is true and text is "Group by" then the
118
+ prompt will be "Group by (day, week): ".
119
+
120
+ .. versionadded:: 8.0
121
+ ``confirmation_prompt`` can be a custom string.
122
+
123
+ .. versionadded:: 7.0
124
+ Added the ``show_choices`` parameter.
125
+
126
+ .. versionadded:: 6.0
127
+ Added unicode support for cmd.exe on Windows.
128
+
129
+ .. versionadded:: 4.0
130
+ Added the `err` parameter.
131
+
132
+ """
133
+
134
+ def prompt_func(text: str) -> str:
135
+ f = hidden_prompt_func if hide_input else visible_prompt_func
136
+ try:
137
+ # Write the prompt separately so that we get nice
138
+ # coloring through colorama on Windows
139
+ echo(text.rstrip(" "), nl=False, err=err)
140
+ # Echo a space to stdout to work around an issue where
141
+ # readline causes backspace to clear the whole line.
142
+ return f(" ")
143
+ except (KeyboardInterrupt, EOFError):
144
+ # getpass doesn't print a newline if the user aborts input with ^C.
145
+ # Allegedly this behavior is inherited from getpass(3).
146
+ # A doc bug has been filed at https://bugs.python.org/issue24711
147
+ if hide_input:
148
+ echo(None, err=err)
149
+ raise Abort() from None
150
+
151
+ if value_proc is None:
152
+ value_proc = convert_type(type, default)
153
+
154
+ prompt = _build_prompt(
155
+ text, prompt_suffix, show_default, default, show_choices, type
156
+ )
157
+
158
+ if confirmation_prompt:
159
+ if confirmation_prompt is True:
160
+ confirmation_prompt = _("Repeat for confirmation")
161
+
162
+ confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix)
163
+
164
+ while True:
165
+ while True:
166
+ value = prompt_func(prompt)
167
+ if value:
168
+ break
169
+ elif default is not None:
170
+ value = default
171
+ break
172
+ try:
173
+ result = value_proc(value)
174
+ except UsageError as e:
175
+ if hide_input:
176
+ echo(_("Error: The value you entered was invalid."), err=err)
177
+ else:
178
+ echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306
179
+ continue
180
+ if not confirmation_prompt:
181
+ return result
182
+ while True:
183
+ value2 = prompt_func(confirmation_prompt)
184
+ is_empty = not value and not value2
185
+ if value2 or is_empty:
186
+ break
187
+ if value == value2:
188
+ return result
189
+ echo(_("Error: The two entered values do not match."), err=err)
190
+
191
+
192
+ def confirm(
193
+ text: str,
194
+ default: t.Optional[bool] = False,
195
+ abort: bool = False,
196
+ prompt_suffix: str = ": ",
197
+ show_default: bool = True,
198
+ err: bool = False,
199
+ ) -> bool:
200
+ """Prompts for confirmation (yes/no question).
201
+
202
+ If the user aborts the input by sending a interrupt signal this
203
+ function will catch it and raise a :exc:`Abort` exception.
204
+
205
+ :param text: the question to ask.
206
+ :param default: The default value to use when no input is given. If
207
+ ``None``, repeat until input is given.
208
+ :param abort: if this is set to `True` a negative answer aborts the
209
+ exception by raising :exc:`Abort`.
210
+ :param prompt_suffix: a suffix that should be added to the prompt.
211
+ :param show_default: shows or hides the default value in the prompt.
212
+ :param err: if set to true the file defaults to ``stderr`` instead of
213
+ ``stdout``, the same as with echo.
214
+
215
+ .. versionchanged:: 8.0
216
+ Repeat until input is given if ``default`` is ``None``.
217
+
218
+ .. versionadded:: 4.0
219
+ Added the ``err`` parameter.
220
+ """
221
+ prompt = _build_prompt(
222
+ text,
223
+ prompt_suffix,
224
+ show_default,
225
+ "y/n" if default is None else ("Y/n" if default else "y/N"),
226
+ )
227
+
228
+ while True:
229
+ try:
230
+ # Write the prompt separately so that we get nice
231
+ # coloring through colorama on Windows
232
+ echo(prompt.rstrip(" "), nl=False, err=err)
233
+ # Echo a space to stdout to work around an issue where
234
+ # readline causes backspace to clear the whole line.
235
+ value = visible_prompt_func(" ").lower().strip()
236
+ except (KeyboardInterrupt, EOFError):
237
+ raise Abort() from None
238
+ if value in ("y", "yes"):
239
+ rv = True
240
+ elif value in ("n", "no"):
241
+ rv = False
242
+ elif default is not None and value == "":
243
+ rv = default
244
+ else:
245
+ echo(_("Error: invalid input"), err=err)
246
+ continue
247
+ break
248
+ if abort and not rv:
249
+ raise Abort()
250
+ return rv
251
+
252
+
253
+ def echo_via_pager(
254
+ text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str],
255
+ color: t.Optional[bool] = None,
256
+ ) -> None:
257
+ """This function takes a text and shows it via an environment specific
258
+ pager on stdout.
259
+
260
+ .. versionchanged:: 3.0
261
+ Added the `color` flag.
262
+
263
+ :param text_or_generator: the text to page, or alternatively, a
264
+ generator emitting the text to page.
265
+ :param color: controls if the pager supports ANSI colors or not. The
266
+ default is autodetection.
267
+ """
268
+ color = resolve_color_default(color)
269
+
270
+ if inspect.isgeneratorfunction(text_or_generator):
271
+ i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)()
272
+ elif isinstance(text_or_generator, str):
273
+ i = [text_or_generator]
274
+ else:
275
+ i = iter(t.cast(t.Iterable[str], text_or_generator))
276
+
277
+ # convert every element of i to a text type if necessary
278
+ text_generator = (el if isinstance(el, str) else str(el) for el in i)
279
+
280
+ from ._termui_impl import pager
281
+
282
+ return pager(itertools.chain(text_generator, "\n"), color)
283
+
284
+
285
+ def progressbar(
286
+ iterable: t.Optional[t.Iterable[V]] = None,
287
+ length: t.Optional[int] = None,
288
+ label: t.Optional[str] = None,
289
+ show_eta: bool = True,
290
+ show_percent: t.Optional[bool] = None,
291
+ show_pos: bool = False,
292
+ item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None,
293
+ fill_char: str = "#",
294
+ empty_char: str = "-",
295
+ bar_template: str = "%(label)s [%(bar)s] %(info)s",
296
+ info_sep: str = " ",
297
+ width: int = 36,
298
+ file: t.Optional[t.TextIO] = None,
299
+ color: t.Optional[bool] = None,
300
+ update_min_steps: int = 1,
301
+ ) -> "ProgressBar[V]":
302
+ """This function creates an iterable context manager that can be used
303
+ to iterate over something while showing a progress bar. It will
304
+ either iterate over the `iterable` or `length` items (that are counted
305
+ up). While iteration happens, this function will print a rendered
306
+ progress bar to the given `file` (defaults to stdout) and will attempt
307
+ to calculate remaining time and more. By default, this progress bar
308
+ will not be rendered if the file is not a terminal.
309
+
310
+ The context manager creates the progress bar. When the context
311
+ manager is entered the progress bar is already created. With every
312
+ iteration over the progress bar, the iterable passed to the bar is
313
+ advanced and the bar is updated. When the context manager exits,
314
+ a newline is printed and the progress bar is finalized on screen.
315
+
316
+ Note: The progress bar is currently designed for use cases where the
317
+ total progress can be expected to take at least several seconds.
318
+ Because of this, the ProgressBar class object won't display
319
+ progress that is considered too fast, and progress where the time
320
+ between steps is less than a second.
321
+
322
+ No printing must happen or the progress bar will be unintentionally
323
+ destroyed.
324
+
325
+ Example usage::
326
+
327
+ with progressbar(items) as bar:
328
+ for item in bar:
329
+ do_something_with(item)
330
+
331
+ Alternatively, if no iterable is specified, one can manually update the
332
+ progress bar through the `update()` method instead of directly
333
+ iterating over the progress bar. The update method accepts the number
334
+ of steps to increment the bar with::
335
+
336
+ with progressbar(length=chunks.total_bytes) as bar:
337
+ for chunk in chunks:
338
+ process_chunk(chunk)
339
+ bar.update(chunks.bytes)
340
+
341
+ The ``update()`` method also takes an optional value specifying the
342
+ ``current_item`` at the new position. This is useful when used
343
+ together with ``item_show_func`` to customize the output for each
344
+ manual step::
345
+
346
+ with click.progressbar(
347
+ length=total_size,
348
+ label='Unzipping archive',
349
+ item_show_func=lambda a: a.filename
350
+ ) as bar:
351
+ for archive in zip_file:
352
+ archive.extract()
353
+ bar.update(archive.size, archive)
354
+
355
+ :param iterable: an iterable to iterate over. If not provided the length
356
+ is required.
357
+ :param length: the number of items to iterate over. By default the
358
+ progressbar will attempt to ask the iterator about its
359
+ length, which might or might not work. If an iterable is
360
+ also provided this parameter can be used to override the
361
+ length. If an iterable is not provided the progress bar
362
+ will iterate over a range of that length.
363
+ :param label: the label to show next to the progress bar.
364
+ :param show_eta: enables or disables the estimated time display. This is
365
+ automatically disabled if the length cannot be
366
+ determined.
367
+ :param show_percent: enables or disables the percentage display. The
368
+ default is `True` if the iterable has a length or
369
+ `False` if not.
370
+ :param show_pos: enables or disables the absolute position display. The
371
+ default is `False`.
372
+ :param item_show_func: A function called with the current item which
373
+ can return a string to show next to the progress bar. If the
374
+ function returns ``None`` nothing is shown. The current item can
375
+ be ``None``, such as when entering and exiting the bar.
376
+ :param fill_char: the character to use to show the filled part of the
377
+ progress bar.
378
+ :param empty_char: the character to use to show the non-filled part of
379
+ the progress bar.
380
+ :param bar_template: the format string to use as template for the bar.
381
+ The parameters in it are ``label`` for the label,
382
+ ``bar`` for the progress bar and ``info`` for the
383
+ info section.
384
+ :param info_sep: the separator between multiple info items (eta etc.)
385
+ :param width: the width of the progress bar in characters, 0 means full
386
+ terminal width
387
+ :param file: The file to write to. If this is not a terminal then
388
+ only the label is printed.
389
+ :param color: controls if the terminal supports ANSI colors or not. The
390
+ default is autodetection. This is only needed if ANSI
391
+ codes are included anywhere in the progress bar output
392
+ which is not the case by default.
393
+ :param update_min_steps: Render only when this many updates have
394
+ completed. This allows tuning for very fast iterators.
395
+
396
+ .. versionchanged:: 8.0
397
+ Output is shown even if execution time is less than 0.5 seconds.
398
+
399
+ .. versionchanged:: 8.0
400
+ ``item_show_func`` shows the current item, not the previous one.
401
+
402
+ .. versionchanged:: 8.0
403
+ Labels are echoed if the output is not a TTY. Reverts a change
404
+ in 7.0 that removed all output.
405
+
406
+ .. versionadded:: 8.0
407
+ Added the ``update_min_steps`` parameter.
408
+
409
+ .. versionchanged:: 4.0
410
+ Added the ``color`` parameter. Added the ``update`` method to
411
+ the object.
412
+
413
+ .. versionadded:: 2.0
414
+ """
415
+ from ._termui_impl import ProgressBar
416
+
417
+ color = resolve_color_default(color)
418
+ return ProgressBar(
419
+ iterable=iterable,
420
+ length=length,
421
+ show_eta=show_eta,
422
+ show_percent=show_percent,
423
+ show_pos=show_pos,
424
+ item_show_func=item_show_func,
425
+ fill_char=fill_char,
426
+ empty_char=empty_char,
427
+ bar_template=bar_template,
428
+ info_sep=info_sep,
429
+ file=file,
430
+ label=label,
431
+ width=width,
432
+ color=color,
433
+ update_min_steps=update_min_steps,
434
+ )
435
+
436
+
437
+ def clear() -> None:
438
+ """Clears the terminal screen. This will have the effect of clearing
439
+ the whole visible space of the terminal and moving the cursor to the
440
+ top left. This does not do anything if not connected to a terminal.
441
+
442
+ .. versionadded:: 2.0
443
+ """
444
+ if not isatty(sys.stdout):
445
+ return
446
+ if WIN:
447
+ os.system("cls")
448
+ else:
449
+ sys.stdout.write("\033[2J\033[1;1H")
450
+
451
+
452
+ def _interpret_color(
453
+ color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0
454
+ ) -> str:
455
+ if isinstance(color, int):
456
+ return f"{38 + offset};5;{color:d}"
457
+
458
+ if isinstance(color, (tuple, list)):
459
+ r, g, b = color
460
+ return f"{38 + offset};2;{r:d};{g:d};{b:d}"
461
+
462
+ return str(_ansi_colors[color] + offset)
463
+
464
+
465
+ def style(
466
+ text: t.Any,
467
+ fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None,
468
+ bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None,
469
+ bold: t.Optional[bool] = None,
470
+ dim: t.Optional[bool] = None,
471
+ underline: t.Optional[bool] = None,
472
+ overline: t.Optional[bool] = None,
473
+ italic: t.Optional[bool] = None,
474
+ blink: t.Optional[bool] = None,
475
+ reverse: t.Optional[bool] = None,
476
+ strikethrough: t.Optional[bool] = None,
477
+ reset: bool = True,
478
+ ) -> str:
479
+ """Styles a text with ANSI styles and returns the new string. By
480
+ default the styling is self contained which means that at the end
481
+ of the string a reset code is issued. This can be prevented by
482
+ passing ``reset=False``.
483
+
484
+ Examples::
485
+
486
+ click.echo(click.style('Hello World!', fg='green'))
487
+ click.echo(click.style('ATTENTION!', blink=True))
488
+ click.echo(click.style('Some things', reverse=True, fg='cyan'))
489
+ click.echo(click.style('More colors', fg=(255, 12, 128), bg=117))
490
+
491
+ Supported color names:
492
+
493
+ * ``black`` (might be a gray)
494
+ * ``red``
495
+ * ``green``
496
+ * ``yellow`` (might be an orange)
497
+ * ``blue``
498
+ * ``magenta``
499
+ * ``cyan``
500
+ * ``white`` (might be light gray)
501
+ * ``bright_black``
502
+ * ``bright_red``
503
+ * ``bright_green``
504
+ * ``bright_yellow``
505
+ * ``bright_blue``
506
+ * ``bright_magenta``
507
+ * ``bright_cyan``
508
+ * ``bright_white``
509
+ * ``reset`` (reset the color code only)
510
+
511
+ If the terminal supports it, color may also be specified as:
512
+
513
+ - An integer in the interval [0, 255]. The terminal must support
514
+ 8-bit/256-color mode.
515
+ - An RGB tuple of three integers in [0, 255]. The terminal must
516
+ support 24-bit/true-color mode.
517
+
518
+ See https://en.wikipedia.org/wiki/ANSI_color and
519
+ https://gist.github.com/XVilka/8346728 for more information.
520
+
521
+ :param text: the string to style with ansi codes.
522
+ :param fg: if provided this will become the foreground color.
523
+ :param bg: if provided this will become the background color.
524
+ :param bold: if provided this will enable or disable bold mode.
525
+ :param dim: if provided this will enable or disable dim mode. This is
526
+ badly supported.
527
+ :param underline: if provided this will enable or disable underline.
528
+ :param overline: if provided this will enable or disable overline.
529
+ :param italic: if provided this will enable or disable italic.
530
+ :param blink: if provided this will enable or disable blinking.
531
+ :param reverse: if provided this will enable or disable inverse
532
+ rendering (foreground becomes background and the
533
+ other way round).
534
+ :param strikethrough: if provided this will enable or disable
535
+ striking through text.
536
+ :param reset: by default a reset-all code is added at the end of the
537
+ string which means that styles do not carry over. This
538
+ can be disabled to compose styles.
539
+
540
+ .. versionchanged:: 8.0
541
+ A non-string ``message`` is converted to a string.
542
+
543
+ .. versionchanged:: 8.0
544
+ Added support for 256 and RGB color codes.
545
+
546
+ .. versionchanged:: 8.0
547
+ Added the ``strikethrough``, ``italic``, and ``overline``
548
+ parameters.
549
+
550
+ .. versionchanged:: 7.0
551
+ Added support for bright colors.
552
+
553
+ .. versionadded:: 2.0
554
+ """
555
+ if not isinstance(text, str):
556
+ text = str(text)
557
+
558
+ bits = []
559
+
560
+ if fg:
561
+ try:
562
+ bits.append(f"\033[{_interpret_color(fg)}m")
563
+ except KeyError:
564
+ raise TypeError(f"Unknown color {fg!r}") from None
565
+
566
+ if bg:
567
+ try:
568
+ bits.append(f"\033[{_interpret_color(bg, 10)}m")
569
+ except KeyError:
570
+ raise TypeError(f"Unknown color {bg!r}") from None
571
+
572
+ if bold is not None:
573
+ bits.append(f"\033[{1 if bold else 22}m")
574
+ if dim is not None:
575
+ bits.append(f"\033[{2 if dim else 22}m")
576
+ if underline is not None:
577
+ bits.append(f"\033[{4 if underline else 24}m")
578
+ if overline is not None:
579
+ bits.append(f"\033[{53 if overline else 55}m")
580
+ if italic is not None:
581
+ bits.append(f"\033[{3 if italic else 23}m")
582
+ if blink is not None:
583
+ bits.append(f"\033[{5 if blink else 25}m")
584
+ if reverse is not None:
585
+ bits.append(f"\033[{7 if reverse else 27}m")
586
+ if strikethrough is not None:
587
+ bits.append(f"\033[{9 if strikethrough else 29}m")
588
+ bits.append(text)
589
+ if reset:
590
+ bits.append(_ansi_reset_all)
591
+ return "".join(bits)
592
+
593
+
594
+ def unstyle(text: str) -> str:
595
+ """Removes ANSI styling information from a string. Usually it's not
596
+ necessary to use this function as Click's echo function will
597
+ automatically remove styling if necessary.
598
+
599
+ .. versionadded:: 2.0
600
+
601
+ :param text: the text to remove style information from.
602
+ """
603
+ return strip_ansi(text)
604
+
605
+
606
+ def secho(
607
+ message: t.Optional[t.Any] = None,
608
+ file: t.Optional[t.IO[t.AnyStr]] = None,
609
+ nl: bool = True,
610
+ err: bool = False,
611
+ color: t.Optional[bool] = None,
612
+ **styles: t.Any,
613
+ ) -> None:
614
+ """This function combines :func:`echo` and :func:`style` into one
615
+ call. As such the following two calls are the same::
616
+
617
+ click.secho('Hello World!', fg='green')
618
+ click.echo(click.style('Hello World!', fg='green'))
619
+
620
+ All keyword arguments are forwarded to the underlying functions
621
+ depending on which one they go with.
622
+
623
+ Non-string types will be converted to :class:`str`. However,
624
+ :class:`bytes` are passed directly to :meth:`echo` without applying
625
+ style. If you want to style bytes that represent text, call
626
+ :meth:`bytes.decode` first.
627
+
628
+ .. versionchanged:: 8.0
629
+ A non-string ``message`` is converted to a string. Bytes are
630
+ passed through without style applied.
631
+
632
+ .. versionadded:: 2.0
633
+ """
634
+ if message is not None and not isinstance(message, (bytes, bytearray)):
635
+ message = style(message, **styles)
636
+
637
+ return echo(message, file=file, nl=nl, err=err, color=color)
638
+
639
+
640
+ def edit(
641
+ text: t.Optional[t.AnyStr] = None,
642
+ editor: t.Optional[str] = None,
643
+ env: t.Optional[t.Mapping[str, str]] = None,
644
+ require_save: bool = True,
645
+ extension: str = ".txt",
646
+ filename: t.Optional[str] = None,
647
+ ) -> t.Optional[t.AnyStr]:
648
+ r"""Edits the given text in the defined editor. If an editor is given
649
+ (should be the full path to the executable but the regular operating
650
+ system search path is used for finding the executable) it overrides
651
+ the detected editor. Optionally, some environment variables can be
652
+ used. If the editor is closed without changes, `None` is returned. In
653
+ case a file is edited directly the return value is always `None` and
654
+ `require_save` and `extension` are ignored.
655
+
656
+ If the editor cannot be opened a :exc:`UsageError` is raised.
657
+
658
+ Note for Windows: to simplify cross-platform usage, the newlines are
659
+ automatically converted from POSIX to Windows and vice versa. As such,
660
+ the message here will have ``\n`` as newline markers.
661
+
662
+ :param text: the text to edit.
663
+ :param editor: optionally the editor to use. Defaults to automatic
664
+ detection.
665
+ :param env: environment variables to forward to the editor.
666
+ :param require_save: if this is true, then not saving in the editor
667
+ will make the return value become `None`.
668
+ :param extension: the extension to tell the editor about. This defaults
669
+ to `.txt` but changing this might change syntax
670
+ highlighting.
671
+ :param filename: if provided it will edit this file instead of the
672
+ provided text contents. It will not use a temporary
673
+ file as an indirection in that case.
674
+ """
675
+ from ._termui_impl import Editor
676
+
677
+ ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension)
678
+
679
+ if filename is None:
680
+ return ed.edit(text)
681
+
682
+ ed.edit_file(filename)
683
+ return None
684
+
685
+
686
+ def launch(url: str, wait: bool = False, locate: bool = False) -> int:
687
+ """This function launches the given URL (or filename) in the default
688
+ viewer application for this file type. If this is an executable, it
689
+ might launch the executable in a new session. The return value is
690
+ the exit code of the launched application. Usually, ``0`` indicates
691
+ success.
692
+
693
+ Examples::
694
+
695
+ click.launch('https://click.palletsprojects.com/')
696
+ click.launch('/my/downloaded/file', locate=True)
697
+
698
+ .. versionadded:: 2.0
699
+
700
+ :param url: URL or filename of the thing to launch.
701
+ :param wait: Wait for the program to exit before returning. This
702
+ only works if the launched program blocks. In particular,
703
+ ``xdg-open`` on Linux does not block.
704
+ :param locate: if this is set to `True` then instead of launching the
705
+ application associated with the URL it will attempt to
706
+ launch a file manager with the file located. This
707
+ might have weird effects if the URL does not point to
708
+ the filesystem.
709
+ """
710
+ from ._termui_impl import open_url
711
+
712
+ return open_url(url, wait=wait, locate=locate)
713
+
714
+
715
+ # If this is provided, getchar() calls into this instead. This is used
716
+ # for unittesting purposes.
717
+ _getchar: t.Optional[t.Callable[[bool], str]] = None
718
+
719
+
720
+ def getchar(echo: bool = False) -> str:
721
+ """Fetches a single character from the terminal and returns it. This
722
+ will always return a unicode character and under certain rare
723
+ circumstances this might return more than one character. The
724
+ situations which more than one character is returned is when for
725
+ whatever reason multiple characters end up in the terminal buffer or
726
+ standard input was not actually a terminal.
727
+
728
+ Note that this will always read from the terminal, even if something
729
+ is piped into the standard input.
730
+
731
+ Note for Windows: in rare cases when typing non-ASCII characters, this
732
+ function might wait for a second character and then return both at once.
733
+ This is because certain Unicode characters look like special-key markers.
734
+
735
+ .. versionadded:: 2.0
736
+
737
+ :param echo: if set to `True`, the character read will also show up on
738
+ the terminal. The default is to not show it.
739
+ """
740
+ global _getchar
741
+
742
+ if _getchar is None:
743
+ from ._termui_impl import getchar as f
744
+
745
+ _getchar = f
746
+
747
+ return _getchar(echo)
748
+
749
+
750
+ def raw_terminal() -> t.ContextManager[int]:
751
+ from ._termui_impl import raw_terminal as f
752
+
753
+ return f()
754
+
755
+
756
+ def pause(info: t.Optional[str] = None, err: bool = False) -> None:
757
+ """This command stops execution and waits for the user to press any
758
+ key to continue. This is similar to the Windows batch "pause"
759
+ command. If the program is not run through a terminal, this command
760
+ will instead do nothing.
761
+
762
+ .. versionadded:: 2.0
763
+
764
+ .. versionadded:: 4.0
765
+ Added the `err` parameter.
766
+
767
+ :param info: The message to print before pausing. Defaults to
768
+ ``"Press any key to continue..."``.
769
+ :param err: if set to message goes to ``stderr`` instead of
770
+ ``stdout``, the same as with echo.
771
+ """
772
+ if not isatty(sys.stdin) or not isatty(sys.stdout):
773
+ return
774
+
775
+ if info is None:
776
+ info = _("Press any key to continue...")
777
+
778
+ try:
779
+ if info:
780
+ echo(info, nl=False, err=err)
781
+ try:
782
+ getchar()
783
+ except (KeyboardInterrupt, EOFError):
784
+ pass
785
+ finally:
786
+ if info:
787
+ echo(err=err)