Issue with Type Checking Pydantic Generics in Pyright #9298
-
I’ve encountered an issue with type checking when using Pydantic’s simulated generics, and I’d like to understand if this is something that can be addressed or if there’s a recommended workaround. BackgroundPydantic’s generics behave differently compared to standard Python generics because they simulate generics in a way that results in the creation of a new, specific type at runtime. For example, from typing import TypeVar
from pydantic import RootModel
_T = TypeVar("_T")
CustomList = RootModel[list[_T]]
print(isinstance(CustomList[int]([1, 2, 3]), CustomList)) # False
print(isinstance(CustomList[int]([1, 2, 3]), CustomList[int])) # True
print(isinstance(CustomList[int]([1, 2, 3]), CustomList[float])) # False The code runs as expected, and Pydantic is able to distinguish between different generic instances at runtime. However, Pyright flags the following errors:
QuestionIs there a way to make Pyright more aware of Pydantic’s runtime behavior with generics, or a way to bypass these errors without completely disabling type checking? I understand that Pyright is adhering to standard Python type rules, but since Pydantic can distinguish these types at runtime, it would be helpful if there were a mechanism to reflect this behavior in Pyright’s type checking. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Pyright adheres to the typing standard. In areas where pydantic deviates from standard behaviors, there will be mismatches. If you or the maintainers of pydantic would like to propose extensions or modifications to the typing system, the Python typing forum is a good place to discuss such proposals. I can imagine different levels of standardized support for pydantic's behavior. Level 1: Assume standard behaviors. This is what pyright and other conformant type checkers do today. Level 2: A static type checker could detect that a class has a custom Level 3: All of the custom behaviors of pydantic, including its Today we are at level 1. Arguably, level 2 would be a step backward in terms of usability because you'd lose many other benefits of static type checking for these classes, including type narrowing. That means level 2 is probably not a good place to be, and we'd probably need to go all the way to level 3. This is possible, but it would require a significant effort in terms of spec'ing and implementation. It would probably require a full PEP. If you want to pursue something along these lines, I recommend posting to the typing forum. Someone else in the typing community may have other ideas — perhaps some blend of my level 2 and 3 above — that achieves a good set of tradeoffs. |
Beta Was this translation helpful? Give feedback.
Pyright adheres to the typing standard. In areas where pydantic deviates from standard behaviors, there will be mismatches. If you or the maintainers of pydantic would like to propose extensions or modifications to the typing system, the Python typing forum is a good place to discuss such proposals.
I can imagine different levels of standardized support for pydantic's behavior.
Level 1: Assume standard behaviors. This is what pyright and other conformant type checkers do today.
Level 2: A static type checker could detect that a class has a custom
__class_getitem__
with a return type other thanGenericAlias
. In such a case, it could assume that the class should no longer be treated like a …