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

Import completion not suggesting private symbol included in __all__

Open mayankj opened this issue 2 years ago • 8 comments

I have a project structured like

appname:
  - utils:
    -  __init__.py
    - _util1.py -> contains a function called `util1`
    - _util2.py -> contains a function called `util2`
   

__init__.py imports all the _utilx.py modules and populates __all__ with the right util methods but auto-import doesn't suggest appname.utils.utilx when trying to use utilx

when I rename _util1.py to change util1.py, auto-import starts working again. Is this expected?

mayankj avatar Apr 19 '23 21:04 mayankj

Thanks for the issue.

I believe this is by design as talked about here: https://github.com/microsoft/pylance-release/issues/2490

One way to work around this is to explicitly import all of the private members in your __init__.py. They'll then end up in the utils package:

# __init__.py
from _utils1 import *
from _utils2 import *
# test.py
import appname.utils
appname.utils.util1() # This should be available now

rchiodo avatar Apr 20 '23 16:04 rchiodo

@rchiodo I've looked at #2490 and I understand that symbols inside files starting with an underscore will not show up. However, here, I'm explicitly importing symbols from the private symbols in my init.py and then adding it to __all__ in my init.py (which is not private). So the functions that were added to __all__ should be picked up by the autocomplete right?

mayankj avatar Apr 24 '23 15:04 mayankj

Sorry but privates are still excluded even if included in __all__. Only if you do what I suggested will they end up being exported from __init__

rchiodo avatar Apr 24 '23 16:04 rchiodo

this might work too in the __init__.py

from _utils1 import util1 as util1

“from X import A as A” (a redundant symbol alias), see https://microsoft.github.io/pyright/#/typed-libraries

bschnurr avatar Apr 24 '23 16:04 bschnurr

This makes it seem like including them in __all__ should work:

A module can expose an __all__ symbol at the module level that provides a list of names that are considered part of the interface. The __all__ symbol indicates which symbols are included in a wildcard import. All symbols included in the __all__ list are considered public even if the other rules above would otherwise indicate that they were private. For example, this allows symbols whose names begin with an underscore to be included in the interface.

Reopening.

rchiodo avatar Apr 24 '23 16:04 rchiodo

Hi, is there a timeline on when this might get fixed? wanted to let my team so we can figure out a workaround accordingly :)

mayankj avatar May 25 '23 23:05 mayankj

Generally, upvotes determine the priority of things. This item having a single upvote means it's low priority at the moment.

rchiodo avatar May 25 '23 23:05 rchiodo

@mayankj, I wasn't sure if utils was a directory within your workspace or a package in your environment, so I tried it both ways.

I know it's been a while since you opened this issue, but if you can provide any guidance on how to repro this, I'd appreciate it.

Local files

If it's a directory in your workspace, then I believe you are hitting https://github.com/microsoft/pylance-release/issues/5159.

Here's how I set that up: <workspace-root>\utils\__init__.py

from _util1 import util1
from _util2 import util2

__all__ = [ "util1", "util2" ] 

<workspace-root>\utils\_util1.py

def util1(): pass

<workspace-root>\utils\_util2.py

def util2(): pass

<workspace-root>\test.py Tried auto-import here. It fails. -- https://github.com/microsoft/pylance-release/issues/5159

Package

I wasn't able to repro any issues when utils was a package in my venv. I tried downgrading to 2023.4.30 which was the latest stable release when you filed this issue, and I couldn't repro it there either.

Here's how I set that up: <workspace-root>\.venv\lib\site-packages\utils\__init__.py

from ._util1 import util1
from ._util2 import util2

__all__ = [ "util1", "util2" ] 

<workspace-root>\.venv\lib\site-packages\utils\__init__.py

def util1(): pass

<workspace-root>\.venv\lib\site-packages\utils\__init__.py

def util2(): pass

<workspace-root>\test.py Tried auto-import here and succeeded.

debonte avatar Feb 07 '24 02:02 debonte

@debonte, you're correct - it is a directory in our workspace

mayankj avatar Mar 04 '24 05:03 mayankj

Thanks for confirming. I'm resolving this as a duplicate of #5159.

debonte avatar Mar 04 '24 15:03 debonte