microsoft / pylance-release

Documentation and issues for Pylance
Creative Commons Attribution 4.0 International
1.72k stars 766 forks source link

Pylance suggests importing only those variables that start with a capital letter #3948

Closed VolDr closed 1 year ago

VolDr commented 1 year ago

Environment data

Python analysis settings in settings.json:

  "python.analysis.inlayHints.functionReturnTypes": true,
  "python.analysis.inlayHints.variableTypes": true,
  "python.analysis.diagnosticMode": "workspace",
  "python.analysis.autoImportCompletions": true,
  "python.analysis.completeFunctionParens": true,
  "python.analysis.autoImportUserSymbols": true,
  "python.analysis.indexing": true,
  "python.analysis.inlayHints.pytestParameters": true,

Code Snippet

I have the following project structure:

project_dir
└── app
    └── package
         ├── module1.py
         └── module2.py

module1.py looks like this:

Foo = "Foo"

bar = "bar"

Repro Steps

I start writing code in a module2.py like below:

Expected behavior

Vs Code offers auto-completion to Foo and bar and makes auto-import the corresponding variable.

Actual behavior

Vs Code offers auto-completion to Foo and does not offer auto-completion for bar.

heejaechang commented 1 year ago

unfortunately, this is by design. otherwise, you will get thousands of all variables defined in every python files in completion.

that said we could make variables in __all__ to show up regardless whether it starts with capital or not.

wtfzambo commented 1 year ago

we could make variables in __all__ to show up regardless whether it starts with capital or not.

I have a related issue when it comes to __all__ and autosuggestion.

Using the same settings as OP, I find that no matter if I define __all__, autocomplete always shows every possible symbol, including imports, at least in user defined modules.

E.g.

modA.py

import random

__all__ = ['Foo', 'bar']

Foo = "Foo"
bar = "bar"

def _private():
    pass

modB.py

However, it seems to work as expected when importing from other (builtin?) modules, such as pathlib:

I don't understand where the problem comes from, any idea?

erictraut commented 1 year ago

I think there may be a misunderstanding of what __all__ does in Python. It indicates to the runtime which symbols should be imported when a wildcard import is used. It does not prevent a non-wildcard import statement from importing other symbols. As such, it really shouldn't have any impact on auto-import.

There are additional rules related to __all__ for a library that is marked as "py.typed". It helps distinguish between private and public symbols in a "py.typed" module. But those rules don't apply to normal user code or libraries that are not marked "py.typed".

wtfzambo commented 1 year ago

There are additional rules related to __all__ for a library that is marked as "py.typed".

Thanks for the explanation. So in theory, if I were to add a py.typed file to my package, I could obtain what I was trying to do ?

erictraut commented 1 year ago

If the package is installed as a library in your Python environment, that should work. You could install it directly (in which case the files will be copied to your site-packages directory) or use an editable install (which uses a symbolic link to point back to the files in your project).

heejaechang commented 1 year ago

@wtfzambo the completion you see is not auto import so it is not the same issue as this issue. so it would be better to open new issue rather than piggyback on this one.

that said, the current import completion behavior is it will show every symbols including private symbols defined from the imported module unless the module is stub file or module from py.typed package. but py.typed is for library, not local project.

wtfzambo commented 1 year ago

Thanks for the clarifications @erictraut and @heejaechang :)

heejaechang commented 1 year ago

We actually had this implemented for long time - https://github.com/microsoft/pyrx/pull/1217

lower case variable must be in __all__ to show up in auto import

abduakhatov commented 1 month ago

In my case it is still not working even with __all__. I dont know what to share so that to make the issue clear.

debonte commented 1 month ago

@abduakhatov, please open a new issue.

When you do that, can you share the project where you're seeing this issue? If not, are you trying to import symbols from a public package? Sharing the package name + version and your import statement might be sufficient in that case.