Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No validation occurred after using Annotated. #6612

Closed
1 task done
vagreargnatry opened this issue Jul 12, 2023 · 4 comments
Closed
1 task done

No validation occurred after using Annotated. #6612

vagreargnatry opened this issue Jul 12, 2023 · 4 comments
Assignees
Labels
bug V2 Bug related to Pydantic V2 unconfirmed Bug not yet confirmed as valid/applicable

Comments

@vagreargnatry
Copy link

vagreargnatry commented Jul 12, 2023

Initial Checks

  • I confirm that I'm using Pydantic V2

Description

Please take a look at this issue first: #5006

TimeOne can make VS Code Python type inference work properly, but TimeOne did not undergo validation.

Example Code

from pydantic import BaseModel, conint
from typing import Annotated

Hour = Annotated[int, conint(gt=0, lt=25)]
Minute = Annotated[int, conint(gt=0, lt=61)]


class TimeOne(BaseModel):
    hour: Hour
    minute: Minute


class TimeTwo(BaseModel):
    hour: conint(gt=0, lt=25)
    minute: conint(gt=0, lt=61)


print(TimeOne(hour=-1, minute=10))
print(TimeTwo(hour=-1, minute=10))

# output:
#
# hour=-1 minute=10
# Traceback (most recent call last):
#   File "/home/{{username}}/learn/sample-1/sample_1/main.py", line 19, in <module>
#     print(TimeTwo(hour=-1, minute=10))
#           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
#   File "/home/{{username}}/.cache/pypoetry/virtualenvs/sample-1-wFgLiamH-py3.11/lib/python3.11/site-packages/pydantic/main.py", line 150, in __init__
#     __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)
# pydantic_core._pydantic_core.ValidationError: 1 validation error for TimeTwo
# hour
#   Input should be greater than 0 [type=greater_than, input_value=-1, input_type=int]
#     For further information visit https://errors.pydantic.dev/2.1.2/v/greater_than

Python, Pydantic & OS Version

pydantic version: 2.0.2
        pydantic-core version: 2.1.2 release build profile
                 install path: /home/{{username}}/.cache/pypoetry/virtualenvs/sample-1-wFgLiamH-py3.11/lib/python3.11/site-packages/pydantic
               python version: 3.11.4 (main, Jul 10 2023, 10:28:44) [GCC 13.1.1 20230429]
                     platform: Linux-6.4.2-arch1-1-x86_64-with-glibc2.37
     optional deps. installed: ['typing-extensions']

Selected Assignee: @adriangb

@vagreargnatry vagreargnatry added bug V2 Bug related to Pydantic V2 unconfirmed Bug not yet confirmed as valid/applicable labels Jul 12, 2023
@vagreargnatry
Copy link
Author

I am trying to change some of the code to the following code:

Hour = Annotated[conint(gt=0, lt=25), int]
Minute = Annotated[conint(gt=0, lt=61), int]

This can lead to validation and enable vscode Python type inference to work properly, but I'm not sure why.

@Viicos
Copy link
Contributor

Viicos commented Jul 12, 2023

In v2 conint already returns a Annotated type:

pydantic/pydantic/types.py

Lines 132 to 159 in c4b40f2

def conint(
*,
strict: bool | None = None,
gt: int | None = None,
ge: int | None = None,
lt: int | None = None,
le: int | None = None,
multiple_of: int | None = None,
) -> type[int]:
"""A wrapper around `int` that allows for additional constraints.
Args:
strict: Whether to validate the integer in strict mode. Defaults to `None`.
gt: The value must be greater than this.
ge: The value must be greater than or equal to this.
lt: The value must be less than this.
le: The value must be less than or equal to this.
multiple_of: The value must be a multiple of this.
Returns:
The wrapped integer type.
"""
return Annotated[ # type: ignore[return-value]
int,
Strict(strict) if strict is not None else None,
annotated_types.Interval(gt=gt, ge=ge, lt=lt, le=le),
annotated_types.MultipleOf(multiple_of) if multiple_of is not None else None,
]

The pylance error is unfortunate, but you can still use the following:

from typing import Annotated

from annotated_types import Interval
from pydantic import BaseModel

Hour = Annotated[int, Interval(gt=0, lt=25)]
Minute = Annotated[int, Interval(gt=0, lt=61)]

@adriangb
Copy link
Member

It might make sense to do something similar to #6605

@adriangb
Copy link
Member

Here's a runnable version of the approach @Viicos suggested above:

from typing import Annotated

from annotated_types import Interval

from pydantic import BaseModel, Field

Hour = Annotated[int, Field(gt=0, lt=25)]
Minute = Annotated[int, Interval(gt=0, lt=61)]


class TimeOne(BaseModel):
    hour: Hour
    minute: Minute


print(TimeOne(hour=-1, minute=10))
#> hour -> Input should be greater than 0 [type=greater_than, input_value=-1, input_type=int]

Note that you can use Interval directly or Field, whichever you prefer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V2 Bug related to Pydantic V2 unconfirmed Bug not yet confirmed as valid/applicable
Projects
None yet
Development

No branches or pull requests

3 participants