pytype
pytype copied to clipboard
wrong-arg-types false positive
The following code will result in a false wrong-arg-types error:
# src/components.py
from typing import TYPE_CHECKING, Dict
if TYPE_CHECKING:
from .loaders import Foo
class Component:
def __init__(self, foos: Dict[int, "Foo"]):
pass
# src/loaders.py
from typing import Dict, NamedTuple
from .components import Component
class Foo(NamedTuple):
foo: int
def load() -> Component:
foos: Dict[int, Foo] = {}
return Component(foos=foos)
Running pytype . produces the following error:
pytype .
Computing dependencies
Analyzing 3 sources with 0 local dependencies
ninja: Entering directory `.pytype'
[5/5] check src.loaders
FAILED: /<dir>/.pytype/pyi/src/loaders.pyi
/<dir>/.venv/bin/python -m pytype.single --imports_info /<dir>/.pytype/imports/src.loaders.imports --module-name src.loaders -V 3.8 -o /<dir>/.pytype/pyi/src/loaders.pyi --analyze-annotated --attribute-variable-annotations --nofail --quick /<dir>/src/loaders.py
File "/<dir>/src/loaders.py", line 11, in load: Function Component.__init__ was called with the wrong arguments [wrong-arg-types]
Expected: (self, foos: Dict[int, src.loaders.Foo], ...)
Actually passed: (self, foos: Dict[int, Foo], ...)
For more details, see https://google.github.io/pytype/errors.html#wrong-arg-types
ninja: build stopped: subcommand failed.
Leaving directory '.pytype'
It seems like due to the slightly circular import inside the if TYPE_CHECKING that the two Foo types are seen as different.
Note that if you rename components.py to xcomponents.py (and change the import in loaders.py accordingly) then everything is fine. I assume that is because the order in which the files are processed has changed.
Note that this was not an issue in version 2021.9.9, but is in 2021.10.11.
Pytype version: 2021.10.11
This is a minimal example. If you want to see the full project, there is a PR upgrading Pytype which is failing CI here. The equivalent load function being here, and the type error is on Page - the equivalent of Foo.
Thanks for the detailed report! I was able to reproduce this locally using the example code. Interestingly, the error appears even with pytype-2021.9.9, so my guess is that a newer pytype version fixed some other issue that then exposed this one.
It's rather baffling to me that pytype seems to think there are two src.loaders.Foo classes - I have no idea how that can happen.
Agreed that it seems a bit crazy... I was very confused for a while (especially as the first time I tried to make my minimal example I changed the names of the files which solved the issue).
Let me know if I can help at all, but I have zero familiarity with the PyType code so I doubt there's much I can do. Happy to check a fix, though, and I'll be interested to hear what has gone wrong :smiley:
@rchen152 This is still an issue. Is there anything I can do to help?
The readme lists some debugging tools but I wasn't quite sure how to use them... if you can point me at a way to get some details on what's happening internally I can try and take a look.
Is it likely to be something in the Python code or something in C?
Sorry for the slow response! I was out of office for a couple weeks. This seems likely to be an issue in the Python code dealing with imports (so https://github.com/google/pytype/blob/main/pytype/load_pytd.py or https://github.com/google/pytype/blob/main/pytype/imports_map_loader.py). To debug this, I'd start by looking at the contents of the .pytype/ directory - there should be an pyi subdirectory showing the inferred type information and an imports directory mapping import paths to pyi stubs.
This is an issue for me too. Any word on getting it fixed?
I have a fix for this out for review.