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

GenericModel[Any] raises ValidationError for GenericModel[SomeModel] #9414

Open
1 task done
gsakkis opened this issue May 8, 2024 · 1 comment
Open
1 task done
Labels
bug V2 Bug related to Pydantic V2 pending Awaiting a response / confirmation

Comments

@gsakkis
Copy link
Contributor

gsakkis commented May 8, 2024

Initial Checks

  • I confirm that I'm using Pydantic V2

Description

Annotating a field as ResponseModel[Any] (where ResponseModel is a generic BaseModel) fails to validate values of type ResponseModel and ResponseModel[Product]; it only validates values of ResponseModel[Any].

On the other hand annotating the field as ResponseModel validates all three cases, however mypy gives Missing type parameters for generic type "ResponseModel".

Questions:

  • Is the ResponseModel[Any] validation working as expected or it's a bug?
  • Is it safe to # type: ignore the second version that seems to be working?

Example Code

from typing import Any, Generic, TypeVar

from pydantic import BaseModel, ValidationError

T = TypeVar("T")


class ResponseModel(BaseModel, Generic[T]):
    content: T


class Product(BaseModel):
    name: str
    price: float


class Order(BaseModel):
    id: int
    product: ResponseModel[Any]
    # replacing the previous annotation with the following succeeds at runtime but fails type checking
    # product: ResponseModel


product = Product(name="Apple", price=0.5)
response1: ResponseModel[Any] = ResponseModel[Any](content=product)
response2: ResponseModel[Any] = ResponseModel(content=product)
response3: ResponseModel[Any] = ResponseModel[Product](content=product)

for response in response1, response2, response3:
    try:
        order = Order(id=1, product=response)
        print(f"{response!r} succeeded")
    except ValidationError:
        print(f"{response!r} failed")

Output:

ResponseModel[Any](content=Product(name='Apple', price=0.5)) succeeded
ResponseModel(content=Product(name='Apple', price=0.5)) failed
ResponseModel[Product](content=Product(name='Apple', price=0.5)) failed

Python, Pydantic & OS Version

pydantic version: 2.7.1
        pydantic-core version: 2.18.2
          pydantic-core build: profile=release pgo=true
               python version: 3.11.8 | packaged by conda-forge | (main, Feb 16 2024, 20:49:36) [Clang 16.0.6 ]
                     platform: macOS-14.1-arm64-arm-64bit
             related packages: mypy-1.9.0 typing_extensions-4.10.0 pydantic-settings-2.2.1
                       commit: unknown
@gsakkis gsakkis added bug V2 Bug related to Pydantic V2 pending Awaiting a response / confirmation labels May 8, 2024
@sydney-runkle
Copy link
Member

Hi @gsakkis,

Thanks for your questions. This comment might help to add some context regarding some of the nuances with validation and parametrized generics: #8884 (comment).

The case with Any is interesting. This does seem a bit buggy to me. Specifically, this works:

from typing import Any, Generic, TypeVar

from pydantic import BaseModel, ValidationError

T = TypeVar("T")


class ResponseModel(BaseModel, Generic[T]):
    content: T


class Product(BaseModel):
    name: str
    price: float


class Order(BaseModel):
    id: int
    product: ResponseModel[Any]
    # replacing the previous annotation with the following succeeds at runtime but fails type checking
    # product: ResponseModel


product = Product(name="Apple", price=0.5)
response1: ResponseModel[Any] = ResponseModel[Any](content=product)
response2: ResponseModel[Any] = ResponseModel(content=product)
response3: ResponseModel[Any] = ResponseModel[Product](content=product)

for response in response1, response2, response3:
    try:
        order = Order(id=1, product=response.model_dump())
        print(f"{response!r} succeeded")
    except ValidationError:
        print(f"{response!r} failed")

I'm going to chat with @dmontagu, our resident generics expert, about this and will get back to you!

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 pending Awaiting a response / confirmation
Projects
None yet
Development

No branches or pull requests

2 participants