Pylance is generating invalid type annotations (with misattributed module names) for typing.Any in completions and inlays.
Environment data
- Pylance version: 2024.10.1
- OS and version: Windows 10 Pro 22H2 19045.4894
- Python version (& distribution if applicable, e.g. Anaconda): Python 3.12.6
Settings.json
{
"python.analysis.typeCheckingMode": "basic",
"python.analysis.inlayHints.functionReturnTypes": true,
"python.experiments.enabled": false
}
I'm running Python in a venv with no external modules present:
(.venv) C:\Users\REDACTED\REDACTED\test>pip list
Package Version
------- -------
pip 24.2
(.venv) C:\Users\REDACTED\REDACTED\test>python -V
Python 3.12.6
Repro Steps
Entering this code:
import os
class Foo:
def __call__
and then triggering the suggested completion for __call__
Expected behavior
I would anticipate either of the two following outputs:
import os
from typing import Any
class Foo:
def __call__(self, *args: Any, **kwds: Any) -> Any:
pass
or at the very least:
import os
class Foo:
def __call__(self, *args, **kwds):
pass
Actual behavior
Pylance incorrectly attributes Any to the os module, or some other module if it is imported before os.
import os
class Foo:
def __call__(self, *args: os.Any, **kwds: os.Any) -> os.Any:
pass
import re
import os
class Foo:
def __call__(self, *args: re.Any, **kwds: re.Any) -> re.Any:
pass
Pylance is still aware this is incorrect on some level and immediately flags the Any tokens with reportAttributeAccessIssue.
On the other hand, Ctrl+Clicking on the Any token takes me to vscode\extensions\ms-python.vscode-pylance-2024.10.1\dist\typeshed-fallback\stdlib\typing.pyi, indicating that it does have some idea where Any actually comes from.
The same issue occurs when double clicking on some inlays that suggest the Any type. In this example, the return type on baz is the result of double clicking an inlay hint that was rendered as -> Any | None.
import os
some_bool: bool
some_string: str
def baz() -> os.Any | None:
if some_bool:
return globals()[some_string]
I was only able to trigger the bug on an inlay when the Any type was originating from outside my code and was part of a union type with something else. Removing the condition or using some locally created value that identifies as dict[str, any] causes pylance to instead insert a comment of the type annotation without any module names.
Speculation
This issue isn't specific to the os module, but it doesn't trigger for all modules. It seems to me that the issue occurs when the pyi file for any imported module itself imports Any from typing. Since pylance will take me to typing.pyi when I click on the token, I can only assume that pylance knows perfectly well what module Any actually comes from, but it is somehow being associated with the namespace it is first imported into when it comes time to format the type for insertion in my code.
Previously I was getting this error even without any import statements, but in the course of debugging I deleted ms-python.vscode-pylance-2024.10.1\dist\.cache and reinstalled the extension. After these steps, it began correctly attributing the Any type to typing as long as no problematic modules were imported, but as you can see all is still not well.
Apologies if this is already known. I searched around the issues and I found some type annotation related stuff (hence why I tried disabling A/B testing) but nothing jumped out as this problem specifically.
Thanks for the repro steps. I was able to reproduce this and will investigate.
It seems to me that the issue occurs when the pyi file for any imported module itself imports Any from typing.
Yes, this is correct.
@heejaechang, at https://github.com/microsoft/pyrx/blob/main/packages/pylance-internal/src/common/importUtils.ts#L204, we're assuming that if the desired type is in the target module's symbol table, that we should import it from there. But that's not the case here. We're looking at the symbol table of os/__init__.pyi and indeed we find typing.Any there, but we're missing some additional filtering/validation here I believe.
You're probably the best person to fix this, so I'm reassigning to you.