我使用 pydantic 从 JSON 文件加载数据,这些文件可以具有不同的参数,在本例中为 x 或 y。我使用
Loader
类将它们加载到 pydantic 模型中,以便我可以在运行时验证它们,但我无法使我的代码与 mypy 兼容。它失败并出现以下错误:Expected type 'Type[T]', got 'UnionType' instead
。
我有 mypy 1.10.0 和 pydantic 2.7.0。
这是我的用例的可重现示例:
from typing import Iterator, Type, TypeVar, Union
from pydantic import BaseModel, TypeAdapter
class A(BaseModel):
x: int
class B(BaseModel):
y: int
T = TypeVar("T", bound=BaseModel)
class Loader:
def load_models(self, model_class: Type[T]) -> Iterator[T]:
# logic to load models
my_dict = {"x": 1} # fake data for testing
yield TypeAdapter(model_class).validate_python(my_dict)
my_dict = {"y": 2} # fake data for testing
yield TypeAdapter(model_class).validate_python(my_dict)
ModelAOrB = A | B
print(list(Loader().load_models(ModelAOrB)))
有没有办法让它与 mypy 一起工作?
感谢这篇文章,我找到了一种方法来做我想做的事情,关键是使用 pydantic 中的
RootModel
并直接将其用作参数。不要忘记返回 .root
,mypy 现在接受以下代码:
class Loader:
def load_models(self, root_model: type[RootModel[T]]) -> Iterator[T]:
# logic to load models
my_dict = {"x": 1} # fake data for testing
yield root_model.model_validate(my_dict).root # or root_model(**my_dict).root
my_dict = {"y": 2} # fake data for testing
yield root_model.model_validate(my_dict).root # or root_model(**my_dict).root
ModelAOrB = A | B
print(list(Loader().load_models(RootModel[ModelAOrB])))