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

228 statements  

1from __future__ import annotations 

2 

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 _ 

13 

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 

24 

25if t.TYPE_CHECKING: 

26 from ._termui_impl import ProgressBar 

27 

28V = t.TypeVar("V") 

29 

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 

33 

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" 

54 

55 

56_HIDDEN_INPUT_MASK = "'***'" 

57 

58 

59def _mask_hidden_input(message: str, value: str) -> str: 

60 """Replace occurrences of ``value`` in ``message`` with a fixed mask. 

61 

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 

75 

76 

77def hidden_prompt_func(prompt: str) -> str: 

78 import getpass 

79 

80 return getpass.getpass(prompt) 

81 

82 

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) 

91 

92 

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}" 

109 

110 

111def _format_default(default: t.Any) -> t.Any: 

112 if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): 

113 return default.name 

114 

115 return default 

116 

117 

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. 

132 

133 If the user aborts the input by sending an interrupt signal, this 

134 function will catch it and raise a :exc:`Abort` exception. 

135 

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): ". 

158 

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. 

162 

163 .. versionchanged:: 8.3.1 

164 A space is no longer appended to the prompt. 

165 

166 .. versionadded:: 8.0 

167 ``confirmation_prompt`` can be a custom string. 

168 

169 .. versionadded:: 7.0 

170 Added the ``show_choices`` parameter. 

171 

172 .. versionadded:: 6.0 

173 Added unicode support for cmd.exe on Windows. 

174 

175 .. versionadded:: 4.0 

176 Added the `err` parameter. 

177 

178 """ 

179 

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 

191 

192 if value_proc is None: 

193 value_proc = convert_type(type, default) 

194 

195 prompt = _build_prompt( 

196 text, prompt_suffix, show_default, default, show_choices, type 

197 ) 

198 

199 if confirmation_prompt: 

200 if confirmation_prompt is True: 

201 confirmation_prompt = _("Repeat for confirmation") 

202 

203 confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) 

204 

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) 

229 

230 

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). 

240 

241 If the user aborts the input by sending a interrupt signal this 

242 function will catch it and raise a :exc:`Abort` exception. 

243 

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. 

253 

254 .. versionchanged:: 8.3.1 

255 A space is no longer appended to the prompt. 

256 

257 .. versionchanged:: 8.0 

258 Repeat until input is given if ``default`` is ``None``. 

259 

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 ) 

269 

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 

288 

289 

290def get_pager_file( 

291 color: bool | None = None, 

292) -> t.ContextManager[t.TextIO]: 

293 """Context manager. 

294 

295 Yields a writable file-like object which can be used as an output pager. 

296 

297 .. versionadded:: 8.4.0 

298 

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 

303 

304 color = resolve_color_default(color) 

305 

306 return get_pager_file(color=color) 

307 

308 

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. 

315 

316 .. versionchanged:: 3.0 

317 Added the `color` flag. 

318 

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 """ 

324 

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)) 

331 

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) 

334 

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() 

342 

343 

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]: ... 

362 

363 

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]: ... 

383 

384 

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. 

410 

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. 

416 

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. 

422 

423 No printing must happen or the progress bar will be unintentionally 

424 destroyed. 

425 

426 Example usage:: 

427 

428 with progressbar(items) as bar: 

429 for item in bar: 

430 do_something_with(item) 

431 

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:: 

436 

437 with progressbar(length=chunks.total_bytes) as bar: 

438 for chunk in chunks: 

439 process_chunk(chunk) 

440 bar.update(chunks.bytes) 

441 

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:: 

446 

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) 

455 

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. 

499 

500 .. versionadded:: 8.2 

501 The ``hidden`` argument. 

502 

503 .. versionchanged:: 8.0 

504 Output is shown even if execution time is less than 0.5 seconds. 

505 

506 .. versionchanged:: 8.0 

507 ``item_show_func`` shows the current item, not the previous one. 

508 

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. 

512 

513 .. versionadded:: 8.0 

514 The ``update_min_steps`` parameter. 

515 

516 .. versionadded:: 4.0 

517 The ``color`` parameter and ``update`` method. 

518 

519 .. versionadded:: 2.0 

520 """ 

521 from ._termui_impl import ProgressBar 

522 

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 ) 

542 

543 

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. 

548 

549 .. versionadded:: 2.0 

550 """ 

551 if not isatty(sys.stdout): 

552 return 

553 

554 # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor 

555 echo("\033[2J\033[1;1H", nl=False) 

556 

557 

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}" 

561 

562 if isinstance(color, (tuple, list)): 

563 r, g, b = color 

564 return f"{38 + offset};2;{r:d};{g:d};{b:d}" 

565 

566 return str(_ansi_colors[color] + offset) 

567 

568 

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``. 

587 

588 Examples:: 

589 

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)) 

594 

595 Supported color names: 

596 

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) 

614 

615 If the terminal supports it, color may also be specified as: 

616 

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. 

621 

622 See https://en.wikipedia.org/wiki/ANSI_color and 

623 https://gist.github.com/XVilka/8346728 for more information. 

624 

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. 

643 

644 .. versionchanged:: 8.0 

645 A non-string ``message`` is converted to a string. 

646 

647 .. versionchanged:: 8.0 

648 Added support for 256 and RGB color codes. 

649 

650 .. versionchanged:: 8.0 

651 Added the ``strikethrough``, ``italic``, and ``overline`` 

652 parameters. 

653 

654 .. versionchanged:: 7.0 

655 Added support for bright colors. 

656 

657 .. versionadded:: 2.0 

658 """ 

659 if not isinstance(text, str): 

660 text = str(text) 

661 

662 bits = [] 

663 

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 

669 

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 

675 

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) 

696 

697 

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. 

702 

703 .. versionadded:: 2.0 

704 

705 :param text: the text to remove style information from. 

706 """ 

707 return strip_ansi(text) 

708 

709 

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:: 

720 

721 click.secho('Hello World!', fg='green') 

722 click.echo(click.style('Hello World!', fg='green')) 

723 

724 All keyword arguments are forwarded to the underlying functions 

725 depending on which one they go with. 

726 

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. 

731 

732 .. versionchanged:: 8.0 

733 A non-string ``message`` is converted to a string. Bytes are 

734 passed through without style applied. 

735 

736 .. versionadded:: 2.0 

737 """ 

738 if message is not None and not isinstance(message, (bytes, bytearray)): 

739 message = style(message, **styles) 

740 

741 return echo(message, file=file, nl=nl, err=err, color=color) 

742 

743 

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: ... 

752 

753 

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: ... 

762 

763 

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: ... 

773 

774 

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. 

790 

791 If the editor cannot be opened a :exc:`UsageError` is raised. 

792 

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. 

796 

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. 

813 

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. 

817 

818 """ 

819 from ._termui_impl import Editor 

820 

821 ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) 

822 

823 if filename is None: 

824 return ed.edit(text) 

825 

826 if isinstance(filename, str): 

827 filename = (filename,) 

828 

829 ed.edit_files(filenames=filename) 

830 return None 

831 

832 

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. 

839 

840 Examples:: 

841 

842 click.launch('https://click.palletsprojects.com/') 

843 click.launch('/my/downloaded/file', locate=True) 

844 

845 .. versionadded:: 2.0 

846 

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 

858 

859 return open_url(url, wait=wait, locate=locate) 

860 

861 

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 

865 

866 

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. 

874 

875 Note that this will always read from the terminal, even if something 

876 is piped into the standard input. 

877 

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. 

881 

882 .. versionadded:: 2.0 

883 

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 

888 

889 if _getchar is None: 

890 from ._termui_impl import getchar as f 

891 

892 _getchar = f 

893 

894 return _getchar(echo) 

895 

896 

897def raw_terminal() -> AbstractContextManager[int]: 

898 from ._termui_impl import raw_terminal as f 

899 

900 return f() 

901 

902 

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. 

908 

909 .. versionadded:: 2.0 

910 

911 .. versionadded:: 4.0 

912 Added the `err` parameter. 

913 

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 

921 

922 if info is None: 

923 info = _("Press any key to continue...") 

924 

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)