Coverage for typer / models.py: 100%

134 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-03-26 21:46 +0000

1import inspect 1abcdefg

2import io 1abcdefg

3from collections.abc import Callable, Sequence 1abcdefg

4from typing import ( 1abcdefg

5 TYPE_CHECKING, 

6 Any, 

7 Optional, 

8 TypeVar, 

9) 

10 

11import click 1abcdefg

12import click.shell_completion 1abcdefg

13 

14if TYPE_CHECKING: # pragma: no cover 1abcdefg

15 from .core import TyperCommand, TyperGroup 

16 from .main import Typer 

17 

18 

19NoneType = type(None) 1abcdefg

20 

21AnyType = type[Any] 1abcdefg

22 

23Required = ... 1abcdefg

24 

25 

26class Context(click.Context): 1abcdefg

27 """ 

28 The [`Context`](https://click.palletsprojects.com/en/stable/api/#click.Context) has some additional data about the current execution of your program. 

29 When declaring it in a [callback](https://typer.tiangolo.com/tutorial/options/callback-and-context/) function, 

30 you can access this additional information. 

31 """ 

32 

33 pass 1abcdefg

34 

35 

36class FileText(io.TextIOWrapper): 1abcdefg

37 """ 1abcdefg

38 Gives you a file-like object for reading text, and you will get a `str` data from it. 

39 The default mode of this class is `mode="r"`. 

40 

41 **Example** 

42 

43 ```python 

44 from typing import Annotated 

45 

46 import typer 

47 

48 app = typer.Typer() 

49 

50 @app.command() 

51 def main(config: Annotated[typer.FileText, typer.Option()]): 

52 for line in config: 

53 print(f"Config line: {line}") 

54 

55 if __name__ == "__main__": 

56 app() 

57 ``` 

58 """ 

59 

60 pass 1abcdefg

61 

62 

63class FileTextWrite(FileText): 1abcdefg

64 """ 1abcdefg

65 You can use this class for writing text. Alternatively, you can use `FileText` with `mode="w"`. 

66 The default mode of this class is `mode="w"`. 

67 

68 **Example** 

69 

70 ```python 

71 from typing import Annotated 

72 

73 import typer 

74 

75 app = typer.Typer() 

76 

77 @app.command() 

78 def main(config: Annotated[typer.FileTextWrite, typer.Option()]): 

79 config.write("Some config written by the app") 

80 print("Config written") 

81 

82 if __name__ == "__main__": 

83 app() 

84 ``` 

85 """ 

86 

87 pass 1abcdefg

88 

89 

90class FileBinaryRead(io.BufferedReader): 1abcdefg

91 """ 1abcdefg

92 You can use this class to read binary data, receiving `bytes`. 

93 The default mode of this class is `mode="rb"`. 

94 It is useful for reading binary files like images: 

95 

96 **Example** 

97 

98 ```python 

99 from typing import Annotated 

100 

101 import typer 

102 

103 app = typer.Typer() 

104 

105 @app.command() 

106 def main(file: Annotated[typer.FileBinaryRead, typer.Option()]): 

107 processed_total = 0 

108 for bytes_chunk in file: 

109 # Process the bytes in bytes_chunk 

110 processed_total += len(bytes_chunk) 

111 print(f"Processed bytes total: {processed_total}") 

112 

113 if __name__ == "__main__": 

114 app() 

115 ``` 

116 """ 

117 

118 pass 1abcdefg

119 

120 

121class FileBinaryWrite(io.BufferedWriter): 1abcdefg

122 """ 1abcdefg

123 You can use this class to write binary data: you pass `bytes` to it instead of strings. 

124 The default mode of this class is `mode="wb"`. 

125 It is useful for writing binary files like images: 

126 

127 **Example** 

128 

129 ```python 

130 from typing import Annotated 

131 

132 import typer 

133 

134 app = typer.Typer() 

135 

136 @app.command() 

137 def main(file: Annotated[typer.FileBinaryWrite, typer.Option()]): 

138 first_line_str = "some settings\\n" 

139 # You cannot write str directly to a binary file; encode it first 

140 first_line_bytes = first_line_str.encode("utf-8") 

141 # Then you can write the bytes 

142 file.write(first_line_bytes) 

143 # This is already bytes, it starts with b" 

144 second_line = b"la cig\xc3\xbce\xc3\xb1a trae al ni\xc3\xb1o" 

145 file.write(second_line) 

146 print("Binary file written") 

147 

148 if __name__ == "__main__": 

149 app() 

150 ``` 

151 """ 

152 

153 pass 1abcdefg

154 

155 

156class CallbackParam(click.Parameter): 1abcdefg

157 """ 

158 In a callback function, you can declare a function parameter with type `CallbackParam` 

159 to access the specific Click [`Parameter`](https://click.palletsprojects.com/en/stable/api/#click.Parameter) object. 

160 """ 

161 

162 pass 1abcdefg

163 

164 

165class DefaultPlaceholder: 1abcdefg

166 """ 

167 You shouldn't use this class directly. 

168 

169 It's used internally to recognize when a default value has been overwritten, even 

170 if the new value is `None`. 

171 """ 

172 

173 def __init__(self, value: Any): 1abcdefg

174 self.value = value 1abcdefg

175 

176 def __bool__(self) -> bool: 1abcdefg

177 return bool(self.value) 1abcdefg

178 

179 

180DefaultType = TypeVar("DefaultType") 1abcdefg

181 

182CommandFunctionType = TypeVar("CommandFunctionType", bound=Callable[..., Any]) 1abcdefg

183 

184 

185def Default(value: DefaultType) -> DefaultType: 1abcdefg

186 """ 

187 You shouldn't use this function directly. 

188 

189 It's used internally to recognize when a default value has been overwritten, even 

190 if the new value is `None`. 

191 """ 

192 return DefaultPlaceholder(value) # type: ignore 1abcdefg

193 

194 

195class CommandInfo: 1abcdefg

196 def __init__( 1abcdefg

197 self, 

198 name: str | None = None, 

199 *, 

200 cls: type["TyperCommand"] | None = None, 

201 context_settings: dict[Any, Any] | None = None, 

202 callback: Callable[..., Any] | None = None, 

203 help: str | None = None, 

204 epilog: str | None = None, 

205 short_help: str | None = None, 

206 options_metavar: str = "[OPTIONS]", 

207 add_help_option: bool = True, 

208 no_args_is_help: bool = False, 

209 hidden: bool = False, 

210 deprecated: bool = False, 

211 # Rich settings 

212 rich_help_panel: str | None = None, 

213 ): 

214 self.name = name 1abcdefg

215 self.cls = cls 1abcdefg

216 self.context_settings = context_settings 1abcdefg

217 self.callback = callback 1abcdefg

218 self.help = help 1abcdefg

219 self.epilog = epilog 1abcdefg

220 self.short_help = short_help 1abcdefg

221 self.options_metavar = options_metavar 1abcdefg

222 self.add_help_option = add_help_option 1abcdefg

223 self.no_args_is_help = no_args_is_help 1abcdefg

224 self.hidden = hidden 1abcdefg

225 self.deprecated = deprecated 1abcdefg

226 # Rich settings 

227 self.rich_help_panel = rich_help_panel 1abcdefg

228 

229 

230class TyperInfo: 1abcdefg

231 def __init__( 1abcdefg

232 self, 

233 typer_instance: Optional["Typer"] = Default(None), 

234 *, 

235 name: str | None = Default(None), 

236 cls: type["TyperGroup"] | None = Default(None), 

237 invoke_without_command: bool = Default(False), 

238 no_args_is_help: bool = Default(False), 

239 subcommand_metavar: str | None = Default(None), 

240 chain: bool = Default(False), 

241 result_callback: Callable[..., Any] | None = Default(None), 

242 # Command 

243 context_settings: dict[Any, Any] | None = Default(None), 

244 callback: Callable[..., Any] | None = Default(None), 

245 help: str | None = Default(None), 

246 epilog: str | None = Default(None), 

247 short_help: str | None = Default(None), 

248 options_metavar: str = Default("[OPTIONS]"), 

249 add_help_option: bool = Default(True), 

250 hidden: bool = Default(False), 

251 deprecated: bool = Default(False), 

252 # Rich settings 

253 rich_help_panel: str | None = Default(None), 

254 ): 

255 self.typer_instance = typer_instance 1abcdefg

256 self.name = name 1abcdefg

257 self.cls = cls 1abcdefg

258 self.invoke_without_command = invoke_without_command 1abcdefg

259 self.no_args_is_help = no_args_is_help 1abcdefg

260 self.subcommand_metavar = subcommand_metavar 1abcdefg

261 self.chain = chain 1abcdefg

262 self.result_callback = result_callback 1abcdefg

263 self.context_settings = context_settings 1abcdefg

264 self.callback = callback 1abcdefg

265 self.help = help 1abcdefg

266 self.epilog = epilog 1abcdefg

267 self.short_help = short_help 1abcdefg

268 self.options_metavar = options_metavar 1abcdefg

269 self.add_help_option = add_help_option 1abcdefg

270 self.hidden = hidden 1abcdefg

271 self.deprecated = deprecated 1abcdefg

272 self.rich_help_panel = rich_help_panel 1abcdefg

273 

274 

275class ParameterInfo: 1abcdefg

276 def __init__( 1abcdefg

277 self, 

278 *, 

279 default: Any | None = None, 

280 param_decls: Sequence[str] | None = None, 

281 callback: Callable[..., Any] | None = None, 

282 metavar: str | None = None, 

283 expose_value: bool = True, 

284 is_eager: bool = False, 

285 envvar: str | list[str] | None = None, 

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

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

288 shell_complete: Callable[ 

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

290 list["click.shell_completion.CompletionItem"] | list[str], 

291 ] 

292 | None = None, 

293 autocompletion: Callable[..., Any] | None = None, 

294 default_factory: Callable[[], Any] | None = None, 

295 # Custom type 

296 parser: Callable[[str], Any] | None = None, 

297 click_type: click.ParamType | None = None, 

298 # TyperArgument 

299 show_default: bool | str = True, 

300 show_choices: bool = True, 

301 show_envvar: bool = True, 

302 help: str | None = None, 

303 hidden: bool = False, 

304 # Choice 

305 case_sensitive: bool = True, 

306 # Numbers 

307 min: int | float | None = None, 

308 max: int | float | None = None, 

309 clamp: bool = False, 

310 # DateTime 

311 formats: list[str] | None = None, 

312 # File 

313 mode: str | None = None, 

314 encoding: str | None = None, 

315 errors: str | None = "strict", 

316 lazy: bool | None = None, 

317 atomic: bool = False, 

318 # Path 

319 exists: bool = False, 

320 file_okay: bool = True, 

321 dir_okay: bool = True, 

322 writable: bool = False, 

323 readable: bool = True, 

324 resolve_path: bool = False, 

325 allow_dash: bool = False, 

326 path_type: None | type[str] | type[bytes] = None, 

327 # Rich settings 

328 rich_help_panel: str | None = None, 

329 ): 

330 # Check if user has provided multiple custom parsers 

331 if parser and click_type: 1abcdefg

332 raise ValueError( 1abcdefg

333 "Multiple custom type parsers provided. " 

334 "`parser` and `click_type` may not both be provided." 

335 ) 

336 

337 self.default = default 1abcdefg

338 self.param_decls = param_decls 1abcdefg

339 self.callback = callback 1abcdefg

340 self.metavar = metavar 1abcdefg

341 self.expose_value = expose_value 1abcdefg

342 self.is_eager = is_eager 1abcdefg

343 self.envvar = envvar 1abcdefg

344 self.shell_complete = shell_complete 1abcdefg

345 self.autocompletion = autocompletion 1abcdefg

346 self.default_factory = default_factory 1abcdefg

347 # Custom type 

348 self.parser = parser 1abcdefg

349 self.click_type = click_type 1abcdefg

350 # TyperArgument 

351 self.show_default = show_default 1abcdefg

352 self.show_choices = show_choices 1abcdefg

353 self.show_envvar = show_envvar 1abcdefg

354 self.help = help 1abcdefg

355 self.hidden = hidden 1abcdefg

356 # Choice 

357 self.case_sensitive = case_sensitive 1abcdefg

358 # Numbers 

359 self.min = min 1abcdefg

360 self.max = max 1abcdefg

361 self.clamp = clamp 1abcdefg

362 # DateTime 

363 self.formats = formats 1abcdefg

364 # File 

365 self.mode = mode 1abcdefg

366 self.encoding = encoding 1abcdefg

367 self.errors = errors 1abcdefg

368 self.lazy = lazy 1abcdefg

369 self.atomic = atomic 1abcdefg

370 # Path 

371 self.exists = exists 1abcdefg

372 self.file_okay = file_okay 1abcdefg

373 self.dir_okay = dir_okay 1abcdefg

374 self.writable = writable 1abcdefg

375 self.readable = readable 1abcdefg

376 self.resolve_path = resolve_path 1abcdefg

377 self.allow_dash = allow_dash 1abcdefg

378 self.path_type = path_type 1abcdefg

379 # Rich settings 

380 self.rich_help_panel = rich_help_panel 1abcdefg

381 

382 

383class OptionInfo(ParameterInfo): 1abcdefg

384 def __init__( 1abcdefg

385 self, 

386 *, 

387 # ParameterInfo 

388 default: Any | None = None, 

389 param_decls: Sequence[str] | None = None, 

390 callback: Callable[..., Any] | None = None, 

391 metavar: str | None = None, 

392 expose_value: bool = True, 

393 is_eager: bool = False, 

394 envvar: str | list[str] | None = None, 

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

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

397 shell_complete: Callable[ 

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

399 list["click.shell_completion.CompletionItem"] | list[str], 

400 ] 

401 | None = None, 

402 autocompletion: Callable[..., Any] | None = None, 

403 default_factory: Callable[[], Any] | None = None, 

404 # Custom type 

405 parser: Callable[[str], Any] | None = None, 

406 click_type: click.ParamType | None = None, 

407 # Option 

408 show_default: bool | str = True, 

409 prompt: bool | str = False, 

410 confirmation_prompt: bool = False, 

411 prompt_required: bool = True, 

412 hide_input: bool = False, 

413 # TODO: remove is_flag and flag_value in a future release 

414 is_flag: bool | None = None, 

415 flag_value: Any | None = None, 

416 count: bool = False, 

417 allow_from_autoenv: bool = True, 

418 help: str | None = None, 

419 hidden: bool = False, 

420 show_choices: bool = True, 

421 show_envvar: bool = True, 

422 # Choice 

423 case_sensitive: bool = True, 

424 # Numbers 

425 min: int | float | None = None, 

426 max: int | float | None = None, 

427 clamp: bool = False, 

428 # DateTime 

429 formats: list[str] | None = None, 

430 # File 

431 mode: str | None = None, 

432 encoding: str | None = None, 

433 errors: str | None = "strict", 

434 lazy: bool | None = None, 

435 atomic: bool = False, 

436 # Path 

437 exists: bool = False, 

438 file_okay: bool = True, 

439 dir_okay: bool = True, 

440 writable: bool = False, 

441 readable: bool = True, 

442 resolve_path: bool = False, 

443 allow_dash: bool = False, 

444 path_type: None | type[str] | type[bytes] = None, 

445 # Rich settings 

446 rich_help_panel: str | None = None, 

447 ): 

448 super().__init__( 1abcdefg

449 default=default, 

450 param_decls=param_decls, 

451 callback=callback, 

452 metavar=metavar, 

453 expose_value=expose_value, 

454 is_eager=is_eager, 

455 envvar=envvar, 

456 shell_complete=shell_complete, 

457 autocompletion=autocompletion, 

458 default_factory=default_factory, 

459 # Custom type 

460 parser=parser, 

461 click_type=click_type, 

462 # TyperArgument 

463 show_default=show_default, 

464 show_choices=show_choices, 

465 show_envvar=show_envvar, 

466 help=help, 

467 hidden=hidden, 

468 # Choice 

469 case_sensitive=case_sensitive, 

470 # Numbers 

471 min=min, 

472 max=max, 

473 clamp=clamp, 

474 # DateTime 

475 formats=formats, 

476 # File 

477 mode=mode, 

478 encoding=encoding, 

479 errors=errors, 

480 lazy=lazy, 

481 atomic=atomic, 

482 # Path 

483 exists=exists, 

484 file_okay=file_okay, 

485 dir_okay=dir_okay, 

486 writable=writable, 

487 readable=readable, 

488 resolve_path=resolve_path, 

489 allow_dash=allow_dash, 

490 path_type=path_type, 

491 # Rich settings 

492 rich_help_panel=rich_help_panel, 

493 ) 

494 if is_flag is not None or flag_value is not None: 1abcdefg

495 import warnings 1abcdefg

496 

497 warnings.warn( 1abcdefg

498 "The 'is_flag' and 'flag_value' parameters are not supported by Typer " 

499 "and will be removed entirely in a future release.", 

500 DeprecationWarning, 

501 stacklevel=2, 

502 ) 

503 self.prompt = prompt 1abcdefg

504 self.confirmation_prompt = confirmation_prompt 1abcdefg

505 self.prompt_required = prompt_required 1abcdefg

506 self.hide_input = hide_input 1abcdefg

507 self.count = count 1abcdefg

508 self.allow_from_autoenv = allow_from_autoenv 1abcdefg

509 

510 

511class ArgumentInfo(ParameterInfo): 1abcdefg

512 def __init__( 1abcdefg

513 self, 

514 *, 

515 # ParameterInfo 

516 default: Any | None = None, 

517 param_decls: Sequence[str] | None = None, 

518 callback: Callable[..., Any] | None = None, 

519 metavar: str | None = None, 

520 expose_value: bool = True, 

521 is_eager: bool = False, 

522 envvar: str | list[str] | None = None, 

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

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

525 shell_complete: Callable[ 

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

527 list["click.shell_completion.CompletionItem"] | list[str], 

528 ] 

529 | None = None, 

530 autocompletion: Callable[..., Any] | None = None, 

531 default_factory: Callable[[], Any] | None = None, 

532 # Custom type 

533 parser: Callable[[str], Any] | None = None, 

534 click_type: click.ParamType | None = None, 

535 # TyperArgument 

536 show_default: bool | str = True, 

537 show_choices: bool = True, 

538 show_envvar: bool = True, 

539 help: str | None = None, 

540 hidden: bool = False, 

541 # Choice 

542 case_sensitive: bool = True, 

543 # Numbers 

544 min: int | float | None = None, 

545 max: int | float | None = None, 

546 clamp: bool = False, 

547 # DateTime 

548 formats: list[str] | None = None, 

549 # File 

550 mode: str | None = None, 

551 encoding: str | None = None, 

552 errors: str | None = "strict", 

553 lazy: bool | None = None, 

554 atomic: bool = False, 

555 # Path 

556 exists: bool = False, 

557 file_okay: bool = True, 

558 dir_okay: bool = True, 

559 writable: bool = False, 

560 readable: bool = True, 

561 resolve_path: bool = False, 

562 allow_dash: bool = False, 

563 path_type: None | type[str] | type[bytes] = None, 

564 # Rich settings 

565 rich_help_panel: str | None = None, 

566 ): 

567 super().__init__( 1abcdefg

568 default=default, 

569 param_decls=param_decls, 

570 callback=callback, 

571 metavar=metavar, 

572 expose_value=expose_value, 

573 is_eager=is_eager, 

574 envvar=envvar, 

575 shell_complete=shell_complete, 

576 autocompletion=autocompletion, 

577 default_factory=default_factory, 

578 # Custom type 

579 parser=parser, 

580 click_type=click_type, 

581 # TyperArgument 

582 show_default=show_default, 

583 show_choices=show_choices, 

584 show_envvar=show_envvar, 

585 help=help, 

586 hidden=hidden, 

587 # Choice 

588 case_sensitive=case_sensitive, 

589 # Numbers 

590 min=min, 

591 max=max, 

592 clamp=clamp, 

593 # DateTime 

594 formats=formats, 

595 # File 

596 mode=mode, 

597 encoding=encoding, 

598 errors=errors, 

599 lazy=lazy, 

600 atomic=atomic, 

601 # Path 

602 exists=exists, 

603 file_okay=file_okay, 

604 dir_okay=dir_okay, 

605 writable=writable, 

606 readable=readable, 

607 resolve_path=resolve_path, 

608 allow_dash=allow_dash, 

609 path_type=path_type, 

610 # Rich settings 

611 rich_help_panel=rich_help_panel, 

612 ) 

613 

614 

615class ParamMeta: 1abcdefg

616 empty = inspect.Parameter.empty 1abcdefg

617 

618 def __init__( 1abcdefg

619 self, 

620 *, 

621 name: str, 

622 default: Any = inspect.Parameter.empty, 

623 annotation: Any = inspect.Parameter.empty, 

624 ) -> None: 

625 self.name = name 1abcdefg

626 self.default = default 1abcdefg

627 self.annotation = annotation 1abcdefg

628 

629 

630class DeveloperExceptionConfig: 1abcdefg

631 def __init__( 1abcdefg

632 self, 

633 *, 

634 pretty_exceptions_enable: bool = True, 

635 pretty_exceptions_show_locals: bool = True, 

636 pretty_exceptions_short: bool = True, 

637 ) -> None: 

638 self.pretty_exceptions_enable = pretty_exceptions_enable 1abcdefg

639 self.pretty_exceptions_show_locals = pretty_exceptions_show_locals 1abcdefg

640 self.pretty_exceptions_short = pretty_exceptions_short 1abcdefg

641 

642 

643class TyperPath(click.Path): 1abcdefg

644 # Overwrite Click's behaviour to be compatible with Typer's autocompletion system 

645 def shell_complete( 1abcdefg

646 self, ctx: click.Context, param: click.Parameter, incomplete: str 

647 ) -> list[click.shell_completion.CompletionItem]: 

648 """Return an empty list so that the autocompletion functionality 

649 will work properly from the commandline. 

650 """ 

651 return [] 1abcdefg