✨ Use Pydantic for parameter validation - #1831
Open
svlandeg wants to merge 144 commits into
Open
Conversation
svlandeg
commented
Jun 10, 2026
| ("No", False), | ||
| ], | ||
| ) | ||
| def test_bool_convert_valid(cli_value: str, expected: bool) -> None: |
Member
Author
There was a problem hiding this comment.
This test currently mimics master behaviour 100%.
Contributor
…o feat/pydantic
…ept for str typed)
svlandeg
marked this pull request as ready for review
August 4, 2026 18:12
svlandeg
commented
Aug 4, 2026
| @@ -0,0 +1,22 @@ | |||
| from typing import Any | |||
Member
Author
There was a problem hiding this comment.
This module ended up being relatively small, we could also fold it in somewhere else.
Contributor
|
This pull request has a merge conflict that needs to be resolved. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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