comparison env/lib/python3.9/site-packages/click/termui.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 import inspect
2 import io
3 import itertools
4 import os
5 import struct
6 import sys
7
8 from ._compat import DEFAULT_COLUMNS
9 from ._compat import get_winterm_size
10 from ._compat import isatty
11 from ._compat import raw_input
12 from ._compat import string_types
13 from ._compat import strip_ansi
14 from ._compat import text_type
15 from ._compat import WIN
16 from .exceptions import Abort
17 from .exceptions import UsageError
18 from .globals import resolve_color_default
19 from .types import Choice
20 from .types import convert_type
21 from .types import Path
22 from .utils import echo
23 from .utils import LazyFile
24
25 # The prompt functions to use. The doc tools currently override these
26 # functions to customize how they work.
27 visible_prompt_func = raw_input
28
29 _ansi_colors = {
30 "black": 30,
31 "red": 31,
32 "green": 32,
33 "yellow": 33,
34 "blue": 34,
35 "magenta": 35,
36 "cyan": 36,
37 "white": 37,
38 "reset": 39,
39 "bright_black": 90,
40 "bright_red": 91,
41 "bright_green": 92,
42 "bright_yellow": 93,
43 "bright_blue": 94,
44 "bright_magenta": 95,
45 "bright_cyan": 96,
46 "bright_white": 97,
47 }
48 _ansi_reset_all = "\033[0m"
49
50
51 def hidden_prompt_func(prompt):
52 import getpass
53
54 return getpass.getpass(prompt)
55
56
57 def _build_prompt(
58 text, suffix, show_default=False, default=None, show_choices=True, type=None
59 ):
60 prompt = text
61 if type is not None and show_choices and isinstance(type, Choice):
62 prompt += " ({})".format(", ".join(map(str, type.choices)))
63 if default is not None and show_default:
64 prompt = "{} [{}]".format(prompt, _format_default(default))
65 return prompt + suffix
66
67
68 def _format_default(default):
69 if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"):
70 return default.name
71
72 return default
73
74
75 def prompt(
76 text,
77 default=None,
78 hide_input=False,
79 confirmation_prompt=False,
80 type=None,
81 value_proc=None,
82 prompt_suffix=": ",
83 show_default=True,
84 err=False,
85 show_choices=True,
86 ):
87 """Prompts a user for input. This is a convenience function that can
88 be used to prompt a user for input later.
89
90 If the user aborts the input by sending a interrupt signal, this
91 function will catch it and raise a :exc:`Abort` exception.
92
93 .. versionadded:: 7.0
94 Added the show_choices parameter.
95
96 .. versionadded:: 6.0
97 Added unicode support for cmd.exe on Windows.
98
99 .. versionadded:: 4.0
100 Added the `err` parameter.
101
102 :param text: the text to show for the prompt.
103 :param default: the default value to use if no input happens. If this
104 is not given it will prompt until it's aborted.
105 :param hide_input: if this is set to true then the input value will
106 be hidden.
107 :param confirmation_prompt: asks for confirmation for the value.
108 :param type: the type to use to check the value against.
109 :param value_proc: if this parameter is provided it's a function that
110 is invoked instead of the type conversion to
111 convert a value.
112 :param prompt_suffix: a suffix that should be added to the prompt.
113 :param show_default: shows or hides the default value in the prompt.
114 :param err: if set to true the file defaults to ``stderr`` instead of
115 ``stdout``, the same as with echo.
116 :param show_choices: Show or hide choices if the passed type is a Choice.
117 For example if type is a Choice of either day or week,
118 show_choices is true and text is "Group by" then the
119 prompt will be "Group by (day, week): ".
120 """
121 result = None
122
123 def prompt_func(text):
124 f = hidden_prompt_func if hide_input else visible_prompt_func
125 try:
126 # Write the prompt separately so that we get nice
127 # coloring through colorama on Windows
128 echo(text, nl=False, err=err)
129 return f("")
130 except (KeyboardInterrupt, EOFError):
131 # getpass doesn't print a newline if the user aborts input with ^C.
132 # Allegedly this behavior is inherited from getpass(3).
133 # A doc bug has been filed at https://bugs.python.org/issue24711
134 if hide_input:
135 echo(None, err=err)
136 raise Abort()
137
138 if value_proc is None:
139 value_proc = convert_type(type, default)
140
141 prompt = _build_prompt(
142 text, prompt_suffix, show_default, default, show_choices, type
143 )
144
145 while 1:
146 while 1:
147 value = prompt_func(prompt)
148 if value:
149 break
150 elif default is not None:
151 if isinstance(value_proc, Path):
152 # validate Path default value(exists, dir_okay etc.)
153 value = default
154 break
155 return default
156 try:
157 result = value_proc(value)
158 except UsageError as e:
159 echo("Error: {}".format(e.message), err=err) # noqa: B306
160 continue
161 if not confirmation_prompt:
162 return result
163 while 1:
164 value2 = prompt_func("Repeat for confirmation: ")
165 if value2:
166 break
167 if value == value2:
168 return result
169 echo("Error: the two entered values do not match", err=err)
170
171
172 def confirm(
173 text, default=False, abort=False, prompt_suffix=": ", show_default=True, err=False
174 ):
175 """Prompts for confirmation (yes/no question).
176
177 If the user aborts the input by sending a interrupt signal this
178 function will catch it and raise a :exc:`Abort` exception.
179
180 .. versionadded:: 4.0
181 Added the `err` parameter.
182
183 :param text: the question to ask.
184 :param default: the default for the prompt.
185 :param abort: if this is set to `True` a negative answer aborts the
186 exception by raising :exc:`Abort`.
187 :param prompt_suffix: a suffix that should be added to the prompt.
188 :param show_default: shows or hides the default value in the prompt.
189 :param err: if set to true the file defaults to ``stderr`` instead of
190 ``stdout``, the same as with echo.
191 """
192 prompt = _build_prompt(
193 text, prompt_suffix, show_default, "Y/n" if default else "y/N"
194 )
195 while 1:
196 try:
197 # Write the prompt separately so that we get nice
198 # coloring through colorama on Windows
199 echo(prompt, nl=False, err=err)
200 value = visible_prompt_func("").lower().strip()
201 except (KeyboardInterrupt, EOFError):
202 raise Abort()
203 if value in ("y", "yes"):
204 rv = True
205 elif value in ("n", "no"):
206 rv = False
207 elif value == "":
208 rv = default
209 else:
210 echo("Error: invalid input", err=err)
211 continue
212 break
213 if abort and not rv:
214 raise Abort()
215 return rv
216
217
218 def get_terminal_size():
219 """Returns the current size of the terminal as tuple in the form
220 ``(width, height)`` in columns and rows.
221 """
222 # If shutil has get_terminal_size() (Python 3.3 and later) use that
223 if sys.version_info >= (3, 3):
224 import shutil
225
226 shutil_get_terminal_size = getattr(shutil, "get_terminal_size", None)
227 if shutil_get_terminal_size:
228 sz = shutil_get_terminal_size()
229 return sz.columns, sz.lines
230
231 # We provide a sensible default for get_winterm_size() when being invoked
232 # inside a subprocess. Without this, it would not provide a useful input.
233 if get_winterm_size is not None:
234 size = get_winterm_size()
235 if size == (0, 0):
236 return (79, 24)
237 else:
238 return size
239
240 def ioctl_gwinsz(fd):
241 try:
242 import fcntl
243 import termios
244
245 cr = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))
246 except Exception:
247 return
248 return cr
249
250 cr = ioctl_gwinsz(0) or ioctl_gwinsz(1) or ioctl_gwinsz(2)
251 if not cr:
252 try:
253 fd = os.open(os.ctermid(), os.O_RDONLY)
254 try:
255 cr = ioctl_gwinsz(fd)
256 finally:
257 os.close(fd)
258 except Exception:
259 pass
260 if not cr or not cr[0] or not cr[1]:
261 cr = (os.environ.get("LINES", 25), os.environ.get("COLUMNS", DEFAULT_COLUMNS))
262 return int(cr[1]), int(cr[0])
263
264
265 def echo_via_pager(text_or_generator, color=None):
266 """This function takes a text and shows it via an environment specific
267 pager on stdout.
268
269 .. versionchanged:: 3.0
270 Added the `color` flag.
271
272 :param text_or_generator: the text to page, or alternatively, a
273 generator emitting the text to page.
274 :param color: controls if the pager supports ANSI colors or not. The
275 default is autodetection.
276 """
277 color = resolve_color_default(color)
278
279 if inspect.isgeneratorfunction(text_or_generator):
280 i = text_or_generator()
281 elif isinstance(text_or_generator, string_types):
282 i = [text_or_generator]
283 else:
284 i = iter(text_or_generator)
285
286 # convert every element of i to a text type if necessary
287 text_generator = (el if isinstance(el, string_types) else text_type(el) for el in i)
288
289 from ._termui_impl import pager
290
291 return pager(itertools.chain(text_generator, "\n"), color)
292
293
294 def progressbar(
295 iterable=None,
296 length=None,
297 label=None,
298 show_eta=True,
299 show_percent=None,
300 show_pos=False,
301 item_show_func=None,
302 fill_char="#",
303 empty_char="-",
304 bar_template="%(label)s [%(bar)s] %(info)s",
305 info_sep=" ",
306 width=36,
307 file=None,
308 color=None,
309 ):
310 """This function creates an iterable context manager that can be used
311 to iterate over something while showing a progress bar. It will
312 either iterate over the `iterable` or `length` items (that are counted
313 up). While iteration happens, this function will print a rendered
314 progress bar to the given `file` (defaults to stdout) and will attempt
315 to calculate remaining time and more. By default, this progress bar
316 will not be rendered if the file is not a terminal.
317
318 The context manager creates the progress bar. When the context
319 manager is entered the progress bar is already created. With every
320 iteration over the progress bar, the iterable passed to the bar is
321 advanced and the bar is updated. When the context manager exits,
322 a newline is printed and the progress bar is finalized on screen.
323
324 Note: The progress bar is currently designed for use cases where the
325 total progress can be expected to take at least several seconds.
326 Because of this, the ProgressBar class object won't display
327 progress that is considered too fast, and progress where the time
328 between steps is less than a second.
329
330 No printing must happen or the progress bar will be unintentionally
331 destroyed.
332
333 Example usage::
334
335 with progressbar(items) as bar:
336 for item in bar:
337 do_something_with(item)
338
339 Alternatively, if no iterable is specified, one can manually update the
340 progress bar through the `update()` method instead of directly
341 iterating over the progress bar. The update method accepts the number
342 of steps to increment the bar with::
343
344 with progressbar(length=chunks.total_bytes) as bar:
345 for chunk in chunks:
346 process_chunk(chunk)
347 bar.update(chunks.bytes)
348
349 .. versionadded:: 2.0
350
351 .. versionadded:: 4.0
352 Added the `color` parameter. Added a `update` method to the
353 progressbar object.
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 the current item
374 next to the progress bar. Note that the current
375 item can be `None`!
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 """
394 from ._termui_impl import ProgressBar
395
396 color = resolve_color_default(color)
397 return ProgressBar(
398 iterable=iterable,
399 length=length,
400 show_eta=show_eta,
401 show_percent=show_percent,
402 show_pos=show_pos,
403 item_show_func=item_show_func,
404 fill_char=fill_char,
405 empty_char=empty_char,
406 bar_template=bar_template,
407 info_sep=info_sep,
408 file=file,
409 label=label,
410 width=width,
411 color=color,
412 )
413
414
415 def clear():
416 """Clears the terminal screen. This will have the effect of clearing
417 the whole visible space of the terminal and moving the cursor to the
418 top left. This does not do anything if not connected to a terminal.
419
420 .. versionadded:: 2.0
421 """
422 if not isatty(sys.stdout):
423 return
424 # If we're on Windows and we don't have colorama available, then we
425 # clear the screen by shelling out. Otherwise we can use an escape
426 # sequence.
427 if WIN:
428 os.system("cls")
429 else:
430 sys.stdout.write("\033[2J\033[1;1H")
431
432
433 def style(
434 text,
435 fg=None,
436 bg=None,
437 bold=None,
438 dim=None,
439 underline=None,
440 blink=None,
441 reverse=None,
442 reset=True,
443 ):
444 """Styles a text with ANSI styles and returns the new string. By
445 default the styling is self contained which means that at the end
446 of the string a reset code is issued. This can be prevented by
447 passing ``reset=False``.
448
449 Examples::
450
451 click.echo(click.style('Hello World!', fg='green'))
452 click.echo(click.style('ATTENTION!', blink=True))
453 click.echo(click.style('Some things', reverse=True, fg='cyan'))
454
455 Supported color names:
456
457 * ``black`` (might be a gray)
458 * ``red``
459 * ``green``
460 * ``yellow`` (might be an orange)
461 * ``blue``
462 * ``magenta``
463 * ``cyan``
464 * ``white`` (might be light gray)
465 * ``bright_black``
466 * ``bright_red``
467 * ``bright_green``
468 * ``bright_yellow``
469 * ``bright_blue``
470 * ``bright_magenta``
471 * ``bright_cyan``
472 * ``bright_white``
473 * ``reset`` (reset the color code only)
474
475 .. versionadded:: 2.0
476
477 .. versionadded:: 7.0
478 Added support for bright colors.
479
480 :param text: the string to style with ansi codes.
481 :param fg: if provided this will become the foreground color.
482 :param bg: if provided this will become the background color.
483 :param bold: if provided this will enable or disable bold mode.
484 :param dim: if provided this will enable or disable dim mode. This is
485 badly supported.
486 :param underline: if provided this will enable or disable underline.
487 :param blink: if provided this will enable or disable blinking.
488 :param reverse: if provided this will enable or disable inverse
489 rendering (foreground becomes background and the
490 other way round).
491 :param reset: by default a reset-all code is added at the end of the
492 string which means that styles do not carry over. This
493 can be disabled to compose styles.
494 """
495 bits = []
496 if fg:
497 try:
498 bits.append("\033[{}m".format(_ansi_colors[fg]))
499 except KeyError:
500 raise TypeError("Unknown color '{}'".format(fg))
501 if bg:
502 try:
503 bits.append("\033[{}m".format(_ansi_colors[bg] + 10))
504 except KeyError:
505 raise TypeError("Unknown color '{}'".format(bg))
506 if bold is not None:
507 bits.append("\033[{}m".format(1 if bold else 22))
508 if dim is not None:
509 bits.append("\033[{}m".format(2 if dim else 22))
510 if underline is not None:
511 bits.append("\033[{}m".format(4 if underline else 24))
512 if blink is not None:
513 bits.append("\033[{}m".format(5 if blink else 25))
514 if reverse is not None:
515 bits.append("\033[{}m".format(7 if reverse else 27))
516 bits.append(text)
517 if reset:
518 bits.append(_ansi_reset_all)
519 return "".join(bits)
520
521
522 def unstyle(text):
523 """Removes ANSI styling information from a string. Usually it's not
524 necessary to use this function as Click's echo function will
525 automatically remove styling if necessary.
526
527 .. versionadded:: 2.0
528
529 :param text: the text to remove style information from.
530 """
531 return strip_ansi(text)
532
533
534 def secho(message=None, file=None, nl=True, err=False, color=None, **styles):
535 """This function combines :func:`echo` and :func:`style` into one
536 call. As such the following two calls are the same::
537
538 click.secho('Hello World!', fg='green')
539 click.echo(click.style('Hello World!', fg='green'))
540
541 All keyword arguments are forwarded to the underlying functions
542 depending on which one they go with.
543
544 .. versionadded:: 2.0
545 """
546 if message is not None:
547 message = style(message, **styles)
548 return echo(message, file=file, nl=nl, err=err, color=color)
549
550
551 def edit(
552 text=None, editor=None, env=None, require_save=True, extension=".txt", filename=None
553 ):
554 r"""Edits the given text in the defined editor. If an editor is given
555 (should be the full path to the executable but the regular operating
556 system search path is used for finding the executable) it overrides
557 the detected editor. Optionally, some environment variables can be
558 used. If the editor is closed without changes, `None` is returned. In
559 case a file is edited directly the return value is always `None` and
560 `require_save` and `extension` are ignored.
561
562 If the editor cannot be opened a :exc:`UsageError` is raised.
563
564 Note for Windows: to simplify cross-platform usage, the newlines are
565 automatically converted from POSIX to Windows and vice versa. As such,
566 the message here will have ``\n`` as newline markers.
567
568 :param text: the text to edit.
569 :param editor: optionally the editor to use. Defaults to automatic
570 detection.
571 :param env: environment variables to forward to the editor.
572 :param require_save: if this is true, then not saving in the editor
573 will make the return value become `None`.
574 :param extension: the extension to tell the editor about. This defaults
575 to `.txt` but changing this might change syntax
576 highlighting.
577 :param filename: if provided it will edit this file instead of the
578 provided text contents. It will not use a temporary
579 file as an indirection in that case.
580 """
581 from ._termui_impl import Editor
582
583 editor = Editor(
584 editor=editor, env=env, require_save=require_save, extension=extension
585 )
586 if filename is None:
587 return editor.edit(text)
588 editor.edit_file(filename)
589
590
591 def launch(url, wait=False, locate=False):
592 """This function launches the given URL (or filename) in the default
593 viewer application for this file type. If this is an executable, it
594 might launch the executable in a new session. The return value is
595 the exit code of the launched application. Usually, ``0`` indicates
596 success.
597
598 Examples::
599
600 click.launch('https://click.palletsprojects.com/')
601 click.launch('/my/downloaded/file', locate=True)
602
603 .. versionadded:: 2.0
604
605 :param url: URL or filename of the thing to launch.
606 :param wait: waits for the program to stop.
607 :param locate: if this is set to `True` then instead of launching the
608 application associated with the URL it will attempt to
609 launch a file manager with the file located. This
610 might have weird effects if the URL does not point to
611 the filesystem.
612 """
613 from ._termui_impl import open_url
614
615 return open_url(url, wait=wait, locate=locate)
616
617
618 # If this is provided, getchar() calls into this instead. This is used
619 # for unittesting purposes.
620 _getchar = None
621
622
623 def getchar(echo=False):
624 """Fetches a single character from the terminal and returns it. This
625 will always return a unicode character and under certain rare
626 circumstances this might return more than one character. The
627 situations which more than one character is returned is when for
628 whatever reason multiple characters end up in the terminal buffer or
629 standard input was not actually a terminal.
630
631 Note that this will always read from the terminal, even if something
632 is piped into the standard input.
633
634 Note for Windows: in rare cases when typing non-ASCII characters, this
635 function might wait for a second character and then return both at once.
636 This is because certain Unicode characters look like special-key markers.
637
638 .. versionadded:: 2.0
639
640 :param echo: if set to `True`, the character read will also show up on
641 the terminal. The default is to not show it.
642 """
643 f = _getchar
644 if f is None:
645 from ._termui_impl import getchar as f
646 return f(echo)
647
648
649 def raw_terminal():
650 from ._termui_impl import raw_terminal as f
651
652 return f()
653
654
655 def pause(info="Press any key to continue ...", err=False):
656 """This command stops execution and waits for the user to press any
657 key to continue. This is similar to the Windows batch "pause"
658 command. If the program is not run through a terminal, this command
659 will instead do nothing.
660
661 .. versionadded:: 2.0
662
663 .. versionadded:: 4.0
664 Added the `err` parameter.
665
666 :param info: the info string to print before pausing.
667 :param err: if set to message goes to ``stderr`` instead of
668 ``stdout``, the same as with echo.
669 """
670 if not isatty(sys.stdin) or not isatty(sys.stdout):
671 return
672 try:
673 if info:
674 echo(info, nl=False, err=err)
675 try:
676 getchar()
677 except (KeyboardInterrupt, EOFError):
678 pass
679 finally:
680 if info:
681 echo(err=err)