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

Pylance is generating invalid type annotations (with misattributed module names) for typing.Any in completions and inlays. #6544

Open
hungarian-notation opened this issue Oct 10, 2024 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@hungarian-notation
Copy link

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.

pylance_2024.10.1_id_0.txt

@github-actions github-actions bot added the needs repro Issue has not been reproduced yet label Oct 10, 2024
@debonte debonte added bug Something isn't working and removed needs repro Issue has not been reproduced yet labels Oct 10, 2024
@debonte
Copy link
Contributor

debonte commented Oct 10, 2024

Thanks for the repro steps. I was able to reproduce this and will investigate.

@debonte
Copy link
Contributor

debonte commented Oct 14, 2024

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.

@debonte debonte assigned heejaechang and unassigned debonte Oct 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants