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

232 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 ._compat import WIN 

17from .exceptions import Abort 

18from .exceptions import UsageError 

19from .globals import resolve_color_default 

20from .types import Choice 

21from .types import convert_type 

22from .types import ParamType 

23from .utils import echo 

24from .utils import LazyFile 

25 

26if t.TYPE_CHECKING: 

27 from ._termui_impl import ProgressBar 

28 

29V = t.TypeVar("V") 

30 

31# The prompt functions to use. The doc tools currently override these 

32# functions to customize how they work. 

33visible_prompt_func: t.Callable[[str], str] = input 

34 

35_ansi_colors = { 

36 "black": 30, 

37 "red": 31, 

38 "green": 32, 

39 "yellow": 33, 

40 "blue": 34, 

41 "magenta": 35, 

42 "cyan": 36, 

43 "white": 37, 

44 "reset": 39, 

45 "bright_black": 90, 

46 "bright_red": 91, 

47 "bright_green": 92, 

48 "bright_yellow": 93, 

49 "bright_blue": 94, 

50 "bright_magenta": 95, 

51 "bright_cyan": 96, 

52 "bright_white": 97, 

53} 

54_ansi_reset_all = "\033[0m" 

55 

56 

57_HIDDEN_INPUT_MASK = "'***'" 

58 

59 

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

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

62 

63 Both ``repr(value)`` (the form built-in :class:`ParamType` errors use 

64 via ``{value!r}``) and the raw value are masked. The raw-value pass 

65 uses word-boundary lookarounds so a substring like ``"1"`` does not 

66 match inside ``"10"``, and ``"ent"`` does not match inside 

67 ``"Authentication"``. The empty string is skipped to avoid matching 

68 at every boundary. 

69 """ 

70 message = message.replace(repr(value), _HIDDEN_INPUT_MASK) 

71 if value: 

72 message = re.sub( 

73 rf"(?<!\w){re.escape(value)}(?!\w)", _HIDDEN_INPUT_MASK, message 

74 ) 

75 return message 

76 

77 

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

79 import getpass 

80 

81 return getpass.getpass(prompt) 

82 

83 

84def _readline_prompt(func: t.Callable[[str], str], text: str, err: bool) -> str: 

85 """Call a prompt function, passing the full prompt on non-Windows so 

86 readline can handle line editing and cursor positioning correctly. 

87 

88 On Windows the prompt is written separately via :func:`echo` for 

89 colorama support, with only the last character passed to *func*. 

90 """ 

91 if WIN: 

92 # Write the prompt separately so that we get nice coloring 

93 # through colorama on Windows. 

94 echo(text[:-1], nl=False, err=err) 

95 # Echo the last character to stdout to work around an issue 

96 # where readline causes backspace to clear the whole line. 

97 return func(text[-1:]) 

98 if err: 

99 with redirect_stdout(sys.stderr): 

100 return func(text) 

101 return func(text) 

102 

103 

104def _build_prompt( 

105 text: str, 

106 suffix: str, 

107 show_default: bool | str = False, 

108 default: t.Any | None = None, 

109 show_choices: bool = True, 

110 type: ParamType[t.Any] | None = None, 

111) -> str: 

112 prompt = text 

113 if type is not None and show_choices and isinstance(type, Choice): 

114 prompt += f" ({', '.join(map(str, type.choices))})" 

115 if isinstance(show_default, str): 

116 default = f"({show_default})" 

117 if default is not None and show_default: 

118 prompt = f"{prompt} [{_format_default(default)}]" 

119 return f"{prompt}{suffix}" 

120 

121 

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

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

124 return default.name 

125 

126 return default 

127 

128 

129def prompt( 

130 text: str, 

131 default: t.Any | None = None, 

132 hide_input: bool = False, 

133 confirmation_prompt: bool | str = False, 

134 type: ParamType[t.Any] | t.Any | None = None, 

135 value_proc: t.Callable[[str], t.Any] | None = None, 

136 prompt_suffix: str = ": ", 

137 show_default: bool | str = True, 

138 err: bool = False, 

139 show_choices: bool = True, 

140) -> t.Any: 

141 """Prompts a user for input. This is a convenience function that can 

142 be used to prompt a user for input later. 

143 

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

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

146 

147 :param text: the text to show for the prompt. 

148 :param default: the default value to use if no input happens. If this 

149 is not given it will prompt until it's aborted. 

150 :param hide_input: if this is set to true then the input value will 

151 be hidden. 

152 :param confirmation_prompt: Prompt a second time to confirm the 

153 value. Can be set to a string instead of ``True`` to customize 

154 the message. 

155 :param type: the type to use to check the value against. 

156 :param value_proc: if this parameter is provided it's a function that 

157 is invoked instead of the type conversion to 

158 convert a value. 

159 :param prompt_suffix: a suffix that should be added to the prompt. 

160 :param show_default: shows or hides the default value in the prompt. 

161 If this value is a string, it shows that string 

162 in parentheses instead of the actual value. 

163 :param err: if set to true the file defaults to ``stderr`` instead of 

164 ``stdout``, the same as with echo. 

165 :param show_choices: Show or hide choices if the passed type is a Choice. 

166 For example if type is a Choice of either day or week, 

167 show_choices is true and text is "Group by" then the 

168 prompt will be "Group by (day, week): ". 

169 

170 .. versionchanged:: 8.3.3 

171 ``show_default`` can be a string to show a custom value instead 

172 of the actual default, matching the help text behavior. 

173 

174 .. versionchanged:: 8.3.1 

175 A space is no longer appended to the prompt. 

176 

177 .. versionadded:: 8.0 

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

179 

180 .. versionadded:: 7.0 

181 Added the ``show_choices`` parameter. 

182 

183 .. versionadded:: 6.0 

184 Added unicode support for cmd.exe on Windows. 

185 

186 .. versionadded:: 4.0 

187 Added the `err` parameter. 

188 

189 """ 

190 

191 def prompt_func(text: str) -> str: 

192 f = hidden_prompt_func if hide_input else visible_prompt_func 

193 try: 

194 return _readline_prompt(f, text, err) 

195 except (KeyboardInterrupt, EOFError): 

196 # getpass doesn't print a newline if the user aborts input with ^C. 

197 # Allegedly this behavior is inherited from getpass(3). 

198 # A doc bug has been filed at https://bugs.python.org/issue24711 

199 if hide_input: 

200 echo(None, err=err) 

201 raise Abort() from None 

202 

203 if value_proc is None: 

204 value_proc = convert_type(type, default) 

205 

206 prompt = _build_prompt( 

207 text, prompt_suffix, show_default, default, show_choices, type 

208 ) 

209 

210 if confirmation_prompt: 

211 if confirmation_prompt is True: 

212 confirmation_prompt = _("Repeat for confirmation") 

213 

214 confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) 

215 

216 while True: 

217 while True: 

218 value = prompt_func(prompt) 

219 if value: 

220 break 

221 elif default is not None: 

222 value = default 

223 break 

224 try: 

225 result = value_proc(value) 

226 except UsageError as e: 

227 message = _mask_hidden_input(e.message, value) if hide_input else e.message 

228 echo(_("Error: {message}").format(message=message), err=err) 

229 continue 

230 if not confirmation_prompt: 

231 return result 

232 while True: 

233 value2 = prompt_func(confirmation_prompt) 

234 is_empty = not value and not value2 

235 if value2 or is_empty: 

236 break 

237 if value == value2: 

238 return result 

239 echo(_("Error: The two entered values do not match."), err=err) 

240 

241 

242def confirm( 

243 text: str, 

244 default: bool | None = False, 

245 abort: bool = False, 

246 prompt_suffix: str = ": ", 

247 show_default: bool = True, 

248 err: bool = False, 

249) -> bool: 

250 """Prompts for confirmation (yes/no question). 

251 

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

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

254 

255 :param text: the question to ask. 

256 :param default: The default value to use when no input is given. If 

257 ``None``, repeat until input is given. 

258 :param abort: if this is set to `True` a negative answer aborts the 

259 exception by raising :exc:`Abort`. 

260 :param prompt_suffix: a suffix that should be added to the prompt. 

261 :param show_default: shows or hides the default value in the prompt. 

262 :param err: if set to true the file defaults to ``stderr`` instead of 

263 ``stdout``, the same as with echo. 

264 

265 .. versionchanged:: 8.3.1 

266 A space is no longer appended to the prompt. 

267 

268 .. versionchanged:: 8.0 

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

270 

271 .. versionadded:: 4.0 

272 Added the ``err`` parameter. 

273 """ 

274 prompt = _build_prompt( 

275 text, 

276 prompt_suffix, 

277 show_default, 

278 "y/n" if default is None else ("Y/n" if default else "y/N"), 

279 ) 

280 

281 while True: 

282 try: 

283 value = _readline_prompt(visible_prompt_func, prompt, err).lower().strip() 

284 except (KeyboardInterrupt, EOFError): 

285 raise Abort() from None 

286 if value in ("y", "yes"): 

287 rv = True 

288 elif value in ("n", "no"): 

289 rv = False 

290 elif default is not None and value == "": 

291 rv = default 

292 else: 

293 echo(_("Error: invalid input"), err=err) 

294 continue 

295 break 

296 if abort and not rv: 

297 raise Abort() 

298 return rv 

299 

300 

301def get_pager_file( 

302 color: bool | None = None, 

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

304 """Context manager. 

305 

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

307 

308 .. versionadded:: 8.4.0 

309 

310 :param color: controls if the pager supports ANSI colors or not. The 

311 default is autodetection. 

312 """ 

313 from ._termui_impl import get_pager_file 

314 

315 color = resolve_color_default(color) 

316 

317 return get_pager_file(color=color) 

318 

319 

320def echo_via_pager( 

321 text_or_generator: cabc.Iterable[str] | t.Callable[[], cabc.Iterable[str]] | str, 

322 color: bool | None = None, 

323) -> None: 

324 """This function takes a text and shows it via an environment specific 

325 pager on stdout. 

326 

327 .. versionchanged:: 3.0 

328 Added the `color` flag. 

329 

330 :param text_or_generator: the text to page, or alternatively, a 

331 generator emitting the text to page. 

332 :param color: controls if the pager supports ANSI colors or not. The 

333 default is autodetection. 

334 """ 

335 

336 if inspect.isgeneratorfunction(text_or_generator): 

337 i = t.cast("t.Callable[[], cabc.Iterable[str]]", text_or_generator)() 

338 elif isinstance(text_or_generator, str): 

339 i = [text_or_generator] 

340 else: 

341 i = iter(t.cast("cabc.Iterable[str]", text_or_generator)) 

342 

343 # convert every element of i to a text type if necessary 

344 text_generator = (el if isinstance(el, str) else str(el) for el in i) 

345 

346 with get_pager_file(color=color) as pager: 

347 for text in itertools.chain(text_generator, "\n"): 

348 pager.write(text) 

349 # Flush after each write so a slow generator streams to the pager 

350 # incrementally rather than staying invisible until the pipe buffer 

351 # fills (~8 KB). 

352 pager.flush() 

353 

354 

355@t.overload 

356def progressbar( 

357 *, 

358 length: int, 

359 label: str | None = None, 

360 hidden: bool = False, 

361 show_eta: bool = True, 

362 show_percent: bool | None = None, 

363 show_pos: bool = False, 

364 fill_char: str = "#", 

365 empty_char: str = "-", 

366 bar_template: str = "%(label)s [%(bar)s] %(info)s", 

367 info_sep: str = " ", 

368 width: int = 36, 

369 file: t.TextIO | None = None, 

370 color: bool | None = None, 

371 update_min_steps: int = 1, 

372) -> ProgressBar[int]: ... 

373 

374 

375@t.overload 

376def progressbar( 

377 iterable: cabc.Iterable[V] | None = None, 

378 length: int | None = None, 

379 label: str | None = None, 

380 hidden: bool = False, 

381 show_eta: bool = True, 

382 show_percent: bool | None = None, 

383 show_pos: bool = False, 

384 item_show_func: t.Callable[[V | None], str | None] | None = None, 

385 fill_char: str = "#", 

386 empty_char: str = "-", 

387 bar_template: str = "%(label)s [%(bar)s] %(info)s", 

388 info_sep: str = " ", 

389 width: int = 36, 

390 file: t.TextIO | None = None, 

391 color: bool | None = None, 

392 update_min_steps: int = 1, 

393) -> ProgressBar[V]: ... 

394 

395 

396def progressbar( 

397 iterable: cabc.Iterable[V] | None = None, 

398 length: int | None = None, 

399 label: str | None = None, 

400 hidden: bool = False, 

401 show_eta: bool = True, 

402 show_percent: bool | None = None, 

403 show_pos: bool = False, 

404 item_show_func: t.Callable[[V | None], str | None] | None = None, 

405 fill_char: str = "#", 

406 empty_char: str = "-", 

407 bar_template: str = "%(label)s [%(bar)s] %(info)s", 

408 info_sep: str = " ", 

409 width: int = 36, 

410 file: t.TextIO | None = None, 

411 color: bool | None = None, 

412 update_min_steps: int = 1, 

413) -> ProgressBar[V]: 

414 """This function creates an iterable context manager that can be used 

415 to iterate over something while showing a progress bar. It will 

416 either iterate over the `iterable` or `length` items (that are counted 

417 up). While iteration happens, this function will print a rendered 

418 progress bar to the given `file` (defaults to stdout) and will attempt 

419 to calculate remaining time and more. By default, this progress bar 

420 will not be rendered if the file is not a terminal. 

421 

422 The context manager creates the progress bar. When the context 

423 manager is entered the progress bar is already created. With every 

424 iteration over the progress bar, the iterable passed to the bar is 

425 advanced and the bar is updated. When the context manager exits, 

426 a newline is printed and the progress bar is finalized on screen. 

427 

428 Note: The progress bar is currently designed for use cases where the 

429 total progress can be expected to take at least several seconds. 

430 Because of this, the ProgressBar class object won't display 

431 progress that is considered too fast, and progress where the time 

432 between steps is less than a second. 

433 

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

435 destroyed. 

436 

437 Example usage:: 

438 

439 with progressbar(items) as bar: 

440 for item in bar: 

441 do_something_with(item) 

442 

443 Alternatively, if no iterable is specified, one can manually update the 

444 progress bar through the `update()` method instead of directly 

445 iterating over the progress bar. The update method accepts the number 

446 of steps to increment the bar with:: 

447 

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

449 for chunk in chunks: 

450 process_chunk(chunk) 

451 bar.update(chunks.bytes) 

452 

453 The ``update()`` method also takes an optional value specifying the 

454 ``current_item`` at the new position. This is useful when used 

455 together with ``item_show_func`` to customize the output for each 

456 manual step:: 

457 

458 with click.progressbar( 

459 length=total_size, 

460 label='Unzipping archive', 

461 item_show_func=lambda a: a.filename 

462 ) as bar: 

463 for archive in zip_file: 

464 archive.extract() 

465 bar.update(archive.size, archive) 

466 

467 :param iterable: an iterable to iterate over. If not provided the length 

468 is required. 

469 :param length: the number of items to iterate over. By default the 

470 progressbar will attempt to ask the iterator about its 

471 length, which might or might not work. If an iterable is 

472 also provided this parameter can be used to override the 

473 length. If an iterable is not provided the progress bar 

474 will iterate over a range of that length. 

475 :param label: the label to show next to the progress bar. 

476 :param hidden: hide the progressbar. Defaults to ``False``. When no tty is 

477 detected, it will only print the progressbar label. Setting this to 

478 ``False`` also disables that. 

479 :param show_eta: enables or disables the estimated time display. This is 

480 automatically disabled if the length cannot be 

481 determined. 

482 :param show_percent: enables or disables the percentage display. The 

483 default is `True` if the iterable has a length or 

484 `False` if not. 

485 :param show_pos: enables or disables the absolute position display. The 

486 default is `False`. 

487 :param item_show_func: A function called with the current item which 

488 can return a string to show next to the progress bar. If the 

489 function returns ``None`` nothing is shown. The current item can 

490 be ``None``, such as when entering and exiting the bar. 

491 :param fill_char: the character to use to show the filled part of the 

492 progress bar. 

493 :param empty_char: the character to use to show the non-filled part of 

494 the progress bar. 

495 :param bar_template: the format string to use as template for the bar. 

496 The parameters in it are ``label`` for the label, 

497 ``bar`` for the progress bar and ``info`` for the 

498 info section. 

499 :param info_sep: the separator between multiple info items (eta etc.) 

500 :param width: the width of the progress bar in characters, 0 means full 

501 terminal width 

502 :param file: The file to write to. If this is not a terminal then 

503 only the label is printed. 

504 :param color: controls if the terminal supports ANSI colors or not. The 

505 default is autodetection. This is only needed if ANSI 

506 codes are included anywhere in the progress bar output 

507 which is not the case by default. 

508 :param update_min_steps: Render only when this many updates have 

509 completed. This allows tuning for very fast iterators. 

510 

511 .. versionadded:: 8.2 

512 The ``hidden`` argument. 

513 

514 .. versionchanged:: 8.0 

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

516 

517 .. versionchanged:: 8.0 

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

519 

520 .. versionchanged:: 8.0 

521 Labels are echoed if the output is not a TTY. Reverts a change 

522 in 7.0 that removed all output. 

523 

524 .. versionadded:: 8.0 

525 The ``update_min_steps`` parameter. 

526 

527 .. versionadded:: 4.0 

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

529 

530 .. versionadded:: 2.0 

531 """ 

532 from ._termui_impl import ProgressBar 

533 

534 color = resolve_color_default(color) 

535 return ProgressBar( 

536 iterable=iterable, 

537 length=length, 

538 hidden=hidden, 

539 show_eta=show_eta, 

540 show_percent=show_percent, 

541 show_pos=show_pos, 

542 item_show_func=item_show_func, 

543 fill_char=fill_char, 

544 empty_char=empty_char, 

545 bar_template=bar_template, 

546 info_sep=info_sep, 

547 file=file, 

548 label=label, 

549 width=width, 

550 color=color, 

551 update_min_steps=update_min_steps, 

552 ) 

553 

554 

555def clear() -> None: 

556 """Clears the terminal screen. This will have the effect of clearing 

557 the whole visible space of the terminal and moving the cursor to the 

558 top left. This does not do anything if not connected to a terminal. 

559 

560 .. versionadded:: 2.0 

561 """ 

562 if not isatty(sys.stdout): 

563 return 

564 

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

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

567 

568 

569def _interpret_color(color: int | tuple[int, int, int] | str, offset: int = 0) -> str: 

570 if isinstance(color, int): 

571 return f"{38 + offset};5;{color:d}" 

572 

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

574 r, g, b = color 

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

576 

577 return str(_ansi_colors[color] + offset) 

578 

579 

580def style( 

581 text: t.Any, 

582 fg: int | tuple[int, int, int] | str | None = None, 

583 bg: int | tuple[int, int, int] | str | None = None, 

584 bold: bool | None = None, 

585 dim: bool | None = None, 

586 underline: bool | None = None, 

587 overline: bool | None = None, 

588 italic: bool | None = None, 

589 blink: bool | None = None, 

590 reverse: bool | None = None, 

591 strikethrough: bool | None = None, 

592 reset: bool = True, 

593) -> str: 

594 """Styles a text with ANSI styles and returns the new string. By 

595 default the styling is self contained which means that at the end 

596 of the string a reset code is issued. This can be prevented by 

597 passing ``reset=False``. 

598 

599 Examples:: 

600 

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

602 click.echo(click.style('ATTENTION!', blink=True)) 

603 click.echo(click.style('Some things', reverse=True, fg='cyan')) 

604 click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) 

605 

606 Supported color names: 

607 

608 * ``black`` (might be a gray) 

609 * ``red`` 

610 * ``green`` 

611 * ``yellow`` (might be an orange) 

612 * ``blue`` 

613 * ``magenta`` 

614 * ``cyan`` 

615 * ``white`` (might be light gray) 

616 * ``bright_black`` 

617 * ``bright_red`` 

618 * ``bright_green`` 

619 * ``bright_yellow`` 

620 * ``bright_blue`` 

621 * ``bright_magenta`` 

622 * ``bright_cyan`` 

623 * ``bright_white`` 

624 * ``reset`` (reset the color code only) 

625 

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

627 

628 - An integer in the interval [0, 255]. The terminal must support 

629 8-bit/256-color mode. 

630 - An RGB tuple of three integers in [0, 255]. The terminal must 

631 support 24-bit/true-color mode. 

632 

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

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

635 

636 :param text: the string to style with ansi codes. 

637 :param fg: if provided this will become the foreground color. 

638 :param bg: if provided this will become the background color. 

639 :param bold: if provided this will enable or disable bold mode. 

640 :param dim: if provided this will enable or disable dim mode. This is 

641 badly supported. 

642 :param underline: if provided this will enable or disable underline. 

643 :param overline: if provided this will enable or disable overline. 

644 :param italic: if provided this will enable or disable italic. 

645 :param blink: if provided this will enable or disable blinking. 

646 :param reverse: if provided this will enable or disable inverse 

647 rendering (foreground becomes background and the 

648 other way round). 

649 :param strikethrough: if provided this will enable or disable 

650 striking through text. 

651 :param reset: by default a reset-all code is added at the end of the 

652 string which means that styles do not carry over. This 

653 can be disabled to compose styles. 

654 

655 .. versionchanged:: 8.0 

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

657 

658 .. versionchanged:: 8.0 

659 Added support for 256 and RGB color codes. 

660 

661 .. versionchanged:: 8.0 

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

663 parameters. 

664 

665 .. versionchanged:: 7.0 

666 Added support for bright colors. 

667 

668 .. versionadded:: 2.0 

669 """ 

670 if not isinstance(text, str): 

671 text = str(text) 

672 

673 bits = [] 

674 

675 if fg: 

676 try: 

677 bits.append(f"\033[{_interpret_color(fg)}m") 

678 except KeyError: 

679 raise TypeError(_("Unknown color {colour!r}").format(colour=fg)) from None 

680 

681 if bg: 

682 try: 

683 bits.append(f"\033[{_interpret_color(bg, 10)}m") 

684 except KeyError: 

685 raise TypeError(_("Unknown color {colour!r}").format(colour=bg)) from None 

686 

687 if bold is not None: 

688 bits.append(f"\033[{1 if bold else 22}m") 

689 if dim is not None: 

690 bits.append(f"\033[{2 if dim else 22}m") 

691 if underline is not None: 

692 bits.append(f"\033[{4 if underline else 24}m") 

693 if overline is not None: 

694 bits.append(f"\033[{53 if overline else 55}m") 

695 if italic is not None: 

696 bits.append(f"\033[{3 if italic else 23}m") 

697 if blink is not None: 

698 bits.append(f"\033[{5 if blink else 25}m") 

699 if reverse is not None: 

700 bits.append(f"\033[{7 if reverse else 27}m") 

701 if strikethrough is not None: 

702 bits.append(f"\033[{9 if strikethrough else 29}m") 

703 bits.append(text) 

704 if reset: 

705 bits.append(_ansi_reset_all) 

706 return "".join(bits) 

707 

708 

709def unstyle(text: str) -> str: 

710 """Removes ANSI styling information from a string. Usually it's not 

711 necessary to use this function as Click's echo function will 

712 automatically remove styling if necessary. 

713 

714 .. versionadded:: 2.0 

715 

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

717 """ 

718 return strip_ansi(text) 

719 

720 

721def secho( 

722 message: t.Any | None = None, 

723 file: t.IO[t.AnyStr] | None = None, 

724 nl: bool = True, 

725 err: bool = False, 

726 color: bool | None = None, 

727 **styles: t.Any, 

728) -> None: 

729 """This function combines :func:`echo` and :func:`style` into one 

730 call. As such the following two calls are the same:: 

731 

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

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

734 

735 All keyword arguments are forwarded to the underlying functions 

736 depending on which one they go with. 

737 

738 Non-string types will be converted to :class:`str`. However, 

739 :class:`bytes` are passed directly to :meth:`echo` without applying 

740 style. If you want to style bytes that represent text, call 

741 :meth:`bytes.decode` first. 

742 

743 .. versionchanged:: 8.0 

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

745 passed through without style applied. 

746 

747 .. versionadded:: 2.0 

748 """ 

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

750 message = style(message, **styles) 

751 

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

753 

754 

755@t.overload 

756def edit( 

757 text: bytes | bytearray, 

758 editor: str | None = None, 

759 env: cabc.Mapping[str, str] | None = None, 

760 require_save: bool = False, 

761 extension: str = ".txt", 

762) -> bytes | None: ... 

763 

764 

765@t.overload 

766def edit( 

767 text: str, 

768 editor: str | None = None, 

769 env: cabc.Mapping[str, str] | None = None, 

770 require_save: bool = True, 

771 extension: str = ".txt", 

772) -> str | None: ... 

773 

774 

775@t.overload 

776def edit( 

777 text: None = None, 

778 editor: str | None = None, 

779 env: cabc.Mapping[str, str] | None = None, 

780 require_save: bool = True, 

781 extension: str = ".txt", 

782 filename: str | cabc.Iterable[str] | None = None, 

783) -> None: ... 

784 

785 

786def edit( 

787 text: str | bytes | bytearray | None = None, 

788 editor: str | None = None, 

789 env: cabc.Mapping[str, str] | None = None, 

790 require_save: bool = True, 

791 extension: str = ".txt", 

792 filename: str | cabc.Iterable[str] | None = None, 

793) -> str | bytes | bytearray | None: 

794 r"""Edits the given text in the defined editor. If an editor is given 

795 (should be the full path to the executable but the regular operating 

796 system search path is used for finding the executable) it overrides 

797 the detected editor. Optionally, some environment variables can be 

798 used. If the editor is closed without changes, `None` is returned. In 

799 case a file is edited directly the return value is always `None` and 

800 `require_save` and `extension` are ignored. 

801 

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

803 

804 Note for Windows: to simplify cross-platform usage, the newlines are 

805 automatically converted from POSIX to Windows and vice versa. As such, 

806 the message here will have ``\n`` as newline markers. 

807 

808 :param text: the text to edit. 

809 :param editor: optionally the editor to use. Defaults to automatic 

810 detection. 

811 :param env: environment variables to forward to the editor. 

812 :param require_save: if this is true, then not saving in the editor 

813 will make the return value become `None`. 

814 :param extension: the extension to tell the editor about. This defaults 

815 to `.txt` but changing this might change syntax 

816 highlighting. 

817 :param filename: if provided it will edit this file instead of the 

818 provided text contents. It will not use a temporary 

819 file as an indirection in that case. If the editor supports 

820 editing multiple files at once, a sequence of files may be 

821 passed as well. Invoke `click.file` once per file instead 

822 if multiple files cannot be managed at once or editing the 

823 files serially is desired. 

824 

825 .. versionchanged:: 8.2.0 

826 ``filename`` now accepts any ``Iterable[str]`` in addition to a ``str`` 

827 if the ``editor`` supports editing multiple files at once. 

828 

829 """ 

830 from ._termui_impl import Editor 

831 

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

833 

834 if filename is None: 

835 return ed.edit(text) 

836 

837 if isinstance(filename, str): 

838 filename = (filename,) 

839 

840 ed.edit_files(filenames=filename) 

841 return None 

842 

843 

844def launch(url: str, wait: bool = False, locate: bool = False) -> int: 

845 """This function launches the given URL (or filename) in the default 

846 viewer application for this file type. If this is an executable, it 

847 might launch the executable in a new session. The return value is 

848 the exit code of the launched application. Usually, ``0`` indicates 

849 success. 

850 

851 Examples:: 

852 

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

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

855 

856 .. versionadded:: 2.0 

857 

858 :param url: URL or filename of the thing to launch. 

859 :param wait: Wait for the program to exit before returning. This 

860 only works if the launched program blocks. In particular, 

861 ``xdg-open`` on Linux does not block. 

862 :param locate: if this is set to `True` then instead of launching the 

863 application associated with the URL it will attempt to 

864 launch a file manager with the file located. This 

865 might have weird effects if the URL does not point to 

866 the filesystem. 

867 """ 

868 from ._termui_impl import open_url 

869 

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

871 

872 

873# If this is provided, getchar() calls into this instead. This is used 

874# for unittesting purposes. 

875_getchar: t.Callable[[bool], str] | None = None 

876 

877 

878def getchar(echo: bool = False) -> str: 

879 """Fetches a single character from the terminal and returns it. This 

880 will always return a unicode character and under certain rare 

881 circumstances this might return more than one character. The 

882 situations which more than one character is returned is when for 

883 whatever reason multiple characters end up in the terminal buffer or 

884 standard input was not actually a terminal. 

885 

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

887 is piped into the standard input. 

888 

889 Note for Windows: in rare cases when typing non-ASCII characters, this 

890 function might wait for a second character and then return both at once. 

891 This is because certain Unicode characters look like special-key markers. 

892 

893 .. versionadded:: 2.0 

894 

895 :param echo: if set to `True`, the character read will also show up on 

896 the terminal. The default is to not show it. 

897 """ 

898 global _getchar 

899 

900 if _getchar is None: 

901 from ._termui_impl import getchar as f 

902 

903 _getchar = f 

904 

905 return _getchar(echo) 

906 

907 

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

909 from ._termui_impl import raw_terminal as f 

910 

911 return f() 

912 

913 

914def pause(info: str | None = None, err: bool = False) -> None: 

915 """This command stops execution and waits for the user to press any 

916 key to continue. This is similar to the Windows batch "pause" 

917 command. If the program is not run through a terminal, this command 

918 will instead do nothing. 

919 

920 .. versionadded:: 2.0 

921 

922 .. versionadded:: 4.0 

923 Added the `err` parameter. 

924 

925 :param info: The message to print before pausing. Defaults to 

926 ``"Press any key to continue..."``. 

927 :param err: if set to message goes to ``stderr`` instead of 

928 ``stdout``, the same as with echo. 

929 """ 

930 if not isatty(sys.stdin) or not isatty(sys.stdout): 

931 return 

932 

933 if info is None: 

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

935 

936 try: 

937 if info: 

938 echo(info, nl=False, err=err) 

939 try: 

940 getchar() 

941 except (KeyboardInterrupt, EOFError): 

942 pass 

943 finally: 

944 if info: 

945 echo(err=err)