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

Incorrect detection of generics with nested classes #6980

Closed
1 task done
M0dEx opened this issue Aug 1, 2023 · 1 comment · Fixed by #7119
Closed
1 task done

Incorrect detection of generics with nested classes #6980

M0dEx opened this issue Aug 1, 2023 · 1 comment · Fixed by #7119
Assignees
Labels
bug V2 Bug related to Pydantic V2

Comments

@M0dEx
Copy link

M0dEx commented Aug 1, 2023

Initial Checks

  • I confirm that I'm using Pydantic V2

Description

When nesting generic classes, one of which is a subclass of BaseModel (as shown in the example), Pydantic incorrectly raises a TypeError with the explanation that one of the classes is not generic:

Traceback (most recent call last):
  File "/Users/***/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/232.8660.197/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode
    coro = func()
           ^^^^^^
  File "<input>", line 12, in <module>
  File "/Users/***/Library/Caches/pypoetry/virtualenvs/***/lib/python3.11/site-packages/pydantic/main.py", line 607, in __class_getitem__
    raise TypeError(f'{cls} is not a generic class')
TypeError: <class '__main__.BrokenB'> is not a generic class

According to MyPy docs, the example should be valid (and without inheriting BaseModel works just fine.)

There is a workaround - by specifying the Generic keyword with the same TypeVar when inheriting the base class (A in the example code below), the check inside Pydantic succeeds.

Example Code

from typing import Generic, TypeVar

from pydantic import BaseModel

T = TypeVar("T")


class A(BaseModel, Generic[T]):
    a: T
    

class BrokenB(A[T]):
    b: T


class BrokenC(BrokenB[int]):  # FAILS
    pass


class FixedB(A[T], Generic[T]):
    b: T


class FixedC(FixedB[int]):  # WORKS
    pass

Python, Pydantic & OS Version

pydantic version: 2.1.1
pydantic-core version: 2.4.0
pydantic-core build: profile=release pgo=false mimalloc=true
install path: /Users/***/Library/Caches/pypoetry/virtualenvs/***-py3.11/lib/python3.11/site-packages/pydantic
python version: 3.11.2 (main, Mar 21 2023, 13:41:33) [Clang 14.0.0 (clang-1400.0.29.202)]
platform: macOS-13.5-x86_64-i386-64bit
optional deps. installed: ['typing-extensions']

Selected Assignee: @dmontagu

@M0dEx M0dEx added bug V2 Bug related to Pydantic V2 unconfirmed Bug not yet confirmed as valid/applicable labels Aug 1, 2023
@dmontagu dmontagu removed the unconfirmed Bug not yet confirmed as valid/applicable label Aug 14, 2023
@dmontagu
Copy link
Contributor

dmontagu commented Aug 14, 2023

Up to this point, the fact that this didn't work was more of an implementation detail than anything intentional, but I think I found a way to make it work. At least, I found a tweak in #7119 that makes this work properly and keeps all existing tests passing. If this introduces any new issues, I'll address them when reported.

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
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants