pylance-release icon indicating copy to clipboard operation
pylance-release copied to clipboard

Autocomplete stopped working on local class members

Open BabakAmini opened this issue 2 years ago • 6 comments

Environment data

  • Language Server version: v2023.7.40
  • OS: Windows 11
  • Python version: 3.11

Code Snippet

from aiohttp import ClientSession

class MyClass:
    a = 0
    b: int

    def __init__(self) -> None:
        self.c = 0

    async def d():
        pass

async def func():
    async with MyClass() as mc:
        mc.a = 1

Repro Steps

  1. Type mc. followed by Ctrl+Space. There is no autocomplete suggestion (the mc class instance is found, but none of the local class members are accessible via autocomplete).
  2. Change async with MyClass() as mc: to async with ClientSession() as mc: and try again. Autocomplete is working now.
  3. Uninstall or disable the Pylance extension and reload VS Code. Now autocomplete works for the local class as expected but this time none of the ClientSession class members appears in the suggested list.

Expected behavior

Autocomplete works for local class instances.

Actual behavior

Below is what is happening when the Pylance is installed:

And without Pylance:

  • Everything was working well, and these issues appeared for no reason by yesterday.
  • I'm running my code on a remote server, but I have the same issue on the local project as well.
  • These issues exist in both Python files and Jupyter notebooks.
  • Adding "python.languageServer": "Default" or "python.languageServer": "Pylance" to the settings.json didn't help.
  • Updating VS Code and all the extensions including Pylance (both the latest stable and preview releases) didn't help as well.

BabakAmini avatar Jul 28 '23 12:07 BabakAmini

Your class MyClass doesn't support the async context manager protocol, so it's invalid to use here. If you attempt to run your code, it will crash at runtime. To make this work, you would need to implement an __aenter__ and __aexit__ method in MyClass. The __aenter__ should return the context manager type, which provides the type to the variable mc in the statement async with MyClass() as mc.

If you enable type checking (set python.analysis.typeCheckingMode to "basic") in pylance, it will tell you about errors like this.

image

erictraut avatar Jul 28 '23 13:07 erictraut

@erictraut thanks for the reply. I already know about that. This is a sample code to demonstrate the issue in auto-completing. In my real project, this happened when I was trying to access members of my own class that were inherited from aiohttp.ClientSession. Adding __aenter__ to the class as follows doesn't help at all:

async def __aenter__(self) -> "MyClass":
        return self

BabakAmini avatar Jul 28 '23 14:07 BabakAmini

Have you tried adding both an __aenter__ and __aexit__? Both are required. If I add both of them, completion suggestions appear as expected. If I omit either of these methods, the code crashes at runtime if I call func.

from types import TracebackType

class MyClass:
    a = 0
    b: int

    def __init__(self) -> None:
        self.c = 0

    async def d(self):
        pass

    async def __aenter__(self) -> "MyClass":
        return self

    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc: BaseException | None,
        tb: TracebackType | None,
    ) -> None:
        pass

async def func():
    async with MyClass() as mc:
        mc.a = 1

erictraut avatar Jul 28 '23 14:07 erictraut

I tried different scenarios and got some weird results.

  • Adding __aexit__ as well as from types import TracebackType to my existing sample code doesn't help but replacing it by your entire code works.
  • I created a new file and implement the same code again. Autocomplete didn't work until I added __aenter__. No need to add __aexit__

Also, inside the class, suggestions do not appear for default methods except for __init__() and __init_subclass__ until I type five characters. When I press CTRL+Space, no suggestions are displayed, not even for the __init__ method. Therefore, I have to delete the typed word and manually retype it without utilizing the hotkey.

BabakAmini avatar Jul 28 '23 15:07 BabakAmini

Do you see the red squiggle under MyClass() in your screen recording? Pylance is telling you that you have a bug in your code. You need to fix that bug if you want your code to run without crashing. You also need to fix that error for type completions to work for mc. The type of the variable mc depends on the behavior of your __aenter__ and __aexit__ methods. If you don't define those methods, pylance cannot offer completion suggestions here. When a language server like pylance returns zero completion suggestions, VS Code offers some of its own suggestions based on other identifiers that it sees in the same file. That's what you're observing in this case.

Inside the class, you will get completions for methods that you are overriding from a base class. In your case, the only base class for MyClass is object, and the object class doesn't provide a __aenter__ or __aexit__ method, so you won't see any completion suggestions for these methods. The object class does define an __init__ and __init_class__ method, so pylance offers these as override suggestions.

Since MyClass is intended to be an async context manager, it should probably derive from the abstract base class typing.AsyncContextManager. If you do this, you'll then see override completion suggestions for __aenter__ and __aexit__.

image

Pylance appears to be working as designed. I don't see any bugs based on the behaviors you're observing. If there's a different behavior that you'd like to see, please consider filing an enhancement request.

erictraut avatar Jul 28 '23 19:07 erictraut

Great explanation, thanks.

But unlike your code editor, I don't have any suggestions after typing two underscores. Only after typing the fifth character, the only two available items appear:

This is also true for __aenter__:

But there is no suggestion for __aexit__, __call__ and other predefined keywords:

On the other hand, if I inherit my class from aiohttp.ClientSession which is what I'm going to do in my real project, even the __init__ definition doesn't suggest by Pylance:

Also, even though __aenter__ and __aexit__ are defined in aiohttp.ClientSession, no suggestion is provided for those methods too. However, after I defined all those methods manually, autocomplete works as expected:

BabakAmini avatar Jul 29 '23 20:07 BabakAmini

But unlike your code editor, I don't have any suggestions after typing two underscores.

@BabakAmini, I'm unable to reproduce the completion suggestion behavior that you mentioned in your last comment. Here's what I see after typing a single underscore using Pylance 2024.2.105:

image

If you're still seeing problems here, please open a new issue.

debonte avatar Mar 01 '24 17:03 debonte