Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/click/termui.py: 25%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import annotations
3import collections.abc as cabc
4import inspect
5import io
6import itertools
7import re
8import sys
9import typing as t
10from contextlib import AbstractContextManager
11from contextlib import redirect_stdout
12from gettext import gettext as _
14from ._compat import isatty
15from ._compat import strip_ansi
16from .exceptions import Abort
17from .exceptions import UsageError
18from .globals import resolve_color_default
19from .types import Choice
20from .types import convert_type
21from .types import ParamType
22from .utils import echo
23from .utils import LazyFile
25if t.TYPE_CHECKING:
26 from ._termui_impl import ProgressBar
28V = t.TypeVar("V")
30# The prompt functions to use. The doc tools currently override these
31# functions to customize how they work.
32visible_prompt_func: t.Callable[[str], str] = input
34_ansi_colors = {
35 "black": 30,
36 "red": 31,
37 "green": 32,
38 "yellow": 33,
39 "blue": 34,
40 "magenta": 35,
41 "cyan": 36,
42 "white": 37,
43 "reset": 39,
44 "bright_black": 90,
45 "bright_red": 91,
46 "bright_green": 92,
47 "bright_yellow": 93,
48 "bright_blue": 94,
49 "bright_magenta": 95,
50 "bright_cyan": 96,
51 "bright_white": 97,
52}
53_ansi_reset_all = "\033[0m"
56_HIDDEN_INPUT_MASK = "'***'"
59def _mask_hidden_input(message: str, value: str) -> str:
60 """Replace occurrences of ``value`` in ``message`` with a fixed mask.
62 Both ``repr(value)`` (the form built-in :class:`ParamType` errors use
63 via ``{value!r}``) and the raw value are masked. The raw-value pass
64 uses word-boundary lookarounds so a substring like ``"1"`` does not
65 match inside ``"10"``, and ``"ent"`` does not match inside
66 ``"Authentication"``. The empty string is skipped to avoid matching
67 at every boundary.
68 """
69 message = message.replace(repr(value), _HIDDEN_INPUT_MASK)
70 if value:
71 message = re.sub(
72 rf"(?<!\w){re.escape(value)}(?!\w)", _HIDDEN_INPUT_MASK, message
73 )
74 return message
77def hidden_prompt_func(prompt: str) -> str:
78 import getpass
80 return getpass.getpass(prompt)
83def _readline_prompt(func: t.Callable[[str], str], text: str, err: bool) -> str:
84 """Call a prompt function, passing the full prompt on non-Windows so
85 readline can handle line editing and cursor positioning correctly.
86 """
87 if err:
88 with redirect_stdout(sys.stderr):
89 return func(text)
90 return func(text)
93def _build_prompt(
94 text: str,
95 suffix: str,
96 show_default: bool | str = False,
97 default: t.Any | None = None,
98 show_choices: bool = True,
99 type: ParamType[t.Any] | None = None,
100) -> str:
101 prompt = text
102 if type is not None and show_choices and isinstance(type, Choice):
103 prompt += f" ({', '.join(map(str, type.choices))})"
104 if isinstance(show_default, str):
105 default = f"({show_default})"
106 if default is not None and show_default:
107 prompt = f"{prompt} [{_format_default(default)}]"
108 return f"{prompt}{suffix}"
111def _format_default(default: t.Any) -> t.Any:
112 if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"):
113 return default.name
115 return default
118def prompt(
119 text: str,
120 default: t.Any | None = None,
121 hide_input: bool = False,
122 confirmation_prompt: bool | str = False,
123 type: ParamType[t.Any] | t.Any | None = None,
124 value_proc: t.Callable[[str], t.Any] | None = None,
125 prompt_suffix: str = ": ",
126 show_default: bool | str = True,
127 err: bool = False,
128 show_choices: bool = True,
129) -> t.Any:
130 """Prompts a user for input. This is a convenience function that can
131 be used to prompt a user for input later.
133 If the user aborts the input by sending an interrupt signal, this
134 function will catch it and raise a :exc:`Abort` exception.
136 :param text: the text to show for the prompt.
137 :param default: the default value to use if no input happens. If this
138 is not given it will prompt until it's aborted.
139 :param hide_input: if this is set to true then the input value will
140 be hidden.
141 :param confirmation_prompt: Prompt a second time to confirm the
142 value. Can be set to a string instead of ``True`` to customize
143 the message.
144 :param type: the type to use to check the value against.
145 :param value_proc: if this parameter is provided it's a function that
146 is invoked instead of the type conversion to
147 convert a value.
148 :param prompt_suffix: a suffix that should be added to the prompt.
149 :param show_default: shows or hides the default value in the prompt.
150 If this value is a string, it shows that string
151 in parentheses instead of the actual value.
152 :param err: if set to true the file defaults to ``stderr`` instead of
153 ``stdout``, the same as with echo.
154 :param show_choices: Show or hide choices if the passed type is a Choice.
155 For example if type is a Choice of either day or week,
156 show_choices is true and text is "Group by" then the
157 prompt will be "Group by (day, week): ".
159 .. versionchanged:: 8.3.3
160 ``show_default`` can be a string to show a custom value instead
161 of the actual default, matching the help text behavior.
163 .. versionchanged:: 8.3.1
164 A space is no longer appended to the prompt.
166 .. versionadded:: 8.0
167 ``confirmation_prompt`` can be a custom string.
169 .. versionadded:: 7.0
170 Added the ``show_choices`` parameter.
172 .. versionadded:: 6.0
173 Added unicode support for cmd.exe on Windows.
175 .. versionadded:: 4.0
176 Added the `err` parameter.
178 """
180 def prompt_func(text: str) -> str:
181 f = hidden_prompt_func if hide_input else visible_prompt_func
182 try:
183 return _readline_prompt(f, text, err)
184 except (KeyboardInterrupt, EOFError):
185 # getpass doesn't print a newline if the user aborts input with ^C.
186 # Allegedly this behavior is inherited from getpass(3).
187 # A doc bug has been filed at https://bugs.python.org/issue24711
188 if hide_input:
189 echo(None, err=err)
190 raise Abort() from None
192 if value_proc is None:
193 value_proc = convert_type(type, default)
195 prompt = _build_prompt(
196 text, prompt_suffix, show_default, default, show_choices, type
197 )
199 if confirmation_prompt:
200 if confirmation_prompt is True:
201 confirmation_prompt = _("Repeat for confirmation")
203 confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix)
205 while True:
206 while True:
207 value = prompt_func(prompt)
208 if value:
209 break
210 elif default is not None:
211 value = default
212 break
213 try:
214 result = value_proc(value)
215 except UsageError as e:
216 message = _mask_hidden_input(e.message, value) if hide_input else e.message
217 echo(_("Error: {message}").format(message=message), err=err)
218 continue
219 if not confirmation_prompt:
220 return result
221 while True:
222 value2 = prompt_func(confirmation_prompt)
223 is_empty = not value and not value2
224 if value2 or is_empty:
225 break
226 if value == value2:
227 return result
228 echo(_("Error: The two entered values do not match."), err=err)
231def confirm(
232 text: str,
233 default: bool | None = False,
234 abort: bool = False,
235 prompt_suffix: str = ": ",
236 show_default: bool = True,
237 err: bool = False,
238) -> bool:
239 """Prompts for confirmation (yes/no question).
241 If the user aborts the input by sending a interrupt signal this
242 function will catch it and raise a :exc:`Abort` exception.
244 :param text: the question to ask.
245 :param default: The default value to use when no input is given. If
246 ``None``, repeat until input is given.
247 :param abort: if this is set to `True` a negative answer aborts the
248 exception by raising :exc:`Abort`.
249 :param prompt_suffix: a suffix that should be added to the prompt.
250 :param show_default: shows or hides the default value in the prompt.
251 :param err: if set to true the file defaults to ``stderr`` instead of
252 ``stdout``, the same as with echo.
254 .. versionchanged:: 8.3.1
255 A space is no longer appended to the prompt.
257 .. versionchanged:: 8.0
258 Repeat until input is given if ``default`` is ``None``.
260 .. versionadded:: 4.0
261 Added the ``err`` parameter.
262 """
263 prompt = _build_prompt(
264 text,
265 prompt_suffix,
266 show_default,
267 "y/n" if default is None else ("Y/n" if default else "y/N"),
268 )
270 while True:
271 try:
272 value = _readline_prompt(visible_prompt_func, prompt, err).lower().strip()
273 except (KeyboardInterrupt, EOFError):
274 raise Abort() from None
275 if value in ("y", "yes"):
276 rv = True
277 elif value in ("n", "no"):
278 rv = False
279 elif default is not None and value == "":
280 rv = default
281 else:
282 echo(_("Error: invalid input"), err=err)
283 continue
284 break
285 if abort and not rv:
286 raise Abort()
287 return rv
290def get_pager_file(
291 color: bool | None = None,
292) -> t.ContextManager[t.TextIO]:
293 """Context manager.
295 Yields a writable file-like object which can be used as an output pager.
297 .. versionadded:: 8.4.0
299 :param color: controls if the pager supports ANSI colors or not. The
300 default is autodetection.
301 """
302 from ._termui_impl import get_pager_file
304 color = resolve_color_default(color)
306 return get_pager_file(color=color)
309def echo_via_pager(
310 text_or_generator: cabc.Iterable[str] | t.Callable[[], cabc.Iterable[str]] | str,
311 color: bool | None = None,
312) -> None:
313 """This function takes a text and shows it via an environment specific
314 pager on stdout.
316 .. versionchanged:: 3.0
317 Added the `color` flag.
319 :param text_or_generator: the text to page, or alternatively, a
320 generator emitting the text to page.
321 :param color: controls if the pager supports ANSI colors or not. The
322 default is autodetection.
323 """
325 if inspect.isgeneratorfunction(text_or_generator):
326 i = t.cast("t.Callable[[], cabc.Iterable[str]]", text_or_generator)()
327 elif isinstance(text_or_generator, str):
328 i = [text_or_generator]
329 else:
330 i = iter(t.cast("cabc.Iterable[str]", text_or_generator))
332 # convert every element of i to a text type if necessary
333 text_generator = (el if isinstance(el, str) else str(el) for el in i)
335 with get_pager_file(color=color) as pager:
336 for text in itertools.chain(text_generator, "\n"):
337 pager.write(text)
338 # Flush after each write so a slow generator streams to the pager
339 # incrementally rather than staying invisible until the pipe buffer
340 # fills (~8 KB).
341 pager.flush()
344@t.overload
345def progressbar(
346 *,
347 length: int,
348 label: str | None = None,
349 hidden: bool = False,
350 show_eta: bool = True,
351 show_percent: bool | None = None,
352 show_pos: bool = False,
353 fill_char: str = "#",
354 empty_char: str = "-",
355 bar_template: str = "%(label)s [%(bar)s] %(info)s",
356 info_sep: str = " ",
357 width: int = 36,
358 file: t.TextIO | None = None,
359 color: bool | None = None,
360 update_min_steps: int = 1,
361) -> ProgressBar[int]: ...
364@t.overload
365def progressbar(
366 iterable: cabc.Iterable[V] | None = None,
367 length: int | None = None,
368 label: str | None = None,
369 hidden: bool = False,
370 show_eta: bool = True,
371 show_percent: bool | None = None,
372 show_pos: bool = False,
373 item_show_func: t.Callable[[V | None], str | None] | None = None,
374 fill_char: str = "#",
375 empty_char: str = "-",
376 bar_template: str = "%(label)s [%(bar)s] %(info)s",
377 info_sep: str = " ",
378 width: int = 36,
379 file: t.TextIO | None = None,
380 color: bool | None = None,
381 update_min_steps: int = 1,
382) -> ProgressBar[V]: ...
385def progressbar(
386 iterable: cabc.Iterable[V] | None = None,
387 length: int | None = None,
388 label: str | None = None,
389 hidden: bool = False,
390 show_eta: bool = True,
391 show_percent: bool | None = None,
392 show_pos: bool = False,
393 item_show_func: t.Callable[[V | None], str | None] | None = None,
394 fill_char: str = "#",
395 empty_char: str = "-",
396 bar_template: str = "%(label)s [%(bar)s] %(info)s",
397 info_sep: str = " ",
398 width: int = 36,
399 file: t.TextIO | None = None,
400 color: bool | None = None,
401 update_min_steps: int = 1,
402) -> ProgressBar[V]:
403 """This function creates an iterable context manager that can be used
404 to iterate over something while showing a progress bar. It will
405 either iterate over the `iterable` or `length` items (that are counted
406 up). While iteration happens, this function will print a rendered
407 progress bar to the given `file` (defaults to stdout) and will attempt
408 to calculate remaining time and more. By default, this progress bar
409 will not be rendered if the file is not a terminal.
411 The context manager creates the progress bar. When the context
412 manager is entered the progress bar is already created. With every
413 iteration over the progress bar, the iterable passed to the bar is
414 advanced and the bar is updated. When the context manager exits,
415 a newline is printed and the progress bar is finalized on screen.
417 Note: The progress bar is currently designed for use cases where the
418 total progress can be expected to take at least several seconds.
419 Because of this, the ProgressBar class object won't display
420 progress that is considered too fast, and progress where the time
421 between steps is less than a second.
423 No printing must happen or the progress bar will be unintentionally
424 destroyed.
426 Example usage::
428 with progressbar(items) as bar:
429 for item in bar:
430 do_something_with(item)
432 Alternatively, if no iterable is specified, one can manually update the
433 progress bar through the `update()` method instead of directly
434 iterating over the progress bar. The update method accepts the number
435 of steps to increment the bar with::
437 with progressbar(length=chunks.total_bytes) as bar:
438 for chunk in chunks:
439 process_chunk(chunk)
440 bar.update(chunks.bytes)
442 The ``update()`` method also takes an optional value specifying the
443 ``current_item`` at the new position. This is useful when used
444 together with ``item_show_func`` to customize the output for each
445 manual step::
447 with click.progressbar(
448 length=total_size,
449 label='Unzipping archive',
450 item_show_func=lambda a: a.filename
451 ) as bar:
452 for archive in zip_file:
453 archive.extract()
454 bar.update(archive.size, archive)
456 :param iterable: an iterable to iterate over. If not provided the length
457 is required.
458 :param length: the number of items to iterate over. By default the
459 progressbar will attempt to ask the iterator about its
460 length, which might or might not work. If an iterable is
461 also provided this parameter can be used to override the
462 length. If an iterable is not provided the progress bar
463 will iterate over a range of that length.
464 :param label: the label to show next to the progress bar.
465 :param hidden: hide the progressbar. Defaults to ``False``. When no tty is
466 detected, it will only print the progressbar label. Setting this to
467 ``False`` also disables that.
468 :param show_eta: enables or disables the estimated time display. This is
469 automatically disabled if the length cannot be
470 determined.
471 :param show_percent: enables or disables the percentage display. The
472 default is `True` if the iterable has a length or
473 `False` if not.
474 :param show_pos: enables or disables the absolute position display. The
475 default is `False`.
476 :param item_show_func: A function called with the current item which
477 can return a string to show next to the progress bar. If the
478 function returns ``None`` nothing is shown. The current item can
479 be ``None``, such as when entering and exiting the bar.
480 :param fill_char: the character to use to show the filled part of the
481 progress bar.
482 :param empty_char: the character to use to show the non-filled part of
483 the progress bar.
484 :param bar_template: the format string to use as template for the bar.
485 The parameters in it are ``label`` for the label,
486 ``bar`` for the progress bar and ``info`` for the
487 info section.
488 :param info_sep: the separator between multiple info items (eta etc.)
489 :param width: the width of the progress bar in characters, 0 means full
490 terminal width
491 :param file: The file to write to. If this is not a terminal then
492 only the label is printed.
493 :param color: controls if the terminal supports ANSI colors or not. The
494 default is autodetection. This is only needed if ANSI
495 codes are included anywhere in the progress bar output
496 which is not the case by default.
497 :param update_min_steps: Render only when this many updates have
498 completed. This allows tuning for very fast iterators.
500 .. versionadded:: 8.2
501 The ``hidden`` argument.
503 .. versionchanged:: 8.0
504 Output is shown even if execution time is less than 0.5 seconds.
506 .. versionchanged:: 8.0
507 ``item_show_func`` shows the current item, not the previous one.
509 .. versionchanged:: 8.0
510 Labels are echoed if the output is not a TTY. Reverts a change
511 in 7.0 that removed all output.
513 .. versionadded:: 8.0
514 The ``update_min_steps`` parameter.
516 .. versionadded:: 4.0
517 The ``color`` parameter and ``update`` method.
519 .. versionadded:: 2.0
520 """
521 from ._termui_impl import ProgressBar
523 color = resolve_color_default(color)
524 return ProgressBar(
525 iterable=iterable,
526 length=length,
527 hidden=hidden,
528 show_eta=show_eta,
529 show_percent=show_percent,
530 show_pos=show_pos,
531 item_show_func=item_show_func,
532 fill_char=fill_char,
533 empty_char=empty_char,
534 bar_template=bar_template,
535 info_sep=info_sep,
536 file=file,
537 label=label,
538 width=width,
539 color=color,
540 update_min_steps=update_min_steps,
541 )
544def clear() -> None:
545 """Clears the terminal screen. This will have the effect of clearing
546 the whole visible space of the terminal and moving the cursor to the
547 top left. This does not do anything if not connected to a terminal.
549 .. versionadded:: 2.0
550 """
551 if not isatty(sys.stdout):
552 return
554 # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor
555 echo("\033[2J\033[1;1H", nl=False)
558def _interpret_color(color: int | tuple[int, int, int] | str, offset: int = 0) -> str:
559 if isinstance(color, int):
560 return f"{38 + offset};5;{color:d}"
562 if isinstance(color, (tuple, list)):
563 r, g, b = color
564 return f"{38 + offset};2;{r:d};{g:d};{b:d}"
566 return str(_ansi_colors[color] + offset)
569def style(
570 text: t.Any,
571 fg: int | tuple[int, int, int] | str | None = None,
572 bg: int | tuple[int, int, int] | str | None = None,
573 bold: bool | None = None,
574 dim: bool | None = None,
575 underline: bool | None = None,
576 overline: bool | None = None,
577 italic: bool | None = None,
578 blink: bool | None = None,
579 reverse: bool | None = None,
580 strikethrough: bool | None = None,
581 reset: bool = True,
582) -> str:
583 """Styles a text with ANSI styles and returns the new string. By
584 default the styling is self contained which means that at the end
585 of the string a reset code is issued. This can be prevented by
586 passing ``reset=False``.
588 Examples::
590 click.echo(click.style('Hello World!', fg='green'))
591 click.echo(click.style('ATTENTION!', blink=True))
592 click.echo(click.style('Some things', reverse=True, fg='cyan'))
593 click.echo(click.style('More colors', fg=(255, 12, 128), bg=117))
595 Supported color names:
597 * ``black`` (might be a gray)
598 * ``red``
599 * ``green``
600 * ``yellow`` (might be an orange)
601 * ``blue``
602 * ``magenta``
603 * ``cyan``
604 * ``white`` (might be light gray)
605 * ``bright_black``
606 * ``bright_red``
607 * ``bright_green``
608 * ``bright_yellow``
609 * ``bright_blue``
610 * ``bright_magenta``
611 * ``bright_cyan``
612 * ``bright_white``
613 * ``reset`` (reset the color code only)
615 If the terminal supports it, color may also be specified as:
617 - An integer in the interval [0, 255]. The terminal must support
618 8-bit/256-color mode.
619 - An RGB tuple of three integers in [0, 255]. The terminal must
620 support 24-bit/true-color mode.
622 See https://en.wikipedia.org/wiki/ANSI_color and
623 https://gist.github.com/XVilka/8346728 for more information.
625 :param text: the string to style with ansi codes.
626 :param fg: if provided this will become the foreground color.
627 :param bg: if provided this will become the background color.
628 :param bold: if provided this will enable or disable bold mode.
629 :param dim: if provided this will enable or disable dim mode. This is
630 badly supported.
631 :param underline: if provided this will enable or disable underline.
632 :param overline: if provided this will enable or disable overline.
633 :param italic: if provided this will enable or disable italic.
634 :param blink: if provided this will enable or disable blinking.
635 :param reverse: if provided this will enable or disable inverse
636 rendering (foreground becomes background and the
637 other way round).
638 :param strikethrough: if provided this will enable or disable
639 striking through text.
640 :param reset: by default a reset-all code is added at the end of the
641 string which means that styles do not carry over. This
642 can be disabled to compose styles.
644 .. versionchanged:: 8.0
645 A non-string ``message`` is converted to a string.
647 .. versionchanged:: 8.0
648 Added support for 256 and RGB color codes.
650 .. versionchanged:: 8.0
651 Added the ``strikethrough``, ``italic``, and ``overline``
652 parameters.
654 .. versionchanged:: 7.0
655 Added support for bright colors.
657 .. versionadded:: 2.0
658 """
659 if not isinstance(text, str):
660 text = str(text)
662 bits = []
664 if fg:
665 try:
666 bits.append(f"\033[{_interpret_color(fg)}m")
667 except KeyError:
668 raise TypeError(_("Unknown color {colour!r}").format(colour=fg)) from None
670 if bg:
671 try:
672 bits.append(f"\033[{_interpret_color(bg, 10)}m")
673 except KeyError:
674 raise TypeError(_("Unknown color {colour!r}").format(colour=bg)) from None
676 if bold is not None:
677 bits.append(f"\033[{1 if bold else 22}m")
678 if dim is not None:
679 bits.append(f"\033[{2 if dim else 22}m")
680 if underline is not None:
681 bits.append(f"\033[{4 if underline else 24}m")
682 if overline is not None:
683 bits.append(f"\033[{53 if overline else 55}m")
684 if italic is not None:
685 bits.append(f"\033[{3 if italic else 23}m")
686 if blink is not None:
687 bits.append(f"\033[{5 if blink else 25}m")
688 if reverse is not None:
689 bits.append(f"\033[{7 if reverse else 27}m")
690 if strikethrough is not None:
691 bits.append(f"\033[{9 if strikethrough else 29}m")
692 bits.append(text)
693 if reset:
694 bits.append(_ansi_reset_all)
695 return "".join(bits)
698def unstyle(text: str) -> str:
699 """Removes ANSI styling information from a string. Usually it's not
700 necessary to use this function as Click's echo function will
701 automatically remove styling if necessary.
703 .. versionadded:: 2.0
705 :param text: the text to remove style information from.
706 """
707 return strip_ansi(text)
710def secho(
711 message: t.Any | None = None,
712 file: t.IO[t.AnyStr] | None = None,
713 nl: bool = True,
714 err: bool = False,
715 color: bool | None = None,
716 **styles: t.Any,
717) -> None:
718 """This function combines :func:`echo` and :func:`style` into one
719 call. As such the following two calls are the same::
721 click.secho('Hello World!', fg='green')
722 click.echo(click.style('Hello World!', fg='green'))
724 All keyword arguments are forwarded to the underlying functions
725 depending on which one they go with.
727 Non-string types will be converted to :class:`str`. However,
728 :class:`bytes` are passed directly to :meth:`echo` without applying
729 style. If you want to style bytes that represent text, call
730 :meth:`bytes.decode` first.
732 .. versionchanged:: 8.0
733 A non-string ``message`` is converted to a string. Bytes are
734 passed through without style applied.
736 .. versionadded:: 2.0
737 """
738 if message is not None and not isinstance(message, (bytes, bytearray)):
739 message = style(message, **styles)
741 return echo(message, file=file, nl=nl, err=err, color=color)
744@t.overload
745def edit(
746 text: bytes | bytearray,
747 editor: str | None = None,
748 env: cabc.Mapping[str, str] | None = None,
749 require_save: bool = False,
750 extension: str = ".txt",
751) -> bytes | None: ...
754@t.overload
755def edit(
756 text: str,
757 editor: str | None = None,
758 env: cabc.Mapping[str, str] | None = None,
759 require_save: bool = True,
760 extension: str = ".txt",
761) -> str | None: ...
764@t.overload
765def edit(
766 text: None = None,
767 editor: str | None = None,
768 env: cabc.Mapping[str, str] | None = None,
769 require_save: bool = True,
770 extension: str = ".txt",
771 filename: str | cabc.Iterable[str] | None = None,
772) -> None: ...
775def edit(
776 text: str | bytes | bytearray | None = None,
777 editor: str | None = None,
778 env: cabc.Mapping[str, str] | None = None,
779 require_save: bool = True,
780 extension: str = ".txt",
781 filename: str | cabc.Iterable[str] | None = None,
782) -> str | bytes | bytearray | None:
783 r"""Edits the given text in the defined editor. If an editor is given
784 (should be the full path to the executable but the regular operating
785 system search path is used for finding the executable) it overrides
786 the detected editor. Optionally, some environment variables can be
787 used. If the editor is closed without changes, `None` is returned. In
788 case a file is edited directly the return value is always `None` and
789 `require_save` and `extension` are ignored.
791 If the editor cannot be opened a :exc:`UsageError` is raised.
793 Note for Windows: to simplify cross-platform usage, the newlines are
794 automatically converted from POSIX to Windows and vice versa. As such,
795 the message here will have ``\n`` as newline markers.
797 :param text: the text to edit.
798 :param editor: optionally the editor to use. Defaults to automatic
799 detection.
800 :param env: environment variables to forward to the editor.
801 :param require_save: if this is true, then not saving in the editor
802 will make the return value become `None`.
803 :param extension: the extension to tell the editor about. This defaults
804 to `.txt` but changing this might change syntax
805 highlighting.
806 :param filename: if provided it will edit this file instead of the
807 provided text contents. It will not use a temporary
808 file as an indirection in that case. If the editor supports
809 editing multiple files at once, a sequence of files may be
810 passed as well. Invoke `click.file` once per file instead
811 if multiple files cannot be managed at once or editing the
812 files serially is desired.
814 .. versionchanged:: 8.2.0
815 ``filename`` now accepts any ``Iterable[str]`` in addition to a ``str``
816 if the ``editor`` supports editing multiple files at once.
818 """
819 from ._termui_impl import Editor
821 ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension)
823 if filename is None:
824 return ed.edit(text)
826 if isinstance(filename, str):
827 filename = (filename,)
829 ed.edit_files(filenames=filename)
830 return None
833def launch(url: str, wait: bool = False, locate: bool = False) -> int:
834 """This function launches the given URL (or filename) in the default
835 viewer application for this file type. If this is an executable, it
836 might launch the executable in a new session. The return value is
837 the exit code of the launched application. Usually, ``0`` indicates
838 success.
840 Examples::
842 click.launch('https://click.palletsprojects.com/')
843 click.launch('/my/downloaded/file', locate=True)
845 .. versionadded:: 2.0
847 :param url: URL or filename of the thing to launch.
848 :param wait: Wait for the program to exit before returning. This
849 only works if the launched program blocks. In particular,
850 ``xdg-open`` on Linux does not block.
851 :param locate: if this is set to `True` then instead of launching the
852 application associated with the URL it will attempt to
853 launch a file manager with the file located. This
854 might have weird effects if the URL does not point to
855 the filesystem.
856 """
857 from ._termui_impl import open_url
859 return open_url(url, wait=wait, locate=locate)
862# If this is provided, getchar() calls into this instead. This is used
863# for unittesting purposes.
864_getchar: t.Callable[[bool], str] | None = None
867def getchar(echo: bool = False) -> str:
868 """Fetches a single character from the terminal and returns it. This
869 will always return a unicode character and under certain rare
870 circumstances this might return more than one character. The
871 situations which more than one character is returned is when for
872 whatever reason multiple characters end up in the terminal buffer or
873 standard input was not actually a terminal.
875 Note that this will always read from the terminal, even if something
876 is piped into the standard input.
878 Note for Windows: in rare cases when typing non-ASCII characters, this
879 function might wait for a second character and then return both at once.
880 This is because certain Unicode characters look like special-key markers.
882 .. versionadded:: 2.0
884 :param echo: if set to `True`, the character read will also show up on
885 the terminal. The default is to not show it.
886 """
887 global _getchar
889 if _getchar is None:
890 from ._termui_impl import getchar as f
892 _getchar = f
894 return _getchar(echo)
897def raw_terminal() -> AbstractContextManager[int]:
898 from ._termui_impl import raw_terminal as f
900 return f()
903def pause(info: str | None = None, err: bool = False) -> None:
904 """This command stops execution and waits for the user to press any
905 key to continue. This is similar to the Windows batch "pause"
906 command. If the program is not run through a terminal, this command
907 will instead do nothing.
909 .. versionadded:: 2.0
911 .. versionadded:: 4.0
912 Added the `err` parameter.
914 :param info: The message to print before pausing. Defaults to
915 ``"Press any key to continue..."``.
916 :param err: if set to message goes to ``stderr`` instead of
917 ``stdout``, the same as with echo.
918 """
919 if not isatty(sys.stdin) or not isatty(sys.stdout):
920 return
922 if info is None:
923 info = _("Press any key to continue...")
925 try:
926 if info:
927 echo(info, nl=False, err=err)
928 try:
929 getchar()
930 except (KeyboardInterrupt, EOFError):
931 pass
932 finally:
933 if info:
934 echo(err=err)