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

Union does not work with GenericModel #3276

Closed
3 tasks done
povilasb opened this issue Sep 29, 2021 · 4 comments
Closed
3 tasks done

Union does not work with GenericModel #3276

povilasb opened this issue Sep 29, 2021 · 4 comments
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@povilasb
Copy link

Checks

  • I added a descriptive title to this issue
  • I have searched (google, github) for similar issues and couldn't find anything
  • I have read and followed the docs and still think this is a bug

Bug

I've been toying with the master branch since autocomplete support got merged and seems like there is a regression since 1.8.2.
Consider this example:

from typing import Union, TypeVar, Generic
from pydantic.generics import GenericModel

T = TypeVar("T")


class Request(GenericModel, Generic[T]):
    url: str
    data: Union[str, bytes, None] = None


class PostData(Request[str]):
    url = "https://httpbin.org/anything"
    data = "rand data"

With pydantic 1.8.2 it produces such output:

$ pip3 install git+https://github.com/samuelcolvin/pydantic@v1.8.2
$ python3 -c "import pydantic.utils; print(pydantic.utils.version_info())"
            pydantic version: 1.8.2
            pydantic compiled: False
                 install path: /private/tmp/pyenv2/lib/python3.9/site-packages/pydantic
               python version: 3.9.6 (default, Jun 29 2021, 06:20:32)  [Clang 12.0.0 (clang-1200.0.32.29)]
                     platform: macOS-10.15.7-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions']
     
$ python3 demo.py
TypeError: The type of PostData.data differs from the new default value; if you wish to change the type of this field, please use a type annotation 

Which is ok, all I have to do is specify data type:

class PostData(Request[str]):
    url = "https://httpbin.org/anything"
    data: str = "rand data"

But with latest commit on master branch it yields a different error:

$ pip3 install git+https://github.com/samuelcolvin/pydantic@c256dcc
$ python3 -c "import pydantic.utils; print(pydantic.utils.version_info())"
             pydantic version: 1.8.2
            pydantic compiled: False
                 install path: /private/tmp/pyeanv/lib/python3.9/site-packages/pydantic
               python version: 3.9.6 (default, Jun 29 2021, 06:20:32)  [Clang 12.0.0 (clang-1200.0.32.29)]
                     platform: macOS-10.15.7-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions']
     
$ python3 demo.py
Traceback (most recent call last):
  File "/private/tmp/demo.py", line 16, in <module>
    class PostData(Request[str]):
  File "/private/tmp/pyeanv/lib/python3.9/site-packages/pydantic/main.py", line 236, in __new__
    if lenient_issubclass(inferred.type_, fields[var_name].type_):
  File "/private/tmp/pyeanv/lib/python3.9/site-packages/pydantic/utils.py", line 153, in lenient_issubclass
    return isinstance(cls, type) and issubclass(cls, class_or_tuple)
  File "/usr/local/Cellar/python@3.9/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/typing.py", line 713, in __subclasscheck__
    raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks

Any ideas? :)

@povilasb povilasb added the bug V1 Bug related to Pydantic V1.X label Sep 29, 2021
@luccasmmg
Copy link

It seems the problem is in this part of lenient_subclass.

def lenient_issubclass(cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...]]) -> bool:
    try:
        return isinstance(cls, type) and issubclass(cls, class_or_tuple)
    except TypeError:
        if isinstance(cls, WithArgsTypes): <------------------------------------
            return False
        raise  # pragma: no cover

If we remove this isinstance check, and just return False, the old behaviour comes back, and all the tests still pass, from my understanding the # pragma: no cover is from the coverage plugin, to hint that this code should never run, so i don't understand why the check is there, i can make a PR but will first wait someone with more experience than me comment here. This would be my first contribution to the project so i have no confidence in removing lines of code without someone checking first.

@Kludex
Copy link
Member

Kludex commented Apr 25, 2023

We don't have GenericModel on Pydantic V2 anymore.

For that reason, I'll be closing the issue. 🙏

@Kludex Kludex closed this as not planned Won't fix, can't repro, duplicate, stale Apr 25, 2023
@dmontagu
Copy link
Contributor

dmontagu commented May 1, 2023

I don't think this issue was specific to generic models (you didn't actually use the typevar in your model anyway), but either way, in v2, it seems to be fixed (noting that you just use BaseModel directly in v2, instead of GenericModel):

from typing import Union, TypeVar, Generic
from pydantic import BaseModel

T = TypeVar("T")


class Request(BaseModel, Generic[T]):
    url: str
    data: Union[str, bytes, None] = None


class PostData(Request[str]):
    url: str = "https://httpbin.org/anything"
    data: str = "rand data"

No error is raised when you run the code above

@povilasb
Copy link
Author

povilasb commented May 2, 2023

Cool! Thanks, will be playing around with v2 soon :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V1 Bug related to Pydantic V1.X
Projects
None yet
Development

No branches or pull requests

4 participants