summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/click/termui.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/click/termui.py')
-rw-r--r--venv/lib/python3.11/site-packages/click/termui.py784
1 files changed, 0 insertions, 784 deletions
diff --git a/venv/lib/python3.11/site-packages/click/termui.py b/venv/lib/python3.11/site-packages/click/termui.py
deleted file mode 100644
index db7a4b2..0000000
--- a/venv/lib/python3.11/site-packages/click/termui.py
+++ /dev/null
@@ -1,784 +0,0 @@
-import inspect
-import io
-import itertools
-import sys
-import typing as t
-from gettext import gettext as _
-
-from ._compat import isatty
-from ._compat import strip_ansi
-from .exceptions import Abort
-from .exceptions import UsageError
-from .globals import resolve_color_default
-from .types import Choice
-from .types import convert_type
-from .types import ParamType
-from .utils import echo
-from .utils import LazyFile
-
-if t.TYPE_CHECKING:
- from ._termui_impl import ProgressBar
-
-V = t.TypeVar("V")
-
-# The prompt functions to use. The doc tools currently override these
-# functions to customize how they work.
-visible_prompt_func: t.Callable[[str], str] = input
-
-_ansi_colors = {
- "black": 30,
- "red": 31,
- "green": 32,
- "yellow": 33,
- "blue": 34,
- "magenta": 35,
- "cyan": 36,
- "white": 37,
- "reset": 39,
- "bright_black": 90,
- "bright_red": 91,
- "bright_green": 92,
- "bright_yellow": 93,
- "bright_blue": 94,
- "bright_magenta": 95,
- "bright_cyan": 96,
- "bright_white": 97,
-}
-_ansi_reset_all = "\033[0m"
-
-
-def hidden_prompt_func(prompt: str) -> str:
- import getpass
-
- return getpass.getpass(prompt)
-
-
-def _build_prompt(
- text: str,
- suffix: str,
- show_default: bool = False,
- default: t.Optional[t.Any] = None,
- show_choices: bool = True,
- type: t.Optional[ParamType] = None,
-) -> str:
- prompt = text
- if type is not None and show_choices and isinstance(type, Choice):
- prompt += f" ({', '.join(map(str, type.choices))})"
- if default is not None and show_default:
- prompt = f"{prompt} [{_format_default(default)}]"
- return f"{prompt}{suffix}"
-
-
-def _format_default(default: t.Any) -> t.Any:
- if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"):
- return default.name
-
- return default
-
-
-def prompt(
- text: str,
- default: t.Optional[t.Any] = None,
- hide_input: bool = False,
- confirmation_prompt: t.Union[bool, str] = False,
- type: t.Optional[t.Union[ParamType, t.Any]] = None,
- value_proc: t.Optional[t.Callable[[str], t.Any]] = None,
- prompt_suffix: str = ": ",
- show_default: bool = True,
- err: bool = False,
- show_choices: bool = True,
-) -> t.Any:
- """Prompts a user for input. This is a convenience function that can
- be used to prompt a user for input later.
-
- If the user aborts the input by sending an interrupt signal, this
- function will catch it and raise a :exc:`Abort` exception.
-
- :param text: the text to show for the prompt.
- :param default: the default value to use if no input happens. If this
- is not given it will prompt until it's aborted.
- :param hide_input: if this is set to true then the input value will
- be hidden.
- :param confirmation_prompt: Prompt a second time to confirm the
- value. Can be set to a string instead of ``True`` to customize
- the message.
- :param type: the type to use to check the value against.
- :param value_proc: if this parameter is provided it's a function that
- is invoked instead of the type conversion to
- convert a value.
- :param prompt_suffix: a suffix that should be added to the prompt.
- :param show_default: shows or hides the default value in the prompt.
- :param err: if set to true the file defaults to ``stderr`` instead of
- ``stdout``, the same as with echo.
- :param show_choices: Show or hide choices if the passed type is a Choice.
- For example if type is a Choice of either day or week,
- show_choices is true and text is "Group by" then the
- prompt will be "Group by (day, week): ".
-
- .. versionadded:: 8.0
- ``confirmation_prompt`` can be a custom string.
-
- .. versionadded:: 7.0
- Added the ``show_choices`` parameter.
-
- .. versionadded:: 6.0
- Added unicode support for cmd.exe on Windows.
-
- .. versionadded:: 4.0
- Added the `err` parameter.
-
- """
-
- def prompt_func(text: str) -> str:
- f = hidden_prompt_func if hide_input else visible_prompt_func
- try:
- # Write the prompt separately so that we get nice
- # coloring through colorama on Windows
- echo(text.rstrip(" "), nl=False, err=err)
- # Echo a space to stdout to work around an issue where
- # readline causes backspace to clear the whole line.
- return f(" ")
- except (KeyboardInterrupt, EOFError):
- # getpass doesn't print a newline if the user aborts input with ^C.
- # Allegedly this behavior is inherited from getpass(3).
- # A doc bug has been filed at https://bugs.python.org/issue24711
- if hide_input:
- echo(None, err=err)
- raise Abort() from None
-
- if value_proc is None:
- value_proc = convert_type(type, default)
-
- prompt = _build_prompt(
- text, prompt_suffix, show_default, default, show_choices, type
- )
-
- if confirmation_prompt:
- if confirmation_prompt is True:
- confirmation_prompt = _("Repeat for confirmation")
-
- confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix)
-
- while True:
- while True:
- value = prompt_func(prompt)
- if value:
- break
- elif default is not None:
- value = default
- break
- try:
- result = value_proc(value)
- except UsageError as e:
- if hide_input:
- echo(_("Error: The value you entered was invalid."), err=err)
- else:
- echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306
- continue
- if not confirmation_prompt:
- return result
- while True:
- value2 = prompt_func(confirmation_prompt)
- is_empty = not value and not value2
- if value2 or is_empty:
- break
- if value == value2:
- return result
- echo(_("Error: The two entered values do not match."), err=err)
-
-
-def confirm(
- text: str,
- default: t.Optional[bool] = False,
- abort: bool = False,
- prompt_suffix: str = ": ",
- show_default: bool = True,
- err: bool = False,
-) -> bool:
- """Prompts for confirmation (yes/no question).
-
- If the user aborts the input by sending a interrupt signal this
- function will catch it and raise a :exc:`Abort` exception.
-
- :param text: the question to ask.
- :param default: The default value to use when no input is given. If
- ``None``, repeat until input is given.
- :param abort: if this is set to `True` a negative answer aborts the
- exception by raising :exc:`Abort`.
- :param prompt_suffix: a suffix that should be added to the prompt.
- :param show_default: shows or hides the default value in the prompt.
- :param err: if set to true the file defaults to ``stderr`` instead of
- ``stdout``, the same as with echo.
-
- .. versionchanged:: 8.0
- Repeat until input is given if ``default`` is ``None``.
-
- .. versionadded:: 4.0
- Added the ``err`` parameter.
- """
- prompt = _build_prompt(
- text,
- prompt_suffix,
- show_default,
- "y/n" if default is None else ("Y/n" if default else "y/N"),
- )
-
- while True:
- try:
- # Write the prompt separately so that we get nice
- # coloring through colorama on Windows
- echo(prompt.rstrip(" "), nl=False, err=err)
- # Echo a space to stdout to work around an issue where
- # readline causes backspace to clear the whole line.
- value = visible_prompt_func(" ").lower().strip()
- except (KeyboardInterrupt, EOFError):
- raise Abort() from None
- if value in ("y", "yes"):
- rv = True
- elif value in ("n", "no"):
- rv = False
- elif default is not None and value == "":
- rv = default
- else:
- echo(_("Error: invalid input"), err=err)
- continue
- break
- if abort and not rv:
- raise Abort()
- return rv
-
-
-def echo_via_pager(
- text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str],
- color: t.Optional[bool] = None,
-) -> None:
- """This function takes a text and shows it via an environment specific
- pager on stdout.
-
- .. versionchanged:: 3.0
- Added the `color` flag.
-
- :param text_or_generator: the text to page, or alternatively, a
- generator emitting the text to page.
- :param color: controls if the pager supports ANSI colors or not. The
- default is autodetection.
- """
- color = resolve_color_default(color)
-
- if inspect.isgeneratorfunction(text_or_generator):
- i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)()
- elif isinstance(text_or_generator, str):
- i = [text_or_generator]
- else:
- i = iter(t.cast(t.Iterable[str], text_or_generator))
-
- # convert every element of i to a text type if necessary
- text_generator = (el if isinstance(el, str) else str(el) for el in i)
-
- from ._termui_impl import pager
-
- return pager(itertools.chain(text_generator, "\n"), color)
-
-
-def progressbar(
- iterable: t.Optional[t.Iterable[V]] = None,
- length: t.Optional[int] = None,
- label: t.Optional[str] = None,
- show_eta: bool = True,
- show_percent: t.Optional[bool] = None,
- show_pos: bool = False,
- item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None,
- fill_char: str = "#",
- empty_char: str = "-",
- bar_template: str = "%(label)s [%(bar)s] %(info)s",
- info_sep: str = " ",
- width: int = 36,
- file: t.Optional[t.TextIO] = None,
- color: t.Optional[bool] = None,
- update_min_steps: int = 1,
-) -> "ProgressBar[V]":
- """This function creates an iterable context manager that can be used
- to iterate over something while showing a progress bar. It will
- either iterate over the `iterable` or `length` items (that are counted
- up). While iteration happens, this function will print a rendered
- progress bar to the given `file` (defaults to stdout) and will attempt
- to calculate remaining time and more. By default, this progress bar
- will not be rendered if the file is not a terminal.
-
- The context manager creates the progress bar. When the context
- manager is entered the progress bar is already created. With every
- iteration over the progress bar, the iterable passed to the bar is
- advanced and the bar is updated. When the context manager exits,
- a newline is printed and the progress bar is finalized on screen.
-
- Note: The progress bar is currently designed for use cases where the
- total progress can be expected to take at least several seconds.
- Because of this, the ProgressBar class object won't display
- progress that is considered too fast, and progress where the time
- between steps is less than a second.
-
- No printing must happen or the progress bar will be unintentionally
- destroyed.
-
- Example usage::
-
- with progressbar(items) as bar:
- for item in bar:
- do_something_with(item)
-
- Alternatively, if no iterable is specified, one can manually update the
- progress bar through the `update()` method instead of directly
- iterating over the progress bar. The update method accepts the number
- of steps to increment the bar with::
-
- with progressbar(length=chunks.total_bytes) as bar:
- for chunk in chunks:
- process_chunk(chunk)
- bar.update(chunks.bytes)
-
- The ``update()`` method also takes an optional value specifying the
- ``current_item`` at the new position. This is useful when used
- together with ``item_show_func`` to customize the output for each
- manual step::
-
- with click.progressbar(
- length=total_size,
- label='Unzipping archive',
- item_show_func=lambda a: a.filename
- ) as bar:
- for archive in zip_file:
- archive.extract()
- bar.update(archive.size, archive)
-
- :param iterable: an iterable to iterate over. If not provided the length
- is required.
- :param length: the number of items to iterate over. By default the
- progressbar will attempt to ask the iterator about its
- length, which might or might not work. If an iterable is
- also provided this parameter can be used to override the
- length. If an iterable is not provided the progress bar
- will iterate over a range of that length.
- :param label: the label to show next to the progress bar.
- :param show_eta: enables or disables the estimated time display. This is
- automatically disabled if the length cannot be
- determined.
- :param show_percent: enables or disables the percentage display. The
- default is `True` if the iterable has a length or
- `False` if not.
- :param show_pos: enables or disables the absolute position display. The
- default is `False`.
- :param item_show_func: A function called with the current item which
- can return a string to show next to the progress bar. If the
- function returns ``None`` nothing is shown. The current item can
- be ``None``, such as when entering and exiting the bar.
- :param fill_char: the character to use to show the filled part of the
- progress bar.
- :param empty_char: the character to use to show the non-filled part of
- the progress bar.
- :param bar_template: the format string to use as template for the bar.
- The parameters in it are ``label`` for the label,
- ``bar`` for the progress bar and ``info`` for the
- info section.
- :param info_sep: the separator between multiple info items (eta etc.)
- :param width: the width of the progress bar in characters, 0 means full
- terminal width
- :param file: The file to write to. If this is not a terminal then
- only the label is printed.
- :param color: controls if the terminal supports ANSI colors or not. The
- default is autodetection. This is only needed if ANSI
- codes are included anywhere in the progress bar output
- which is not the case by default.
- :param update_min_steps: Render only when this many updates have
- completed. This allows tuning for very fast iterators.
-
- .. versionchanged:: 8.0
- Output is shown even if execution time is less than 0.5 seconds.
-
- .. versionchanged:: 8.0
- ``item_show_func`` shows the current item, not the previous one.
-
- .. versionchanged:: 8.0
- Labels are echoed if the output is not a TTY. Reverts a change
- in 7.0 that removed all output.
-
- .. versionadded:: 8.0
- Added the ``update_min_steps`` parameter.
-
- .. versionchanged:: 4.0
- Added the ``color`` parameter. Added the ``update`` method to
- the object.
-
- .. versionadded:: 2.0
- """
- from ._termui_impl import ProgressBar
-
- color = resolve_color_default(color)
- return ProgressBar(
- iterable=iterable,
- length=length,
- show_eta=show_eta,
- show_percent=show_percent,
- show_pos=show_pos,
- item_show_func=item_show_func,
- fill_char=fill_char,
- empty_char=empty_char,
- bar_template=bar_template,
- info_sep=info_sep,
- file=file,
- label=label,
- width=width,
- color=color,
- update_min_steps=update_min_steps,
- )
-
-
-def clear() -> None:
- """Clears the terminal screen. This will have the effect of clearing
- the whole visible space of the terminal and moving the cursor to the
- top left. This does not do anything if not connected to a terminal.
-
- .. versionadded:: 2.0
- """
- if not isatty(sys.stdout):
- return
-
- # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor
- echo("\033[2J\033[1;1H", nl=False)
-
-
-def _interpret_color(
- color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0
-) -> str:
- if isinstance(color, int):
- return f"{38 + offset};5;{color:d}"
-
- if isinstance(color, (tuple, list)):
- r, g, b = color
- return f"{38 + offset};2;{r:d};{g:d};{b:d}"
-
- return str(_ansi_colors[color] + offset)
-
-
-def style(
- text: t.Any,
- fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None,
- bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None,
- bold: t.Optional[bool] = None,
- dim: t.Optional[bool] = None,
- underline: t.Optional[bool] = None,
- overline: t.Optional[bool] = None,
- italic: t.Optional[bool] = None,
- blink: t.Optional[bool] = None,
- reverse: t.Optional[bool] = None,
- strikethrough: t.Optional[bool] = None,
- reset: bool = True,
-) -> str:
- """Styles a text with ANSI styles and returns the new string. By
- default the styling is self contained which means that at the end
- of the string a reset code is issued. This can be prevented by
- passing ``reset=False``.
-
- Examples::
-
- click.echo(click.style('Hello World!', fg='green'))
- click.echo(click.style('ATTENTION!', blink=True))
- click.echo(click.style('Some things', reverse=True, fg='cyan'))
- click.echo(click.style('More colors', fg=(255, 12, 128), bg=117))
-
- Supported color names:
-
- * ``black`` (might be a gray)
- * ``red``
- * ``green``
- * ``yellow`` (might be an orange)
- * ``blue``
- * ``magenta``
- * ``cyan``
- * ``white`` (might be light gray)
- * ``bright_black``
- * ``bright_red``
- * ``bright_green``
- * ``bright_yellow``
- * ``bright_blue``
- * ``bright_magenta``
- * ``bright_cyan``
- * ``bright_white``
- * ``reset`` (reset the color code only)
-
- If the terminal supports it, color may also be specified as:
-
- - An integer in the interval [0, 255]. The terminal must support
- 8-bit/256-color mode.
- - An RGB tuple of three integers in [0, 255]. The terminal must
- support 24-bit/true-color mode.
-
- See https://en.wikipedia.org/wiki/ANSI_color and
- https://gist.github.com/XVilka/8346728 for more information.
-
- :param text: the string to style with ansi codes.
- :param fg: if provided this will become the foreground color.
- :param bg: if provided this will become the background color.
- :param bold: if provided this will enable or disable bold mode.
- :param dim: if provided this will enable or disable dim mode. This is
- badly supported.
- :param underline: if provided this will enable or disable underline.
- :param overline: if provided this will enable or disable overline.
- :param italic: if provided this will enable or disable italic.
- :param blink: if provided this will enable or disable blinking.
- :param reverse: if provided this will enable or disable inverse
- rendering (foreground becomes background and the
- other way round).
- :param strikethrough: if provided this will enable or disable
- striking through text.
- :param reset: by default a reset-all code is added at the end of the
- string which means that styles do not carry over. This
- can be disabled to compose styles.
-
- .. versionchanged:: 8.0
- A non-string ``message`` is converted to a string.
-
- .. versionchanged:: 8.0
- Added support for 256 and RGB color codes.
-
- .. versionchanged:: 8.0
- Added the ``strikethrough``, ``italic``, and ``overline``
- parameters.
-
- .. versionchanged:: 7.0
- Added support for bright colors.
-
- .. versionadded:: 2.0
- """
- if not isinstance(text, str):
- text = str(text)
-
- bits = []
-
- if fg:
- try:
- bits.append(f"\033[{_interpret_color(fg)}m")
- except KeyError:
- raise TypeError(f"Unknown color {fg!r}") from None
-
- if bg:
- try:
- bits.append(f"\033[{_interpret_color(bg, 10)}m")
- except KeyError:
- raise TypeError(f"Unknown color {bg!r}") from None
-
- if bold is not None:
- bits.append(f"\033[{1 if bold else 22}m")
- if dim is not None:
- bits.append(f"\033[{2 if dim else 22}m")
- if underline is not None:
- bits.append(f"\033[{4 if underline else 24}m")
- if overline is not None:
- bits.append(f"\033[{53 if overline else 55}m")
- if italic is not None:
- bits.append(f"\033[{3 if italic else 23}m")
- if blink is not None:
- bits.append(f"\033[{5 if blink else 25}m")
- if reverse is not None:
- bits.append(f"\033[{7 if reverse else 27}m")
- if strikethrough is not None:
- bits.append(f"\033[{9 if strikethrough else 29}m")
- bits.append(text)
- if reset:
- bits.append(_ansi_reset_all)
- return "".join(bits)
-
-
-def unstyle(text: str) -> str:
- """Removes ANSI styling information from a string. Usually it's not
- necessary to use this function as Click's echo function will
- automatically remove styling if necessary.
-
- .. versionadded:: 2.0
-
- :param text: the text to remove style information from.
- """
- return strip_ansi(text)
-
-
-def secho(
- message: t.Optional[t.Any] = None,
- file: t.Optional[t.IO[t.AnyStr]] = None,
- nl: bool = True,
- err: bool = False,
- color: t.Optional[bool] = None,
- **styles: t.Any,
-) -> None:
- """This function combines :func:`echo` and :func:`style` into one
- call. As such the following two calls are the same::
-
- click.secho('Hello World!', fg='green')
- click.echo(click.style('Hello World!', fg='green'))
-
- All keyword arguments are forwarded to the underlying functions
- depending on which one they go with.
-
- Non-string types will be converted to :class:`str`. However,
- :class:`bytes` are passed directly to :meth:`echo` without applying
- style. If you want to style bytes that represent text, call
- :meth:`bytes.decode` first.
-
- .. versionchanged:: 8.0
- A non-string ``message`` is converted to a string. Bytes are
- passed through without style applied.
-
- .. versionadded:: 2.0
- """
- if message is not None and not isinstance(message, (bytes, bytearray)):
- message = style(message, **styles)
-
- return echo(message, file=file, nl=nl, err=err, color=color)
-
-
-def edit(
- text: t.Optional[t.AnyStr] = None,
- editor: t.Optional[str] = None,
- env: t.Optional[t.Mapping[str, str]] = None,
- require_save: bool = True,
- extension: str = ".txt",
- filename: t.Optional[str] = None,
-) -> t.Optional[t.AnyStr]:
- r"""Edits the given text in the defined editor. If an editor is given
- (should be the full path to the executable but the regular operating
- system search path is used for finding the executable) it overrides
- the detected editor. Optionally, some environment variables can be
- used. If the editor is closed without changes, `None` is returned. In
- case a file is edited directly the return value is always `None` and
- `require_save` and `extension` are ignored.
-
- If the editor cannot be opened a :exc:`UsageError` is raised.
-
- Note for Windows: to simplify cross-platform usage, the newlines are
- automatically converted from POSIX to Windows and vice versa. As such,
- the message here will have ``\n`` as newline markers.
-
- :param text: the text to edit.
- :param editor: optionally the editor to use. Defaults to automatic
- detection.
- :param env: environment variables to forward to the editor.
- :param require_save: if this is true, then not saving in the editor
- will make the return value become `None`.
- :param extension: the extension to tell the editor about. This defaults
- to `.txt` but changing this might change syntax
- highlighting.
- :param filename: if provided it will edit this file instead of the
- provided text contents. It will not use a temporary
- file as an indirection in that case.
- """
- from ._termui_impl import Editor
-
- ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension)
-
- if filename is None:
- return ed.edit(text)
-
- ed.edit_file(filename)
- return None
-
-
-def launch(url: str, wait: bool = False, locate: bool = False) -> int:
- """This function launches the given URL (or filename) in the default
- viewer application for this file type. If this is an executable, it
- might launch the executable in a new session. The return value is
- the exit code of the launched application. Usually, ``0`` indicates
- success.
-
- Examples::
-
- click.launch('https://click.palletsprojects.com/')
- click.launch('/my/downloaded/file', locate=True)
-
- .. versionadded:: 2.0
-
- :param url: URL or filename of the thing to launch.
- :param wait: Wait for the program to exit before returning. This
- only works if the launched program blocks. In particular,
- ``xdg-open`` on Linux does not block.
- :param locate: if this is set to `True` then instead of launching the
- application associated with the URL it will attempt to
- launch a file manager with the file located. This
- might have weird effects if the URL does not point to
- the filesystem.
- """
- from ._termui_impl import open_url
-
- return open_url(url, wait=wait, locate=locate)
-
-
-# If this is provided, getchar() calls into this instead. This is used
-# for unittesting purposes.
-_getchar: t.Optional[t.Callable[[bool], str]] = None
-
-
-def getchar(echo: bool = False) -> str:
- """Fetches a single character from the terminal and returns it. This
- will always return a unicode character and under certain rare
- circumstances this might return more than one character. The
- situations which more than one character is returned is when for
- whatever reason multiple characters end up in the terminal buffer or
- standard input was not actually a terminal.
-
- Note that this will always read from the terminal, even if something
- is piped into the standard input.
-
- Note for Windows: in rare cases when typing non-ASCII characters, this
- function might wait for a second character and then return both at once.
- This is because certain Unicode characters look like special-key markers.
-
- .. versionadded:: 2.0
-
- :param echo: if set to `True`, the character read will also show up on
- the terminal. The default is to not show it.
- """
- global _getchar
-
- if _getchar is None:
- from ._termui_impl import getchar as f
-
- _getchar = f
-
- return _getchar(echo)
-
-
-def raw_terminal() -> t.ContextManager[int]:
- from ._termui_impl import raw_terminal as f
-
- return f()
-
-
-def pause(info: t.Optional[str] = None, err: bool = False) -> None:
- """This command stops execution and waits for the user to press any
- key to continue. This is similar to the Windows batch "pause"
- command. If the program is not run through a terminal, this command
- will instead do nothing.
-
- .. versionadded:: 2.0
-
- .. versionadded:: 4.0
- Added the `err` parameter.
-
- :param info: The message to print before pausing. Defaults to
- ``"Press any key to continue..."``.
- :param err: if set to message goes to ``stderr`` instead of
- ``stdout``, the same as with echo.
- """
- if not isatty(sys.stdin) or not isatty(sys.stdout):
- return
-
- if info is None:
- info = _("Press any key to continue...")
-
- try:
- if info:
- echo(info, nl=False, err=err)
- try:
- getchar()
- except (KeyboardInterrupt, EOFError):
- pass
- finally:
- if info:
- echo(err=err)