✨ 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.
|
WIP: I'm now self reviewing this with Fable, and it's got opinions 🥲 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)
Description
Make Pydantic a required dependency and rely on it for parameter validation.
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]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).<%Y-%m-%d>instead of<%Y-%m-%d|%Y-%m-%dT%H:%M:%S|%Y-%m-%d %H:%M:%S>) even though all three (and more) will work. It's not just those three anymore, so it felt arbitrary to show 3 out ofn. We can decide to reverse the change and keep showing those three formats though. Alternatively, we could just display something like<datetime>but then the user might be unsure on how to exactly provide that.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)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.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")AI Disclaimer
Cursor was used as a micro-managed junior. Every edit was reviewed & understood by me.
TODO
Parameter.nametyped asstrinstead ofstr | None#1878