✨ Use Pydantic for parameter validation - #1831
Conversation
| ("No", False), | ||
| ], | ||
| ) | ||
| def test_bool_convert_valid(cli_value: str, expected: bool) -> None: |
There was a problem hiding this comment.
This test currently mimics master behaviour 100%.
…o feat/pydantic
| ## Dependencies | ||
|
|
||
| **Typer** requires only a few dependencies (most are tiny): | ||
| **Typer** requires only a few dependencies: |
There was a problem hiding this comment.
Removed the note that "most are tiny" as that feels a bit untrue now that Pydantic is added to the list.
|
I've self reviewed this with Fable, and it's got opinions 🥲 And so do I! 😎 Review by Fable 5, transcribed & commented by mePositives
Issues1) Path-specific kwargs for non-Path annotationsFable got confused and then confused me as well, so allow me to recap the issues involved here.
2) Heterogeneous tuplesFable had a comment about heterogeneous tuples, especially with paths in them, not being processed correctly. There were indeed some edge cases not covered correctly, so I wrote some additional unit tests for them: 3)
|
…ept for str typed)
| @@ -0,0 +1,22 @@ | |||
| from typing import Any | |||
There was a problem hiding this comment.
This module ended up being relatively small, we could also fold it in somewhere else.
Meta: marked as a "feature", but definitely also "breaking" !
Description
Make Pydantic a required dependency and rely on it for parameter validation. Picked
>=2.5.3which is the current pin forgithub-actions.Click's
ParamTypehierarchy is now replaced by a three-layer design:TypeDescriptorobjects store static facts about a parameter's type (in the new modulecoercion.py)TypeAdapterobjects are defined in the new moduleadapters.pyRuntimeParamsubclasses own coercion (also defined incoercion.py)Further type-specific functionality is bundled in the new module
param_types.py.How to review this
_click/types.pyandtyper/_types.pyare deletedtyper/param_types.py, thentyper/adapters.py, thentyper/coercion.pytyper/core.pytyper/*.pytyper/_click/*.pyExtended/improved functionality
[%Y-%m-%d|%Y-%m-%dT%H:%M:%S|%Y-%m-%d %H:%M:%S]. Unix timestamps as seconds or milliseconds since the Unix epoch are now also supported.TyperParameter, not quite finished yet with some ugly imports from within_clickbut we'll deal with those in follow-up workTests with same behaviour on
mastertest_bool_convert_validto ensure that the "bool" conversion has remained the same for all kinds of inputs.test_path_resolves, cf point 1) in the Fable review 👇Breaking changes
(more or less in order of breakingness from most to least)
click_typeand open bounds throughmin_openandmax_open. This greatly simplifies the code base while still providing an alternative by settingparserinstead.<list[Eggs|Bacon|Cheese]>(before there was no visual distinction between a single choice, or a list of them).<datetime>". Before, it would show the (only) 3 options, but those are not exhaustive anymore. When the user provides actualformats, those are shown (as before).reprfunctionality ofparam.type. This wasn't really used except for the tests that were recently added in ➖ Vendor Click and streamline Typer's functionality and code base #1774.Anydoes NOT raiseRuntimeError: Type not yet supportedanymore, but instead just falls through and gets a genericTypeAdapter(annotation)Note that as before, nothing in the module
typer/_click(a remnant of the recent vendoring) should be used directly by users and all of it is subject to change in the near future. Any changes in those modules are not considered to be "breaking".Bug fixes (also breaking bwd compat)
def main(age: int = typer.Option(15.3))will now throw a validation error by Pydantic instead ofint(15.3)converting it to15. I consider this a bug fix instead of a regression, and have added a testtest_int_rejects_float_defaultfor it.None(e.g.tuple[str, int, bool]), will fail validation as soon as one of those elements isNone. Our documented example of setting that tuple's default to(None, None, None)is not valid anymore, it should be set toNoneinstead. cf. change todocs_src/multiple_values/options_with_multiple_values/tutorial001_an_py310.py.test_default_infers_param_type.Decision points
_parse_cli_boolwas created to ensure we still parse""asFalseand to strip whitespace from something like" True ". This is just to mimic old Click behaviour. If we don't do this preprocessing (cleaner code base), the empty string and the non-stripped strings won't pass Pydantic validation and it would be slightly breaking.datetimetype if no formats are provided by the user (cf ☝️ "Breaking changes")intorfloatas datetime input, to present Unix timestamps as seconds or milliseconds since the Unix epoch? Cf also Fable's concern in point 4 of its review below 👇AI Disclaimer
Cursor was used as a micro-managed junior. Every edit was reviewed & understood by me.
TODO
Parameter.nametyped asstrinstead ofstr | None#1878Follow-up work
typer/_click