Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/click/termui.py: 22%

195 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-09 06:03 +0000

1from __future__ import annotations 

2 

3import collections.abc as cabc 

4import inspect 

5import io 

6import itertools 

7import sys 

8import typing as t 

9from contextlib import AbstractContextManager 

10from gettext import gettext as _ 

11 

12from ._compat import isatty 

13from ._compat import strip_ansi 

14from .exceptions import Abort 

15from .exceptions import UsageError 

16from .globals import resolve_color_default 

17from .types import Choice 

18from .types import convert_type 

19from .types import ParamType 

20from .utils import echo 

21from .utils import LazyFile 

22 

23if t.TYPE_CHECKING: 

24 from ._termui_impl import ProgressBar 

25 

26V = t.TypeVar("V") 

27 

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

29# functions to customize how they work. 

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

31 

32_ansi_colors = { 

33 "black": 30, 

34 "red": 31, 

35 "green": 32, 

36 "yellow": 33, 

37 "blue": 34, 

38 "magenta": 35, 

39 "cyan": 36, 

40 "white": 37, 

41 "reset": 39, 

42 "bright_black": 90, 

43 "bright_red": 91, 

44 "bright_green": 92, 

45 "bright_yellow": 93, 

46 "bright_blue": 94, 

47 "bright_magenta": 95, 

48 "bright_cyan": 96, 

49 "bright_white": 97, 

50} 

51_ansi_reset_all = "\033[0m" 

52 

53 

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

55 import getpass 

56 

57 return getpass.getpass(prompt) 

58 

59 

60def _build_prompt( 

61 text: str, 

62 suffix: str, 

63 show_default: bool = False, 

64 default: t.Any | None = None, 

65 show_choices: bool = True, 

66 type: ParamType | None = None, 

67) -> str: 

68 prompt = text 

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

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

71 if default is not None and show_default: 

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

73 return f"{prompt}{suffix}" 

74 

75 

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

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

78 return default.name 

79 

80 return default 

81 

82 

83def prompt( 

84 text: str, 

85 default: t.Any | None = None, 

86 hide_input: bool = False, 

87 confirmation_prompt: bool | str = False, 

88 type: ParamType | t.Any | None = None, 

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

90 prompt_suffix: str = ": ", 

91 show_default: bool = True, 

92 err: bool = False, 

93 show_choices: bool = True, 

94) -> t.Any: 

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

96 be used to prompt a user for input later. 

97 

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

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

100 

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

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

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

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

105 be hidden. 

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

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

108 the message. 

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

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

111 is invoked instead of the type conversion to 

112 convert a value. 

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

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

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

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

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

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

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

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

121 

122 .. versionadded:: 8.0 

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

124 

125 .. versionadded:: 7.0 

126 Added the ``show_choices`` parameter. 

127 

128 .. versionadded:: 6.0 

129 Added unicode support for cmd.exe on Windows. 

130 

131 .. versionadded:: 4.0 

132 Added the `err` parameter. 

133 

134 """ 

135 

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

137 f = hidden_prompt_func if hide_input else visible_prompt_func 

138 try: 

139 # Write the prompt separately so that we get nice 

140 # coloring through colorama on Windows 

141 echo(text.rstrip(" "), nl=False, err=err) 

142 # Echo a space to stdout to work around an issue where 

143 # readline causes backspace to clear the whole line. 

144 return f(" ") 

145 except (KeyboardInterrupt, EOFError): 

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

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

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

149 if hide_input: 

150 echo(None, err=err) 

151 raise Abort() from None 

152 

153 if value_proc is None: 

154 value_proc = convert_type(type, default) 

155 

156 prompt = _build_prompt( 

157 text, prompt_suffix, show_default, default, show_choices, type 

158 ) 

159 

160 if confirmation_prompt: 

161 if confirmation_prompt is True: 

162 confirmation_prompt = _("Repeat for confirmation") 

163 

164 confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) 

165 

166 while True: 

167 while True: 

168 value = prompt_func(prompt) 

169 if value: 

170 break 

171 elif default is not None: 

172 value = default 

173 break 

174 try: 

175 result = value_proc(value) 

176 except UsageError as e: 

177 if hide_input: 

178 echo(_("Error: The value you entered was invalid."), err=err) 

179 else: 

180 echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306 

181 continue 

182 if not confirmation_prompt: 

183 return result 

184 while True: 

185 value2 = prompt_func(confirmation_prompt) 

186 is_empty = not value and not value2 

187 if value2 or is_empty: 

188 break 

189 if value == value2: 

190 return result 

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

192 

193 

194def confirm( 

195 text: str, 

196 default: bool | None = False, 

197 abort: bool = False, 

198 prompt_suffix: str = ": ", 

199 show_default: bool = True, 

200 err: bool = False, 

201) -> bool: 

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

203 

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

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

206 

207 :param text: the question to ask. 

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

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

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

211 exception by raising :exc:`Abort`. 

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

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

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

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

216 

217 .. versionchanged:: 8.0 

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

219 

220 .. versionadded:: 4.0 

221 Added the ``err`` parameter. 

222 """ 

223 prompt = _build_prompt( 

224 text, 

225 prompt_suffix, 

226 show_default, 

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

228 ) 

229 

230 while True: 

231 try: 

232 # Write the prompt separately so that we get nice 

233 # coloring through colorama on Windows 

234 echo(prompt.rstrip(" "), nl=False, err=err) 

235 # Echo a space to stdout to work around an issue where 

236 # readline causes backspace to clear the whole line. 

237 value = visible_prompt_func(" ").lower().strip() 

238 except (KeyboardInterrupt, EOFError): 

239 raise Abort() from None 

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

241 rv = True 

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

243 rv = False 

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

245 rv = default 

246 else: 

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

248 continue 

249 break 

250 if abort and not rv: 

251 raise Abort() 

252 return rv 

253 

254 

255def echo_via_pager( 

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

257 color: bool | None = None, 

258) -> None: 

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

260 pager on stdout. 

261 

262 .. versionchanged:: 3.0 

263 Added the `color` flag. 

264 

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

266 generator emitting the text to page. 

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

268 default is autodetection. 

269 """ 

270 color = resolve_color_default(color) 

271 

272 if inspect.isgeneratorfunction(text_or_generator): 

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

274 elif isinstance(text_or_generator, str): 

275 i = [text_or_generator] 

276 else: 

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

278 

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

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

281 

282 from ._termui_impl import pager 

283 

284 return pager(itertools.chain(text_generator, "\n"), color) 

285 

286 

287def progressbar( 

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

289 length: int | None = None, 

290 label: str | None = None, 

291 show_eta: bool = True, 

292 show_percent: bool | None = None, 

293 show_pos: bool = False, 

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

295 fill_char: str = "#", 

296 empty_char: str = "-", 

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

298 info_sep: str = " ", 

299 width: int = 36, 

300 file: t.TextIO | None = None, 

301 color: bool | None = None, 

302 update_min_steps: int = 1, 

303) -> ProgressBar[V]: 

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

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

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

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

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

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

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

311 

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

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

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

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

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

317 

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

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

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

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

322 between steps is less than a second. 

323 

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

325 destroyed. 

326 

327 Example usage:: 

328 

329 with progressbar(items) as bar: 

330 for item in bar: 

331 do_something_with(item) 

332 

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

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

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

336 of steps to increment the bar with:: 

337 

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

339 for chunk in chunks: 

340 process_chunk(chunk) 

341 bar.update(chunks.bytes) 

342 

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

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

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

346 manual step:: 

347 

348 with click.progressbar( 

349 length=total_size, 

350 label='Unzipping archive', 

351 item_show_func=lambda a: a.filename 

352 ) as bar: 

353 for archive in zip_file: 

354 archive.extract() 

355 bar.update(archive.size, archive) 

356 

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

358 is required. 

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

360 progressbar will attempt to ask the iterator about its 

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

362 also provided this parameter can be used to override the 

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

364 will iterate over a range of that length. 

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

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

367 automatically disabled if the length cannot be 

368 determined. 

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

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

371 `False` if not. 

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

373 default is `False`. 

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

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

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

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

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

379 progress bar. 

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

381 the progress bar. 

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

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

384 ``bar`` for the progress bar and ``info`` for the 

385 info section. 

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

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

388 terminal width 

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

390 only the label is printed. 

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

392 default is autodetection. This is only needed if ANSI 

393 codes are included anywhere in the progress bar output 

394 which is not the case by default. 

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

396 completed. This allows tuning for very fast iterators. 

397 

398 .. versionchanged:: 8.0 

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

400 

401 .. versionchanged:: 8.0 

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

403 

404 .. versionchanged:: 8.0 

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

406 in 7.0 that removed all output. 

407 

408 .. versionadded:: 8.0 

409 Added the ``update_min_steps`` parameter. 

410 

411 .. versionchanged:: 4.0 

412 Added the ``color`` parameter. Added the ``update`` method to 

413 the object. 

414 

415 .. versionadded:: 2.0 

416 """ 

417 from ._termui_impl import ProgressBar 

418 

419 color = resolve_color_default(color) 

420 return ProgressBar( 

421 iterable=iterable, 

422 length=length, 

423 show_eta=show_eta, 

424 show_percent=show_percent, 

425 show_pos=show_pos, 

426 item_show_func=item_show_func, 

427 fill_char=fill_char, 

428 empty_char=empty_char, 

429 bar_template=bar_template, 

430 info_sep=info_sep, 

431 file=file, 

432 label=label, 

433 width=width, 

434 color=color, 

435 update_min_steps=update_min_steps, 

436 ) 

437 

438 

439def clear() -> None: 

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

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

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

443 

444 .. versionadded:: 2.0 

445 """ 

446 if not isatty(sys.stdout): 

447 return 

448 

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

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

451 

452 

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

454 if isinstance(color, int): 

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

456 

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

458 r, g, b = color 

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

460 

461 return str(_ansi_colors[color] + offset) 

462 

463 

464def style( 

465 text: t.Any, 

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

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

468 bold: bool | None = None, 

469 dim: bool | None = None, 

470 underline: bool | None = None, 

471 overline: bool | None = None, 

472 italic: bool | None = None, 

473 blink: bool | None = None, 

474 reverse: bool | None = None, 

475 strikethrough: bool | None = None, 

476 reset: bool = True, 

477) -> str: 

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

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

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

481 passing ``reset=False``. 

482 

483 Examples:: 

484 

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

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

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

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

489 

490 Supported color names: 

491 

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

493 * ``red`` 

494 * ``green`` 

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

496 * ``blue`` 

497 * ``magenta`` 

498 * ``cyan`` 

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

500 * ``bright_black`` 

501 * ``bright_red`` 

502 * ``bright_green`` 

503 * ``bright_yellow`` 

504 * ``bright_blue`` 

505 * ``bright_magenta`` 

506 * ``bright_cyan`` 

507 * ``bright_white`` 

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

509 

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

511 

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

513 8-bit/256-color mode. 

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

515 support 24-bit/true-color mode. 

516 

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

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

519 

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

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

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

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

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

525 badly supported. 

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

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

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

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

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

531 rendering (foreground becomes background and the 

532 other way round). 

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

534 striking through text. 

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

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

537 can be disabled to compose styles. 

538 

539 .. versionchanged:: 8.0 

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

541 

542 .. versionchanged:: 8.0 

543 Added support for 256 and RGB color codes. 

544 

545 .. versionchanged:: 8.0 

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

547 parameters. 

548 

549 .. versionchanged:: 7.0 

550 Added support for bright colors. 

551 

552 .. versionadded:: 2.0 

553 """ 

554 if not isinstance(text, str): 

555 text = str(text) 

556 

557 bits = [] 

558 

559 if fg: 

560 try: 

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

562 except KeyError: 

563 raise TypeError(f"Unknown color {fg!r}") from None 

564 

565 if bg: 

566 try: 

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

568 except KeyError: 

569 raise TypeError(f"Unknown color {bg!r}") from None 

570 

571 if bold is not None: 

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

573 if dim is not None: 

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

575 if underline is not None: 

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

577 if overline is not None: 

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

579 if italic is not None: 

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

581 if blink is not None: 

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

583 if reverse is not None: 

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

585 if strikethrough is not None: 

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

587 bits.append(text) 

588 if reset: 

589 bits.append(_ansi_reset_all) 

590 return "".join(bits) 

591 

592 

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

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

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

596 automatically remove styling if necessary. 

597 

598 .. versionadded:: 2.0 

599 

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

601 """ 

602 return strip_ansi(text) 

603 

604 

605def secho( 

606 message: t.Any | None = None, 

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

608 nl: bool = True, 

609 err: bool = False, 

610 color: bool | None = None, 

611 **styles: t.Any, 

612) -> None: 

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

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

615 

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

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

618 

619 All keyword arguments are forwarded to the underlying functions 

620 depending on which one they go with. 

621 

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

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

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

625 :meth:`bytes.decode` first. 

626 

627 .. versionchanged:: 8.0 

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

629 passed through without style applied. 

630 

631 .. versionadded:: 2.0 

632 """ 

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

634 message = style(message, **styles) 

635 

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

637 

638 

639def edit( 

640 text: t.AnyStr | None = None, 

641 editor: str | None = None, 

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

643 require_save: bool = True, 

644 extension: str = ".txt", 

645 filename: str | None = None, 

646) -> t.AnyStr | None: 

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

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

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

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

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

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

653 `require_save` and `extension` are ignored. 

654 

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

656 

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

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

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

660 

661 :param text: the text to edit. 

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

663 detection. 

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

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

666 will make the return value become `None`. 

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

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

669 highlighting. 

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

671 provided text contents. It will not use a temporary 

672 file as an indirection in that case. 

673 """ 

674 from ._termui_impl import Editor 

675 

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

677 

678 if filename is None: 

679 return ed.edit(text) 

680 

681 ed.edit_file(filename) 

682 return None 

683 

684 

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

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

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

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

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

690 success. 

691 

692 Examples:: 

693 

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

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

696 

697 .. versionadded:: 2.0 

698 

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

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

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

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

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

704 application associated with the URL it will attempt to 

705 launch a file manager with the file located. This 

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

707 the filesystem. 

708 """ 

709 from ._termui_impl import open_url 

710 

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

712 

713 

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

715# for unittesting purposes. 

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

717 

718 

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

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

721 will always return a unicode character and under certain rare 

722 circumstances this might return more than one character. The 

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

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

725 standard input was not actually a terminal. 

726 

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

728 is piped into the standard input. 

729 

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

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

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

733 

734 .. versionadded:: 2.0 

735 

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

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

738 """ 

739 global _getchar 

740 

741 if _getchar is None: 

742 from ._termui_impl import getchar as f 

743 

744 _getchar = f 

745 

746 return _getchar(echo) 

747 

748 

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

750 from ._termui_impl import raw_terminal as f 

751 

752 return f() 

753 

754 

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

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

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

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

759 will instead do nothing. 

760 

761 .. versionadded:: 2.0 

762 

763 .. versionadded:: 4.0 

764 Added the `err` parameter. 

765 

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

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

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

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

770 """ 

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

772 return 

773 

774 if info is None: 

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

776 

777 try: 

778 if info: 

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

780 try: 

781 getchar() 

782 except (KeyboardInterrupt, EOFError): 

783 pass 

784 finally: 

785 if info: 

786 echo(err=err)