Coverage for typer / models.py: 100%

134 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-02-09 12:36 +0000

1import inspect 1abcdefgh

2import io 1abcdefgh

3from collections.abc import Sequence 1abcdefgh

4from typing import ( 1abcdefgh

5 TYPE_CHECKING, 

6 Any, 

7 Callable, 

8 Optional, 

9 TypeVar, 

10 Union, 

11) 

12 

13import click 1abcdefgh

14import click.shell_completion 1abcdefgh

15 

16if TYPE_CHECKING: # pragma: no cover 1abcdefgh

17 from .core import TyperCommand, TyperGroup 

18 from .main import Typer 

19 

20 

21NoneType = type(None) 1abcdefgh

22 

23AnyType = type[Any] 1abcdefgh

24 

25Required = ... 1abcdefgh

26 

27 

28class Context(click.Context): 1abcdefgh

29 pass 1abcdefgh

30 

31 

32class FileText(io.TextIOWrapper): 1abcdefgh

33 pass 1abcdefgh

34 

35 

36class FileTextWrite(FileText): 1abcdefgh

37 pass 1abcdefgh

38 

39 

40class FileBinaryRead(io.BufferedReader): 1abcdefgh

41 pass 1abcdefgh

42 

43 

44class FileBinaryWrite(io.BufferedWriter): 1abcdefgh

45 pass 1abcdefgh

46 

47 

48class CallbackParam(click.Parameter): 1abcdefgh

49 pass 1abcdefgh

50 

51 

52class DefaultPlaceholder: 1abcdefgh

53 """ 

54 You shouldn't use this class directly. 

55 

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

57 if the new value is `None`. 

58 """ 

59 

60 def __init__(self, value: Any): 1abcdefgh

61 self.value = value 1abcdefgh

62 

63 def __bool__(self) -> bool: 1abcdefgh

64 return bool(self.value) 1abcdefgh

65 

66 

67DefaultType = TypeVar("DefaultType") 1abcdefgh

68 

69CommandFunctionType = TypeVar("CommandFunctionType", bound=Callable[..., Any]) 1abcdefgh

70 

71 

72def Default(value: DefaultType) -> DefaultType: 1abcdefgh

73 """ 

74 You shouldn't use this function directly. 

75 

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

77 if the new value is `None`. 

78 """ 

79 return DefaultPlaceholder(value) # type: ignore 1abcdefgh

80 

81 

82class CommandInfo: 1abcdefgh

83 def __init__( 1abcdefgh

84 self, 

85 name: Optional[str] = None, 

86 *, 

87 cls: Optional[type["TyperCommand"]] = None, 

88 context_settings: Optional[dict[Any, Any]] = None, 

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

90 help: Optional[str] = None, 

91 epilog: Optional[str] = None, 

92 short_help: Optional[str] = None, 

93 options_metavar: str = "[OPTIONS]", 

94 add_help_option: bool = True, 

95 no_args_is_help: bool = False, 

96 hidden: bool = False, 

97 deprecated: bool = False, 

98 # Rich settings 

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

100 ): 

101 self.name = name 1abcdefgh

102 self.cls = cls 1abcdefgh

103 self.context_settings = context_settings 1abcdefgh

104 self.callback = callback 1abcdefgh

105 self.help = help 1abcdefgh

106 self.epilog = epilog 1abcdefgh

107 self.short_help = short_help 1abcdefgh

108 self.options_metavar = options_metavar 1abcdefgh

109 self.add_help_option = add_help_option 1abcdefgh

110 self.no_args_is_help = no_args_is_help 1abcdefgh

111 self.hidden = hidden 1abcdefgh

112 self.deprecated = deprecated 1abcdefgh

113 # Rich settings 

114 self.rich_help_panel = rich_help_panel 1abcdefgh

115 

116 

117class TyperInfo: 1abcdefgh

118 def __init__( 1abcdefgh

119 self, 

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

121 *, 

122 name: Optional[str] = Default(None), 

123 cls: Optional[type["TyperGroup"]] = Default(None), 

124 invoke_without_command: bool = Default(False), 

125 no_args_is_help: bool = Default(False), 

126 subcommand_metavar: Optional[str] = Default(None), 

127 chain: bool = Default(False), 

128 result_callback: Optional[Callable[..., Any]] = Default(None), 

129 # Command 

130 context_settings: Optional[dict[Any, Any]] = Default(None), 

131 callback: Optional[Callable[..., Any]] = Default(None), 

132 help: Optional[str] = Default(None), 

133 epilog: Optional[str] = Default(None), 

134 short_help: Optional[str] = Default(None), 

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

136 add_help_option: bool = Default(True), 

137 hidden: bool = Default(False), 

138 deprecated: bool = Default(False), 

139 # Rich settings 

140 rich_help_panel: Union[str, None] = Default(None), 

141 ): 

142 self.typer_instance = typer_instance 1abcdefgh

143 self.name = name 1abcdefgh

144 self.cls = cls 1abcdefgh

145 self.invoke_without_command = invoke_without_command 1abcdefgh

146 self.no_args_is_help = no_args_is_help 1abcdefgh

147 self.subcommand_metavar = subcommand_metavar 1abcdefgh

148 self.chain = chain 1abcdefgh

149 self.result_callback = result_callback 1abcdefgh

150 self.context_settings = context_settings 1abcdefgh

151 self.callback = callback 1abcdefgh

152 self.help = help 1abcdefgh

153 self.epilog = epilog 1abcdefgh

154 self.short_help = short_help 1abcdefgh

155 self.options_metavar = options_metavar 1abcdefgh

156 self.add_help_option = add_help_option 1abcdefgh

157 self.hidden = hidden 1abcdefgh

158 self.deprecated = deprecated 1abcdefgh

159 self.rich_help_panel = rich_help_panel 1abcdefgh

160 

161 

162class ParameterInfo: 1abcdefgh

163 def __init__( 1abcdefgh

164 self, 

165 *, 

166 default: Optional[Any] = None, 

167 param_decls: Optional[Sequence[str]] = None, 

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

169 metavar: Optional[str] = None, 

170 expose_value: bool = True, 

171 is_eager: bool = False, 

172 envvar: Optional[Union[str, list[str]]] = None, 

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

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

175 shell_complete: Optional[ 

176 Callable[ 

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

178 Union[list["click.shell_completion.CompletionItem"], list[str]], 

179 ] 

180 ] = None, 

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

182 default_factory: Optional[Callable[[], Any]] = None, 

183 # Custom type 

184 parser: Optional[Callable[[str], Any]] = None, 

185 click_type: Optional[click.ParamType] = None, 

186 # TyperArgument 

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

188 show_choices: bool = True, 

189 show_envvar: bool = True, 

190 help: Optional[str] = None, 

191 hidden: bool = False, 

192 # Choice 

193 case_sensitive: bool = True, 

194 # Numbers 

195 min: Optional[Union[int, float]] = None, 

196 max: Optional[Union[int, float]] = None, 

197 clamp: bool = False, 

198 # DateTime 

199 formats: Optional[list[str]] = None, 

200 # File 

201 mode: Optional[str] = None, 

202 encoding: Optional[str] = None, 

203 errors: Optional[str] = "strict", 

204 lazy: Optional[bool] = None, 

205 atomic: bool = False, 

206 # Path 

207 exists: bool = False, 

208 file_okay: bool = True, 

209 dir_okay: bool = True, 

210 writable: bool = False, 

211 readable: bool = True, 

212 resolve_path: bool = False, 

213 allow_dash: bool = False, 

214 path_type: Union[None, type[str], type[bytes]] = None, 

215 # Rich settings 

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

217 ): 

218 # Check if user has provided multiple custom parsers 

219 if parser and click_type: 1abcdefgh

220 raise ValueError( 1abcdefgh

221 "Multiple custom type parsers provided. " 

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

223 ) 

224 

225 self.default = default 1abcdefgh

226 self.param_decls = param_decls 1abcdefgh

227 self.callback = callback 1abcdefgh

228 self.metavar = metavar 1abcdefgh

229 self.expose_value = expose_value 1abcdefgh

230 self.is_eager = is_eager 1abcdefgh

231 self.envvar = envvar 1abcdefgh

232 self.shell_complete = shell_complete 1abcdefgh

233 self.autocompletion = autocompletion 1abcdefgh

234 self.default_factory = default_factory 1abcdefgh

235 # Custom type 

236 self.parser = parser 1abcdefgh

237 self.click_type = click_type 1abcdefgh

238 # TyperArgument 

239 self.show_default = show_default 1abcdefgh

240 self.show_choices = show_choices 1abcdefgh

241 self.show_envvar = show_envvar 1abcdefgh

242 self.help = help 1abcdefgh

243 self.hidden = hidden 1abcdefgh

244 # Choice 

245 self.case_sensitive = case_sensitive 1abcdefgh

246 # Numbers 

247 self.min = min 1abcdefgh

248 self.max = max 1abcdefgh

249 self.clamp = clamp 1abcdefgh

250 # DateTime 

251 self.formats = formats 1abcdefgh

252 # File 

253 self.mode = mode 1abcdefgh

254 self.encoding = encoding 1abcdefgh

255 self.errors = errors 1abcdefgh

256 self.lazy = lazy 1abcdefgh

257 self.atomic = atomic 1abcdefgh

258 # Path 

259 self.exists = exists 1abcdefgh

260 self.file_okay = file_okay 1abcdefgh

261 self.dir_okay = dir_okay 1abcdefgh

262 self.writable = writable 1abcdefgh

263 self.readable = readable 1abcdefgh

264 self.resolve_path = resolve_path 1abcdefgh

265 self.allow_dash = allow_dash 1abcdefgh

266 self.path_type = path_type 1abcdefgh

267 # Rich settings 

268 self.rich_help_panel = rich_help_panel 1abcdefgh

269 

270 

271class OptionInfo(ParameterInfo): 1abcdefgh

272 def __init__( 1abcdefgh

273 self, 

274 *, 

275 # ParameterInfo 

276 default: Optional[Any] = None, 

277 param_decls: Optional[Sequence[str]] = None, 

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

279 metavar: Optional[str] = None, 

280 expose_value: bool = True, 

281 is_eager: bool = False, 

282 envvar: Optional[Union[str, list[str]]] = None, 

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

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

285 shell_complete: Optional[ 

286 Callable[ 

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

288 Union[list["click.shell_completion.CompletionItem"], list[str]], 

289 ] 

290 ] = None, 

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

292 default_factory: Optional[Callable[[], Any]] = None, 

293 # Custom type 

294 parser: Optional[Callable[[str], Any]] = None, 

295 click_type: Optional[click.ParamType] = None, 

296 # Option 

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

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

299 confirmation_prompt: bool = False, 

300 prompt_required: bool = True, 

301 hide_input: bool = False, 

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

303 is_flag: Optional[bool] = None, 

304 flag_value: Optional[Any] = None, 

305 count: bool = False, 

306 allow_from_autoenv: bool = True, 

307 help: Optional[str] = None, 

308 hidden: bool = False, 

309 show_choices: bool = True, 

310 show_envvar: bool = True, 

311 # Choice 

312 case_sensitive: bool = True, 

313 # Numbers 

314 min: Optional[Union[int, float]] = None, 

315 max: Optional[Union[int, float]] = None, 

316 clamp: bool = False, 

317 # DateTime 

318 formats: Optional[list[str]] = None, 

319 # File 

320 mode: Optional[str] = None, 

321 encoding: Optional[str] = None, 

322 errors: Optional[str] = "strict", 

323 lazy: Optional[bool] = None, 

324 atomic: bool = False, 

325 # Path 

326 exists: bool = False, 

327 file_okay: bool = True, 

328 dir_okay: bool = True, 

329 writable: bool = False, 

330 readable: bool = True, 

331 resolve_path: bool = False, 

332 allow_dash: bool = False, 

333 path_type: Union[None, type[str], type[bytes]] = None, 

334 # Rich settings 

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

336 ): 

337 super().__init__( 1abcdefgh

338 default=default, 

339 param_decls=param_decls, 

340 callback=callback, 

341 metavar=metavar, 

342 expose_value=expose_value, 

343 is_eager=is_eager, 

344 envvar=envvar, 

345 shell_complete=shell_complete, 

346 autocompletion=autocompletion, 

347 default_factory=default_factory, 

348 # Custom type 

349 parser=parser, 

350 click_type=click_type, 

351 # TyperArgument 

352 show_default=show_default, 

353 show_choices=show_choices, 

354 show_envvar=show_envvar, 

355 help=help, 

356 hidden=hidden, 

357 # Choice 

358 case_sensitive=case_sensitive, 

359 # Numbers 

360 min=min, 

361 max=max, 

362 clamp=clamp, 

363 # DateTime 

364 formats=formats, 

365 # File 

366 mode=mode, 

367 encoding=encoding, 

368 errors=errors, 

369 lazy=lazy, 

370 atomic=atomic, 

371 # Path 

372 exists=exists, 

373 file_okay=file_okay, 

374 dir_okay=dir_okay, 

375 writable=writable, 

376 readable=readable, 

377 resolve_path=resolve_path, 

378 allow_dash=allow_dash, 

379 path_type=path_type, 

380 # Rich settings 

381 rich_help_panel=rich_help_panel, 

382 ) 

383 if is_flag is not None or flag_value is not None: 1abcdefgh

384 import warnings 1abcdefgh

385 

386 warnings.warn( 1abcdefgh

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

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

389 DeprecationWarning, 

390 stacklevel=2, 

391 ) 

392 self.prompt = prompt 1abcdefgh

393 self.confirmation_prompt = confirmation_prompt 1abcdefgh

394 self.prompt_required = prompt_required 1abcdefgh

395 self.hide_input = hide_input 1abcdefgh

396 self.count = count 1abcdefgh

397 self.allow_from_autoenv = allow_from_autoenv 1abcdefgh

398 

399 

400class ArgumentInfo(ParameterInfo): 1abcdefgh

401 def __init__( 1abcdefgh

402 self, 

403 *, 

404 # ParameterInfo 

405 default: Optional[Any] = None, 

406 param_decls: Optional[Sequence[str]] = None, 

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

408 metavar: Optional[str] = None, 

409 expose_value: bool = True, 

410 is_eager: bool = False, 

411 envvar: Optional[Union[str, list[str]]] = None, 

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

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

414 shell_complete: Optional[ 

415 Callable[ 

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

417 Union[list["click.shell_completion.CompletionItem"], list[str]], 

418 ] 

419 ] = None, 

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

421 default_factory: Optional[Callable[[], Any]] = None, 

422 # Custom type 

423 parser: Optional[Callable[[str], Any]] = None, 

424 click_type: Optional[click.ParamType] = None, 

425 # TyperArgument 

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

427 show_choices: bool = True, 

428 show_envvar: bool = True, 

429 help: Optional[str] = None, 

430 hidden: bool = False, 

431 # Choice 

432 case_sensitive: bool = True, 

433 # Numbers 

434 min: Optional[Union[int, float]] = None, 

435 max: Optional[Union[int, float]] = None, 

436 clamp: bool = False, 

437 # DateTime 

438 formats: Optional[list[str]] = None, 

439 # File 

440 mode: Optional[str] = None, 

441 encoding: Optional[str] = None, 

442 errors: Optional[str] = "strict", 

443 lazy: Optional[bool] = None, 

444 atomic: bool = False, 

445 # Path 

446 exists: bool = False, 

447 file_okay: bool = True, 

448 dir_okay: bool = True, 

449 writable: bool = False, 

450 readable: bool = True, 

451 resolve_path: bool = False, 

452 allow_dash: bool = False, 

453 path_type: Union[None, type[str], type[bytes]] = None, 

454 # Rich settings 

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

456 ): 

457 super().__init__( 1abcdefgh

458 default=default, 

459 param_decls=param_decls, 

460 callback=callback, 

461 metavar=metavar, 

462 expose_value=expose_value, 

463 is_eager=is_eager, 

464 envvar=envvar, 

465 shell_complete=shell_complete, 

466 autocompletion=autocompletion, 

467 default_factory=default_factory, 

468 # Custom type 

469 parser=parser, 

470 click_type=click_type, 

471 # TyperArgument 

472 show_default=show_default, 

473 show_choices=show_choices, 

474 show_envvar=show_envvar, 

475 help=help, 

476 hidden=hidden, 

477 # Choice 

478 case_sensitive=case_sensitive, 

479 # Numbers 

480 min=min, 

481 max=max, 

482 clamp=clamp, 

483 # DateTime 

484 formats=formats, 

485 # File 

486 mode=mode, 

487 encoding=encoding, 

488 errors=errors, 

489 lazy=lazy, 

490 atomic=atomic, 

491 # Path 

492 exists=exists, 

493 file_okay=file_okay, 

494 dir_okay=dir_okay, 

495 writable=writable, 

496 readable=readable, 

497 resolve_path=resolve_path, 

498 allow_dash=allow_dash, 

499 path_type=path_type, 

500 # Rich settings 

501 rich_help_panel=rich_help_panel, 

502 ) 

503 

504 

505class ParamMeta: 1abcdefgh

506 empty = inspect.Parameter.empty 1abcdefgh

507 

508 def __init__( 1abcdefgh

509 self, 

510 *, 

511 name: str, 

512 default: Any = inspect.Parameter.empty, 

513 annotation: Any = inspect.Parameter.empty, 

514 ) -> None: 

515 self.name = name 1abcdefgh

516 self.default = default 1abcdefgh

517 self.annotation = annotation 1abcdefgh

518 

519 

520class DeveloperExceptionConfig: 1abcdefgh

521 def __init__( 1abcdefgh

522 self, 

523 *, 

524 pretty_exceptions_enable: bool = True, 

525 pretty_exceptions_show_locals: bool = True, 

526 pretty_exceptions_short: bool = True, 

527 ) -> None: 

528 self.pretty_exceptions_enable = pretty_exceptions_enable 1abcdefgh

529 self.pretty_exceptions_show_locals = pretty_exceptions_show_locals 1abcdefgh

530 self.pretty_exceptions_short = pretty_exceptions_short 1abcdefgh

531 

532 

533class TyperPath(click.Path): 1abcdefgh

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

535 def shell_complete( 1abcdefgh

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

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

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

539 will work properly from the commandline. 

540 """ 

541 return [] 1abcdefgh