pydantic root_validator:mypy严格类型检查

发布于 2025-02-13 09:16:37 字数 1234 浏览 0 评论 0 原文

我正在寻找一种“正确”的方法,以在Pydantic root_validator 装饰方法中进行严格的类型检查。

以下面的示例:在 validate_model 方法中,我希望能够使用MyPy严格的类型检查。由于 first_name age 均已通过此方法进行验证和类型检查,因此我们可以假设 values ['first_name'] 值['age'] 分别为'str'和'int'。

您可以看到#类型:ignore “ hack”,我用来允许键入提示和停止mypy抱怨,但这很丑陋,如果我更改任何变量类型,可以创建错误。理想情况下, root_validator 装饰的方法将具有 value 参数与类 SimpleModel 本身相同,否则应该有一种简单的方法将 SimpleModel 转换为 typedDict ,因此我们可以在 validate_model 签名中使用它,例如: def validate_model(cls,values:simpleModelTypedDict) - > 无论如何, SimpleModelTypedDict

,如果有人遇到了类似问题,请让我知道您如何解决它。

from pydantic import BaseModel, root_validator

class SimpleModel(BaseModel):
    first_name: str
    age: int

@root_validator(skip_on_failure=True)
def validate_model(cls, values: dict) -> dict:
    """checks there are no Bobs under 60 (sorry Bob!)"""
    first_name: str = values.get("first_name")  # type:ignore
    age: int = values.get("age")  # type:ignore
    if first_name.lower() == "bob" and age < 60:
        raise ValueError("No Bobs under 60")

    return values

I'm looking for the "proper" way to have strict type checking within a pydantic root_validator decorated method.

Take the example below: in the validate_model method, I want to be able to use mypy strict type-checking. As both first_name and age have been validated and type-checked by the time this method is called, we can assume that values['first_name'] and values['age'] are of type 'str' and 'int' respectively.

You can see the # type:ignore "hack" that I've used to allow type hinting and to stop mypy complaining, but it's pretty ugly, and could create bugs if I change any of the variable types. Ideally, a root_validator decorated method would have the values argument be of same type as the class SimpleModel itself, or there should be a simple way to convert SimpleModel into a TypedDict, so we can use this in the validate_model signature, for example:
def validate_model(cls, values: SimpleModelTypedDict) -> SimpleModelTypedDict

Anyway, if there is anyone out there that has run into a similar issue, please, let me know how you have tackled it.

from pydantic import BaseModel, root_validator

class SimpleModel(BaseModel):
    first_name: str
    age: int

@root_validator(skip_on_failure=True)
def validate_model(cls, values: dict) -> dict:
    """checks there are no Bobs under 60 (sorry Bob!)"""
    first_name: str = values.get("first_name")  # type:ignore
    age: int = values.get("age")  # type:ignore
    if first_name.lower() == "bob" and age < 60:
        raise ValueError("No Bobs under 60")

    return values

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清风夜微凉 2025-02-20 09:16:37

first_name age 的正确类型提示应分别为可选[str] 可选[int] .get() dict 的方法可以返回 none ,而值 dict of valivator将在那里是与提供的名称相对应的字段,或者是无效的:先前对该字段的验证失败。您使用 skip_on_failure = true ,我相信它应该涵盖先前失败的验证的情况,但是 .get()的返回值仍然可以是 none 如果由于某种原因,您尝试获取不存在的字段。

使用该类型提示,如果 first_name age 变量是 none ,则应验证您是否在尝试执行任何其他验证之前。

完整示例:

from typing import Optional

from pydantic import BaseModel, root_validator


class SimpleModel(BaseModel):
    first_name: str
    age: int


@root_validator(skip_on_failure=True)
def validate_model(cls, values: dict) -> dict:
    """checks there are no Bobs under 60 (sorry Bob!)"""
    first_name: Optional[str] = values.get("first_name")
    age: Optional[int] = values.get("age")
    if first_name is not None and age is not None and first_name.lower(
    ) == "bob" and age < 60:
        raise ValueError("No Bobs under 60")

    return values

The correct type hints for first_name and age should be Optional[str] and Optional[int], respectively. The .get() method of a dict can return None and this values dict of a validator will if there is no field that corresponds to the provided name or it is invalid: a validation failed previously for that field. You use skip_on_failure=True and I believe it should cover the case of a previously failed validation, but the return value of .get() can still be None if for some reason you try to get a field that does not exist.

Using that type hint you should validate if the first_name and age variables are None before trying to do any additional validations.

Full example:

from typing import Optional

from pydantic import BaseModel, root_validator


class SimpleModel(BaseModel):
    first_name: str
    age: int


@root_validator(skip_on_failure=True)
def validate_model(cls, values: dict) -> dict:
    """checks there are no Bobs under 60 (sorry Bob!)"""
    first_name: Optional[str] = values.get("first_name")
    age: Optional[int] = values.get("age")
    if first_name is not None and age is not None and first_name.lower(
    ) == "bob" and age < 60:
        raise ValueError("No Bobs under 60")

    return values

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文