pytype icon indicating copy to clipboard operation
pytype copied to clipboard

Erroneous typing when importing pydantic BaseModel

Open agbaum opened this issue 3 years ago • 6 comments

Description

When importing the BaseModel from pydantic, pytype assumes that it is a module, instead of a class.

To Reproduce

Run pytype on a file containing:

from pydantic import BaseModel

class NewModel(BaseModel):
    pass

This code works fine at runtime.

Output

Computing dependencies
Analyzing 1 sources with 0 local dependencies
ninja: Entering directory `.pytype'
[1/1] check pydantic-type
FAILED: /Users/agtree/.pytype/pyi/pydantic-type.pyi 
/Users/agtree/Software/anaconda3/envs/typechecking/bin/python -m pytype.single --imports_info /Users/agtree/.pytype/imports/pydantic-type.imports --module-name pydantic-type -V 3.9 -o /Users/agtree/.pytype/pyi/pydantic-type.pyi --analyze-annotated --nofail --quick /Users/agtree/pydantic-type.py
File "/Users/agtree/pydantic-type.py", line 4, in <module>: Invalid base class: <instance of module> [base-class-error]

For more details, see https://google.github.io/pytype/errors.html#base-class-error
ninja: build stopped: subcommand failed.

Leaving directory '.pytype'

Notes

import pydantic

class NewModel(pydantic.BaseModel):
    pass

Does not throw an error.

Versions:

# Name                    Version                   Build  Channel
attrs                     21.2.0             pyhd3eb1b0_0  
ca-certificates           2021.10.26           hecd8cb5_2  
certifi                   2021.10.8        py39hecd8cb5_2  
dataclasses               0.8                pyh6d0b6a4_7  
importlab                 0.7                pyhd8ed1ab_0    conda-forge
libcst                    0.3.19           py39hecd8cb5_0  
libcxx                    12.0.0               h2f01273_0  
libffi                    3.3                  hb1e8313_2  
mypy_extensions           0.4.3            py39hecd8cb5_1  
ncurses                   6.3                  hca72f7f_2  
networkx                  2.6.3              pyhd3eb1b0_0  
ninja                     1.10.2.3                 pypi_0    pypi
openssl                   1.1.1m               hca72f7f_0  
pip                       21.2.4           py39hecd8cb5_0  
pydantic                  1.8.2            py39hca72f7f_0  
python                    3.9.7                h88f2d9e_1  
python_abi                3.9                      2_cp39    conda-forge
pytype                    2022.01.07       py39h9fcab8e_0    conda-forge
pyyaml                    6.0              py39hca72f7f_1  
readline                  8.1.2                hca72f7f_1  
setuptools                58.0.4           py39hecd8cb5_0  
sqlite                    3.37.0               h707629a_0  
tabulate                  0.8.9            py39hecd8cb5_0  
tk                        8.6.11               h7bc2e8c_0  
toml                      0.10.2             pyhd3eb1b0_0  
typed-ast                 1.5.1            py39h89e85a6_0    conda-forge
typing-extensions         3.10.0.2             hd3eb1b0_0  
typing_extensions         3.10.0.2           pyh06a4308_0  
typing_inspect            0.7.1              pyhd3eb1b0_0  
tzdata                    2021e                hda174b7_0  
wheel                     0.37.1             pyhd3eb1b0_0  
xz                        5.2.5                h1de35cc_0  
yaml                      0.2.5                haf1e3a3_0  
zlib                      1.2.11               h4dc903c_4  

agbaum avatar Jan 13 '22 22:01 agbaum

Huh, that's a funny bug. I'm a little surprised we haven't run into this before. pytype doesn't have type information for pydantic, so it generates a default import mapping like so:

pydantic/BaseModel .pytype/imports/default.pyi

(That "default.pyi" file just contains def __getattr__(name) -> Any.) But the default mapping makes an assumption that "from x import y" always means that y is a module, which is obviously not true. Probably for "from x import y" we should generate a pyi for x, not for y.

rchen152 avatar Jan 13 '22 23:01 rchen152

Anyone know of a workaround for this? It's a pretty big blocker here...

declension avatar Sep 09 '22 09:09 declension

@declension under the "Notes" in my original post there's a different way to import that works fine. You can also just tell pytype to ignore the line: https://google.github.io/pytype/user_guide.html#silencing-errors

agbaum avatar Sep 09 '22 18:09 agbaum

@declension under the "Notes" in my original post there's a different way to import that works fine. You can also just tell pytype to ignore the line: https://google.github.io/pytype/user_guide.html#silencing-errors

Thanks - though I really meant without changing lots of source code, but maybe that can do until a fix comes.

declension avatar Sep 10 '22 15:09 declension

Just ran into this one when testing pytype, imo renders pytype pretty useless and will block adoption for me.

lietu avatar Dec 04 '22 09:12 lietu

In addition to spuriously parsing from x import y as though y were a module, the underlying cause of this is https://github.com/google/pytype/issues/151 (no PEP 561 support in pytype). Pydantic is PEP 561 compliant.

lucaswiman avatar Jan 21 '23 02:01 lucaswiman