Coverage for typer/core.py: 100%

275 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-04-14 00:18 +0000

1import errno 1ibgaefcdh

2import inspect 1ibgaefcdh

3import os 1ibgaefcdh

4import sys 1ibgaefcdh

5from enum import Enum 1ibgaefcdh

6from gettext import gettext as _ 1ibgaefcdh

7from typing import ( 1ibgaefcdh

8 Any, 

9 Callable, 

10 Dict, 

11 List, 

12 MutableMapping, 

13 Optional, 

14 Sequence, 

15 TextIO, 

16 Tuple, 

17 Union, 

18 cast, 

19) 

20 

21import click 1ibgaefcdh

22import click.core 1ibgaefcdh

23import click.formatting 1ibgaefcdh

24import click.parser 1ibgaefcdh

25import click.shell_completion 1ibgaefcdh

26import click.types 1ibgaefcdh

27import click.utils 1ibgaefcdh

28 

29from ._typing import Literal 1ibgaefcdh

30 

31MarkupMode = Literal["markdown", "rich", None] 1ibgaefcdh

32 

33try: 1ibgaefcdh

34 import rich 1ibgaefcdh

35 

36 from . import rich_utils 1ibgaefcdh

37 

38 DEFAULT_MARKUP_MODE: MarkupMode = "rich" 1ibgaefcdh

39 

40except ImportError: # pragma: no cover 

41 rich = None # type: ignore 

42 DEFAULT_MARKUP_MODE = None 

43 

44 

45# Copy from click.parser._split_opt 

46def _split_opt(opt: str) -> Tuple[str, str]: 1ibgaefcdh

47 first = opt[:1] 1ibgaefcdh

48 if first.isalnum(): 1ibgaefcdh

49 return "", opt 1ibgaefcdh

50 if opt[1:2] == first: 1ibgaefcdh

51 return opt[:2], opt[2:] 1ibgaefcdh

52 return first, opt[1:] 1ibgaefcdh

53 

54 

55def _typer_param_setup_autocompletion_compat( 1bgaefcdh

56 self: click.Parameter, 

57 *, 

58 autocompletion: Optional[ 

59 Callable[[click.Context, List[str], str], List[Union[Tuple[str, str], str]]] 

60 ] = None, 

61) -> None: 

62 if self._custom_shell_complete is not None: 1ibgaefcdh

63 import warnings 1ibgaefcdh

64 

65 warnings.warn( 1ibgaefcdh

66 "In Typer, only the parameter 'autocompletion' is supported. " 

67 "The support for 'shell_complete' is deprecated and will be removed in upcoming versions. ", 

68 DeprecationWarning, 

69 stacklevel=2, 

70 ) 

71 

72 if autocompletion is not None: 1ibgaefcdh

73 

74 def compat_autocompletion( 1bgaefcdh

75 ctx: click.Context, param: click.core.Parameter, incomplete: str 

76 ) -> List["click.shell_completion.CompletionItem"]: 

77 from click.shell_completion import CompletionItem 1ibgaefcdh

78 

79 out = [] 1ibgaefcdh

80 

81 for c in autocompletion(ctx, [], incomplete): 1ibgaefcdh

82 if isinstance(c, tuple): 1ibgaefcdh

83 use_completion = CompletionItem(c[0], help=c[1]) 1ibgaefcdh

84 else: 

85 assert isinstance(c, str) 1ibgaefcdh

86 use_completion = CompletionItem(c) 1ibgaefcdh

87 

88 if use_completion.value.startswith(incomplete): 1ibgaefcdh

89 out.append(use_completion) 1ibgaefcdh

90 

91 return out 1ibgaefcdh

92 

93 self._custom_shell_complete = compat_autocompletion 1ibgaefcdh

94 

95 

96def _get_default_string( 1bgaefcdh

97 obj: Union["TyperArgument", "TyperOption"], 

98 *, 

99 ctx: click.Context, 

100 show_default_is_str: bool, 

101 default_value: Union[List[Any], Tuple[Any, ...], str, Callable[..., Any], Any], 

102) -> str: 

103 # Extracted from click.core.Option.get_help_record() to be reused by 

104 # rich_utils avoiding RegEx hacks 

105 if show_default_is_str: 1ibgaefcdh

106 default_string = f"({obj.show_default})" 1ibgaefcdh

107 elif isinstance(default_value, (list, tuple)): 1ibgaefcdh

108 default_string = ", ".join( 1ibgaefcdh

109 _get_default_string( 

110 obj, ctx=ctx, show_default_is_str=show_default_is_str, default_value=d 

111 ) 

112 for d in default_value 

113 ) 

114 elif isinstance(default_value, Enum): 1ibgaefcdh

115 default_string = str(default_value.value) 1ibgaefcdh

116 elif inspect.isfunction(default_value): 1ibgaefcdh

117 default_string = _("(dynamic)") 1ibgaefcdh

118 elif isinstance(obj, TyperOption) and obj.is_bool_flag and obj.secondary_opts: 1ibgaefcdh

119 # For boolean flags that have distinct True/False opts, 

120 # use the opt without prefix instead of the value. 

121 # Typer override, original commented 

122 # default_string = click.parser.split_opt( 

123 # (self.opts if self.default else self.secondary_opts)[0] 

124 # )[1] 

125 if obj.default: 1ibgaefcdh

126 if obj.opts: 1ibgaefcdh

127 default_string = _split_opt(obj.opts[0])[1] 1ibgaefcdh

128 else: 

129 default_string = str(default_value) 1ibgaefcdh

130 else: 

131 default_string = _split_opt(obj.secondary_opts[0])[1] 1ibgaefcdh

132 # Typer override end 

133 elif ( 1bacd

134 isinstance(obj, TyperOption) 

135 and obj.is_bool_flag 

136 and not obj.secondary_opts 

137 and not default_value 

138 ): 

139 default_string = "" 1ibgaefcdh

140 else: 

141 default_string = str(default_value) 1ibgaefcdh

142 return default_string 1ibgaefcdh

143 

144 

145def _extract_default_help_str( 1bgaefcdh

146 obj: Union["TyperArgument", "TyperOption"], *, ctx: click.Context 

147) -> Optional[Union[Any, Callable[[], Any]]]: 

148 # Extracted from click.core.Option.get_help_record() to be reused by 

149 # rich_utils avoiding RegEx hacks 

150 # Temporarily enable resilient parsing to avoid type casting 

151 # failing for the default. Might be possible to extend this to 

152 # help formatting in general. 

153 resilient = ctx.resilient_parsing 1ibgaefcdh

154 ctx.resilient_parsing = True 1ibgaefcdh

155 

156 try: 1ibgaefcdh

157 default_value = obj.get_default(ctx, call=False) 1ibgaefcdh

158 finally: 

159 ctx.resilient_parsing = resilient 1ibgaefcdh

160 return default_value 1ibgaefcdh

161 

162 

163def _main( 1bgaefcdh

164 self: click.Command, 

165 *, 

166 args: Optional[Sequence[str]] = None, 

167 prog_name: Optional[str] = None, 

168 complete_var: Optional[str] = None, 

169 standalone_mode: bool = True, 

170 windows_expand_args: bool = True, 

171 rich_markup_mode: MarkupMode = DEFAULT_MARKUP_MODE, 

172 **extra: Any, 

173) -> Any: 

174 # Typer override, duplicated from click.main() to handle custom rich exceptions 

175 # Verify that the environment is configured correctly, or reject 

176 # further execution to avoid a broken script. 

177 if args is None: 1ibgaefcdh

178 args = sys.argv[1:] 1ibgaefcdh

179 

180 # Covered in Click tests 

181 if os.name == "nt" and windows_expand_args: # pragma: no cover 1ibgaefcdh

182 args = click.utils._expand_args(args) 1aef

183 else: 

184 args = list(args) 1ibgaefcdh

185 

186 if prog_name is None: 1ibgaefcdh

187 prog_name = click.utils._detect_program_name() 1ibgaefcdh

188 

189 # Process shell completion requests and exit early. 

190 self._main_shell_completion(extra, prog_name, complete_var) 1ibgaefcdh

191 

192 try: 1ibgaefcdh

193 try: 1ibgaefcdh

194 with self.make_context(prog_name, args, **extra) as ctx: 1ibgaefcdh

195 rv = self.invoke(ctx) 1ibgaefcdh

196 if not standalone_mode: 1ibgaefcdh

197 return rv 1ibgaefcdh

198 # it's not safe to `ctx.exit(rv)` here! 

199 # note that `rv` may actually contain data like "1" which 

200 # has obvious effects 

201 # more subtle case: `rv=[None, None]` can come out of 

202 # chained commands which all returned `None` -- so it's not 

203 # even always obvious that `rv` indicates success/failure 

204 # by its truthiness/falsiness 

205 ctx.exit() 1ibgaefcdh

206 except EOFError as e: 1ibgaefcdh

207 click.echo(file=sys.stderr) 1ibgaefcdh

208 raise click.Abort() from e 1ibgaefcdh

209 except KeyboardInterrupt as e: 1ibgaefcdh

210 raise click.exceptions.Exit(130) from e 1ibgaefcdh

211 except click.ClickException as e: 1ibgaefcdh

212 if not standalone_mode: 1ibgaefcdh

213 raise 1ibgaefcdh

214 # Typer override 

215 if rich and rich_markup_mode is not None: 1ibgaefcdh

216 rich_utils.rich_format_error(e) 1ibgaefcdh

217 else: 

218 e.show() 1ibgaefcdh

219 # Typer override end 

220 sys.exit(e.exit_code) 1ibgaefcdh

221 except OSError as e: 1ibgaefcdh

222 if e.errno == errno.EPIPE: 1ibgaefcdh

223 sys.stdout = cast(TextIO, click.utils.PacifyFlushWrapper(sys.stdout)) 1ibgaefcdh

224 sys.stderr = cast(TextIO, click.utils.PacifyFlushWrapper(sys.stderr)) 1ibgaefcdh

225 sys.exit(1) 1ibgaefcdh

226 else: 

227 raise 1ibgaefcdh

228 except click.exceptions.Exit as e: 1ibgaefcdh

229 if standalone_mode: 1ibgaefcdh

230 sys.exit(e.exit_code) 1ibgaefcdh

231 else: 

232 # in non-standalone mode, return the exit code 

233 # note that this is only reached if `self.invoke` above raises 

234 # an Exit explicitly -- thus bypassing the check there which 

235 # would return its result 

236 # the results of non-standalone execution may therefore be 

237 # somewhat ambiguous: if there are codepaths which lead to 

238 # `ctx.exit(1)` and to `return 1`, the caller won't be able to 

239 # tell the difference between the two 

240 return e.exit_code 1ibgaefcdh

241 except click.Abort: 1ibgaefcdh

242 if not standalone_mode: 1ibgaefcdh

243 raise 1ibgaefcdh

244 # Typer override 

245 if rich and rich_markup_mode is not None: 1ibgaefcdh

246 rich_utils.rich_abort_error() 1ibgaefcdh

247 else: 

248 click.echo(_("Aborted!"), file=sys.stderr) 1ibgaefcdh

249 # Typer override end 

250 sys.exit(1) 1ibgaefcdh

251 

252 

253class TyperArgument(click.core.Argument): 1ibgaefcdh

254 def __init__( 1bgaefcdh

255 self, 

256 *, 

257 # Parameter 

258 param_decls: List[str], 

259 type: Optional[Any] = None, 

260 required: Optional[bool] = None, 

261 default: Optional[Any] = None, 

262 callback: Optional[Callable[..., Any]] = None, 

263 nargs: Optional[int] = None, 

264 metavar: Optional[str] = None, 

265 expose_value: bool = True, 

266 is_eager: bool = False, 

267 envvar: Optional[Union[str, List[str]]] = None, 

268 # Note that shell_complete is not fully supported and will be removed in future versions 

269 # TODO: Remove shell_complete in a future version (after 0.16.0) 

270 shell_complete: Optional[ 

271 Callable[ 

272 [click.Context, click.Parameter, str], 

273 Union[List["click.shell_completion.CompletionItem"], List[str]], 

274 ] 

275 ] = None, 

276 autocompletion: Optional[Callable[..., Any]] = None, 

277 # TyperArgument 

278 show_default: Union[bool, str] = True, 

279 show_choices: bool = True, 

280 show_envvar: bool = True, 

281 help: Optional[str] = None, 

282 hidden: bool = False, 

283 # Rich settings 

284 rich_help_panel: Union[str, None] = None, 

285 ): 

286 self.help = help 1ibgaefcdh

287 self.show_default = show_default 1ibgaefcdh

288 self.show_choices = show_choices 1ibgaefcdh

289 self.show_envvar = show_envvar 1ibgaefcdh

290 self.hidden = hidden 1ibgaefcdh

291 self.rich_help_panel = rich_help_panel 1ibgaefcdh

292 

293 super().__init__( 1ibgaefcdh

294 param_decls=param_decls, 

295 type=type, 

296 required=required, 

297 default=default, 

298 callback=callback, 

299 nargs=nargs, 

300 metavar=metavar, 

301 expose_value=expose_value, 

302 is_eager=is_eager, 

303 envvar=envvar, 

304 shell_complete=shell_complete, 

305 ) 

306 _typer_param_setup_autocompletion_compat(self, autocompletion=autocompletion) 1ibgaefcdh

307 

308 def _get_default_string( 1bgaefcdh

309 self, 

310 *, 

311 ctx: click.Context, 

312 show_default_is_str: bool, 

313 default_value: Union[List[Any], Tuple[Any, ...], str, Callable[..., Any], Any], 

314 ) -> str: 

315 return _get_default_string( 1ibgaefcdh

316 self, 

317 ctx=ctx, 

318 show_default_is_str=show_default_is_str, 

319 default_value=default_value, 

320 ) 

321 

322 def _extract_default_help_str( 1bgaefcdh

323 self, *, ctx: click.Context 

324 ) -> Optional[Union[Any, Callable[[], Any]]]: 

325 return _extract_default_help_str(self, ctx=ctx) 1ibgaefcdh

326 

327 def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]: 1ibgaefcdh

328 # Modified version of click.core.Option.get_help_record() 

329 # to support Arguments 

330 if self.hidden: 1ibgaefcdh

331 return None 1ibgaefcdh

332 name = self.make_metavar() 1ibgaefcdh

333 help = self.help or "" 1ibgaefcdh

334 extra = [] 1ibgaefcdh

335 if self.show_envvar: 1ibgaefcdh

336 envvar = self.envvar 1ibgaefcdh

337 # allow_from_autoenv is currently not supported in Typer for CLI Arguments 

338 if envvar is not None: 1ibgaefcdh

339 var_str = ( 1bgaefcdh

340 ", ".join(str(d) for d in envvar) 

341 if isinstance(envvar, (list, tuple)) 

342 else envvar 

343 ) 

344 extra.append(f"env var: {var_str}") 1ibgaefcdh

345 

346 # Typer override: 

347 # Extracted to _extract_default_help_str() to allow re-using it in rich_utils 

348 default_value = self._extract_default_help_str(ctx=ctx) 1ibgaefcdh

349 # Typer override end 

350 

351 show_default_is_str = isinstance(self.show_default, str) 1ibgaefcdh

352 

353 if show_default_is_str or ( 1ibgaefcdh

354 default_value is not None and (self.show_default or ctx.show_default) 

355 ): 

356 # Typer override: 

357 # Extracted to _get_default_string() to allow re-using it in rich_utils 

358 default_string = self._get_default_string( 1ibgaefcdh

359 ctx=ctx, 

360 show_default_is_str=show_default_is_str, 

361 default_value=default_value, 

362 ) 

363 # Typer override end 

364 if default_string: 1ibgaefcdh

365 extra.append(_("default: {default}").format(default=default_string)) 1ibgaefcdh

366 if self.required: 1ibgaefcdh

367 extra.append(_("required")) 1ibgaefcdh

368 if extra: 1ibgaefcdh

369 extra_str = "; ".join(extra) 1ibgaefcdh

370 extra_str = f"[{extra_str}]" 1ibgaefcdh

371 if rich is not None: 1ibgaefcdh

372 # This is needed for when we want to export to HTML 

373 extra_str = rich.markup.escape(extra_str).strip() 1ibgaefcdh

374 

375 help = f"{help} {extra_str}" if help else f"{extra_str}" 1ibgaefcdh

376 return name, help 1ibgaefcdh

377 

378 def make_metavar(self) -> str: 1ibgaefcdh

379 # Modified version of click.core.Argument.make_metavar() 

380 # to include Argument name 

381 if self.metavar is not None: 1ibgaefcdh

382 return self.metavar 1ibgaefcdh

383 var = (self.name or "").upper() 1ibgaefcdh

384 if not self.required: 1ibgaefcdh

385 var = f"[{var}]" 1ibgaefcdh

386 type_var = self.type.get_metavar(self) 1ibgaefcdh

387 if type_var: 1ibgaefcdh

388 var += f":{type_var}" 1ibgaefcdh

389 if self.nargs != 1: 1ibgaefcdh

390 var += "..." 1ibgaefcdh

391 return var 1ibgaefcdh

392 

393 

394class TyperOption(click.core.Option): 1ibgaefcdh

395 def __init__( 1bgaefcdh

396 self, 

397 *, 

398 # Parameter 

399 param_decls: List[str], 

400 type: Optional[Union[click.types.ParamType, Any]] = None, 

401 required: Optional[bool] = None, 

402 default: Optional[Any] = None, 

403 callback: Optional[Callable[..., Any]] = None, 

404 nargs: Optional[int] = None, 

405 metavar: Optional[str] = None, 

406 expose_value: bool = True, 

407 is_eager: bool = False, 

408 envvar: Optional[Union[str, List[str]]] = None, 

409 # Note that shell_complete is not fully supported and will be removed in future versions 

410 # TODO: Remove shell_complete in a future version (after 0.16.0) 

411 shell_complete: Optional[ 

412 Callable[ 

413 [click.Context, click.Parameter, str], 

414 Union[List["click.shell_completion.CompletionItem"], List[str]], 

415 ] 

416 ] = None, 

417 autocompletion: Optional[Callable[..., Any]] = None, 

418 # Option 

419 show_default: Union[bool, str] = False, 

420 prompt: Union[bool, str] = False, 

421 confirmation_prompt: Union[bool, str] = False, 

422 prompt_required: bool = True, 

423 hide_input: bool = False, 

424 is_flag: Optional[bool] = None, 

425 multiple: bool = False, 

426 count: bool = False, 

427 allow_from_autoenv: bool = True, 

428 help: Optional[str] = None, 

429 hidden: bool = False, 

430 show_choices: bool = True, 

431 show_envvar: bool = False, 

432 # Rich settings 

433 rich_help_panel: Union[str, None] = None, 

434 ): 

435 super().__init__( 1ibgaefcdh

436 param_decls=param_decls, 

437 type=type, 

438 required=required, 

439 default=default, 

440 callback=callback, 

441 nargs=nargs, 

442 metavar=metavar, 

443 expose_value=expose_value, 

444 is_eager=is_eager, 

445 envvar=envvar, 

446 show_default=show_default, 

447 prompt=prompt, 

448 confirmation_prompt=confirmation_prompt, 

449 hide_input=hide_input, 

450 is_flag=is_flag, 

451 multiple=multiple, 

452 count=count, 

453 allow_from_autoenv=allow_from_autoenv, 

454 help=help, 

455 hidden=hidden, 

456 show_choices=show_choices, 

457 show_envvar=show_envvar, 

458 prompt_required=prompt_required, 

459 shell_complete=shell_complete, 

460 ) 

461 _typer_param_setup_autocompletion_compat(self, autocompletion=autocompletion) 1ibgaefcdh

462 self.rich_help_panel = rich_help_panel 1ibgaefcdh

463 

464 def _get_default_string( 1bgaefcdh

465 self, 

466 *, 

467 ctx: click.Context, 

468 show_default_is_str: bool, 

469 default_value: Union[List[Any], Tuple[Any, ...], str, Callable[..., Any], Any], 

470 ) -> str: 

471 return _get_default_string( 1ibgaefcdh

472 self, 

473 ctx=ctx, 

474 show_default_is_str=show_default_is_str, 

475 default_value=default_value, 

476 ) 

477 

478 def _extract_default_help_str( 1bgaefcdh

479 self, *, ctx: click.Context 

480 ) -> Optional[Union[Any, Callable[[], Any]]]: 

481 return _extract_default_help_str(self, ctx=ctx) 1ibgaefcdh

482 

483 def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]: 1ibgaefcdh

484 # Duplicate all of Click's logic only to modify a single line, to allow boolean 

485 # flags with only names for False values as it's currently supported by Typer 

486 # Ref: https://typer.tiangolo.com/tutorial/parameter-types/bool/#only-names-for-false 

487 if self.hidden: 1ibgaefcdh

488 return None 1ibgaefcdh

489 

490 any_prefix_is_slash = False 1ibgaefcdh

491 

492 def _write_opts(opts: Sequence[str]) -> str: 1ibgaefcdh

493 nonlocal any_prefix_is_slash 

494 

495 rv, any_slashes = click.formatting.join_options(opts) 1ibgaefcdh

496 

497 if any_slashes: 1ibgaefcdh

498 any_prefix_is_slash = True 1ibgaefcdh

499 

500 if not self.is_flag and not self.count: 1ibgaefcdh

501 rv += f" {self.make_metavar()}" 1ibgaefcdh

502 

503 return rv 1ibgaefcdh

504 

505 rv = [_write_opts(self.opts)] 1ibgaefcdh

506 

507 if self.secondary_opts: 1ibgaefcdh

508 rv.append(_write_opts(self.secondary_opts)) 1ibgaefcdh

509 

510 help = self.help or "" 1ibgaefcdh

511 extra = [] 1ibgaefcdh

512 

513 if self.show_envvar: 1ibgaefcdh

514 envvar = self.envvar 1ibgaefcdh

515 

516 if envvar is None: 1ibgaefcdh

517 if ( 1bacd

518 self.allow_from_autoenv 

519 and ctx.auto_envvar_prefix is not None 

520 and self.name is not None 

521 ): 

522 envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" 1ibgaefcdh

523 

524 if envvar is not None: 1ibgaefcdh

525 var_str = ( 1bgaefcdh

526 envvar 

527 if isinstance(envvar, str) 

528 else ", ".join(str(d) for d in envvar) 

529 ) 

530 extra.append(_("env var: {var}").format(var=var_str)) 1ibgaefcdh

531 

532 # Typer override: 

533 # Extracted to _extract_default() to allow re-using it in rich_utils 

534 default_value = self._extract_default_help_str(ctx=ctx) 1ibgaefcdh

535 # Typer override end 

536 

537 show_default_is_str = isinstance(self.show_default, str) 1ibgaefcdh

538 

539 if show_default_is_str or ( 1ibgaefcdh

540 default_value is not None and (self.show_default or ctx.show_default) 

541 ): 

542 # Typer override: 

543 # Extracted to _get_default_string() to allow re-using it in rich_utils 

544 default_string = self._get_default_string( 1ibgaefcdh

545 ctx=ctx, 

546 show_default_is_str=show_default_is_str, 

547 default_value=default_value, 

548 ) 

549 # Typer override end 

550 if default_string: 1ibgaefcdh

551 extra.append(_("default: {default}").format(default=default_string)) 1ibgaefcdh

552 

553 if isinstance(self.type, click.types._NumberRangeBase): 1ibgaefcdh

554 range_str = self.type._describe_range() 1ibgaefcdh

555 

556 if range_str: 1ibgaefcdh

557 extra.append(range_str) 1ibgaefcdh

558 

559 if self.required: 1ibgaefcdh

560 extra.append(_("required")) 1ibgaefcdh

561 

562 if extra: 1ibgaefcdh

563 extra_str = "; ".join(extra) 1ibgaefcdh

564 extra_str = f"[{extra_str}]" 1ibgaefcdh

565 if rich is not None: 1ibgaefcdh

566 # This is needed for when we want to export to HTML 

567 extra_str = rich.markup.escape(extra_str).strip() 1ibgaefcdh

568 

569 help = f"{help} {extra_str}" if help else f"{extra_str}" 1ibgaefcdh

570 

571 return ("; " if any_prefix_is_slash else " / ").join(rv), help 1ibgaefcdh

572 

573 

574def _typer_format_options( 1bgaefcdh

575 self: click.core.Command, *, ctx: click.Context, formatter: click.HelpFormatter 

576) -> None: 

577 args = [] 1ibgaefcdh

578 opts = [] 1ibgaefcdh

579 for param in self.get_params(ctx): 1ibgaefcdh

580 rv = param.get_help_record(ctx) 1ibgaefcdh

581 if rv is not None: 1ibgaefcdh

582 if param.param_type_name == "argument": 1ibgaefcdh

583 args.append(rv) 1ibgaefcdh

584 elif param.param_type_name == "option": 1ibgaefcdh

585 opts.append(rv) 1ibgaefcdh

586 

587 if args: 1ibgaefcdh

588 with formatter.section(_("Arguments")): 1ibgaefcdh

589 formatter.write_dl(args) 1ibgaefcdh

590 if opts: 1ibgaefcdh

591 with formatter.section(_("Options")): 1ibgaefcdh

592 formatter.write_dl(opts) 1ibgaefcdh

593 

594 

595def _typer_main_shell_completion( 1bgaefcdh

596 self: click.core.Command, 

597 *, 

598 ctx_args: MutableMapping[str, Any], 

599 prog_name: str, 

600 complete_var: Optional[str] = None, 

601) -> None: 

602 if complete_var is None: 1ibgaefcdh

603 complete_var = f"_{prog_name}_COMPLETE".replace("-", "_").upper() 1ibgaefcdh

604 

605 instruction = os.environ.get(complete_var) 1ibgaefcdh

606 

607 if not instruction: 1ibgaefcdh

608 return 1ibgaefcdh

609 

610 from .completion import shell_complete 1ibgaefcdh

611 

612 rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) 1ibgaefcdh

613 sys.exit(rv) 1ibgaefcdh

614 

615 

616class TyperCommand(click.core.Command): 1ibgaefcdh

617 def __init__( 1bgaefcdh

618 self, 

619 name: Optional[str], 

620 *, 

621 context_settings: Optional[Dict[str, Any]] = None, 

622 callback: Optional[Callable[..., Any]] = None, 

623 params: Optional[List[click.Parameter]] = None, 

624 help: Optional[str] = None, 

625 epilog: Optional[str] = None, 

626 short_help: Optional[str] = None, 

627 options_metavar: Optional[str] = "[OPTIONS]", 

628 add_help_option: bool = True, 

629 no_args_is_help: bool = False, 

630 hidden: bool = False, 

631 deprecated: bool = False, 

632 # Rich settings 

633 rich_markup_mode: MarkupMode = DEFAULT_MARKUP_MODE, 

634 rich_help_panel: Union[str, None] = None, 

635 ) -> None: 

636 super().__init__( 1ibgaefcdh

637 name=name, 

638 context_settings=context_settings, 

639 callback=callback, 

640 params=params, 

641 help=help, 

642 epilog=epilog, 

643 short_help=short_help, 

644 options_metavar=options_metavar, 

645 add_help_option=add_help_option, 

646 no_args_is_help=no_args_is_help, 

647 hidden=hidden, 

648 deprecated=deprecated, 

649 ) 

650 self.rich_markup_mode: MarkupMode = rich_markup_mode 1ibgaefcdh

651 self.rich_help_panel = rich_help_panel 1ibgaefcdh

652 

653 def format_options( 1bgaefcdh

654 self, ctx: click.Context, formatter: click.HelpFormatter 

655 ) -> None: 

656 _typer_format_options(self, ctx=ctx, formatter=formatter) 1ibgaefcdh

657 

658 def _main_shell_completion( 1bgaefcdh

659 self, 

660 ctx_args: MutableMapping[str, Any], 

661 prog_name: str, 

662 complete_var: Optional[str] = None, 

663 ) -> None: 

664 _typer_main_shell_completion( 1ibgaefcdh

665 self, ctx_args=ctx_args, prog_name=prog_name, complete_var=complete_var 

666 ) 

667 

668 def main( 1bgaefcdh

669 self, 

670 args: Optional[Sequence[str]] = None, 

671 prog_name: Optional[str] = None, 

672 complete_var: Optional[str] = None, 

673 standalone_mode: bool = True, 

674 windows_expand_args: bool = True, 

675 **extra: Any, 

676 ) -> Any: 

677 return _main( 1ibgaefcdh

678 self, 

679 args=args, 

680 prog_name=prog_name, 

681 complete_var=complete_var, 

682 standalone_mode=standalone_mode, 

683 windows_expand_args=windows_expand_args, 

684 rich_markup_mode=self.rich_markup_mode, 

685 **extra, 

686 ) 

687 

688 def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None: 1ibgaefcdh

689 if not rich or self.rich_markup_mode is None: 1ibgaefcdh

690 return super().format_help(ctx, formatter) 1ibgaefcdh

691 return rich_utils.rich_format_help( 1ibgaefcdh

692 obj=self, 

693 ctx=ctx, 

694 markup_mode=self.rich_markup_mode, 

695 ) 

696 

697 

698class TyperGroup(click.core.Group): 1ibgaefcdh

699 def __init__( 1bgaefcdh

700 self, 

701 *, 

702 name: Optional[str] = None, 

703 commands: Optional[ 

704 Union[Dict[str, click.Command], Sequence[click.Command]] 

705 ] = None, 

706 # Rich settings 

707 rich_markup_mode: MarkupMode = DEFAULT_MARKUP_MODE, 

708 rich_help_panel: Union[str, None] = None, 

709 **attrs: Any, 

710 ) -> None: 

711 super().__init__(name=name, commands=commands, **attrs) 1ibgaefcdh

712 self.rich_markup_mode: MarkupMode = rich_markup_mode 1ibgaefcdh

713 self.rich_help_panel = rich_help_panel 1ibgaefcdh

714 

715 def format_options( 1bgaefcdh

716 self, ctx: click.Context, formatter: click.HelpFormatter 

717 ) -> None: 

718 _typer_format_options(self, ctx=ctx, formatter=formatter) 1ibgaefcdh

719 self.format_commands(ctx, formatter) 1ibgaefcdh

720 

721 def _main_shell_completion( 1bgaefcdh

722 self, 

723 ctx_args: MutableMapping[str, Any], 

724 prog_name: str, 

725 complete_var: Optional[str] = None, 

726 ) -> None: 

727 _typer_main_shell_completion( 1ibgaefcdh

728 self, ctx_args=ctx_args, prog_name=prog_name, complete_var=complete_var 

729 ) 

730 

731 def main( 1bgaefcdh

732 self, 

733 args: Optional[Sequence[str]] = None, 

734 prog_name: Optional[str] = None, 

735 complete_var: Optional[str] = None, 

736 standalone_mode: bool = True, 

737 windows_expand_args: bool = True, 

738 **extra: Any, 

739 ) -> Any: 

740 return _main( 1ibgaefcdh

741 self, 

742 args=args, 

743 prog_name=prog_name, 

744 complete_var=complete_var, 

745 standalone_mode=standalone_mode, 

746 windows_expand_args=windows_expand_args, 

747 rich_markup_mode=self.rich_markup_mode, 

748 **extra, 

749 ) 

750 

751 def format_help(self, ctx: click.Context, formatter: click.HelpFormatter) -> None: 1ibgaefcdh

752 if not rich or self.rich_markup_mode is None: 1ibgaefcdh

753 return super().format_help(ctx, formatter) 1ibgaefcdh

754 return rich_utils.rich_format_help( 1ibgaefcdh

755 obj=self, 

756 ctx=ctx, 

757 markup_mode=self.rich_markup_mode, 

758 ) 

759 

760 def list_commands(self, ctx: click.Context) -> List[str]: 1ibgaefcdh

761 """Returns a list of subcommand names. 

762 Note that in Click's Group class, these are sorted. 

763 In Typer, we wish to maintain the original order of creation (cf Issue #933)""" 

764 return [n for n, c in self.commands.items()] 1ibgaefcdh