Closed nineteendo closed 7 months ago
Thanks for your issue. If you look at the os.py
module, the assignment of the path
alias symbol is dynamic and platform dependent. In typeshed, which provides type hints for static type checking, path
is defined as a module(path.pyi
), while in actual library, path
is treated as a symbol. This discrepancy and the dynamic behavior may lead static type checkers to struggle with associating the two so it drops that info somewhere.
@nineteendo, any such change would need to be made to the typeshed stub file os/__init__.pyi
here. Pylance / pyright consume these typeshed stubs, as do many other Python type checkers and static analysis tools.
I'm saying that pyright (the type checker that underlies pylance) has no knowledge of path
or path.os
. Its behavior is dictated entirely by the type stubs that are provided by typeshed. If you want the behavior to change with regard to os.path
, this would require a modification to the typeshed stubs. I don't think there's anything actionable for us to do in pyright or pylance here other than to pull an updated copy of the typeshed stubs if and when such a change is made. I typically pull a new version of the typeshed stubs every two weeks.
I don't know the reason why the typeshed maintainers chose to model os.path
the way they did. You would need to explore that with them if you want to suggest a change.
@StellaHuang95, @erictraut, the issue is simply that no kind of re-export is ever included in the suggestions, only definitions. I've updated the overview to reflect this. Is this something manageable to fix, or do we need to rely on stubs for every re-export?
As I said above, Pylance has no specific knowledge of this (or any other) module or its imports. The behavior is driven by the the type information in the type stubs. If you want the behavior to change, the typeshed stubs will need to be modified accordingly. You can file a bug report or a PR in the typeshed project if you'd like.
Hope Eric answers your question about os.path
. As for your other question about auto-import not suggesting re-exports, we will investigate to see what's going on. Seems like re-export should work in this case. If it's in the __all__
, it should be an exported symbol.
@erictraut, I'm talking about imports in the stubs. Pylance seems to only look at the definitions and ignores the re-exports. The same happens with regular Python code.
I was able to get it working by explicitly defining all functions:
It doesn't work with __all__
and import as
:
@erictraut, @StellaHuang95 are there any updates on this? It's been 2 weeks, do you have any idea what's going on? It's a bit strange, as the regular import completions work perfectly fine. And as the auto-import functionality isn't open source I can't look further into this.
@nineteendo, you started this thread by reporting a problem with os.path
. I've already provided an explanation of why you're seeing the auto-import behavior with os.path
. That behavior is intended, and it won't change unless/until there is a corresponding change in the typeshed stubs. If that's the main issue you're reporting here, then we should close this issue because there's nothing actionable for pyright or pylance at this time. You can pursue a change in the typeshed stubs if you'd like, and pyright will pick up any resulting changes when I next refresh the bundled typeshed stubs.
If there's another issue that doesn't involve os.path
, let us know.
I think you must have misunderstood me.
You started this thread by reporting a problem with
os.path
.
Yes, but this problem applies to ALL modules using re-exports in particular to my own code. (see the issue description for more details).
I've already provided an explanation of why you're seeing the auto-import behavior with
os.path
. That behavior is intended, and it won't change unless/until there is a corresponding change in the typeshed stubs.
The problem is that typeshed would be forced to replace all re-exports with explicit definitions if they want to support auto imports in vscode, leading to a lot of duplicate code.
You can pursue a change in the typeshed stubs if you'd like, and pyright will pick up any resulting changes when I next refresh the bundled typeshed stubs.
I will do that, but they'll probably argue that this is a problem for Pylance to fix.
Yes, but this problem applies to ALL modules using re-exports in particular to my own code. (see the issue description for more details).
The os.path
case is very distinct because of the way path
is defined in the stubs. You can't generalize from that case.
It sounds like os.path
is a red herring. Let's set it aside for now. If you're seeing an issue with other re-exported symbols, then we'll need a repro case. @StellaHuang95, have you been able to repro this issue for cases other than os.path
?
@erictraut, just tried with this simple example,
# hello/__init__.py
__all__ = ["hello_world", 'function1']
from ._hello import hello_world as hello_world
def function1():
pass
# hello/_hello.py
def hello_world():
print("Hello, world!")
# main.py
# type `function1` or `hello_world`
I was able to repro it. I am getting auto-import for function1
but not hello_world
. Seems like re-export should work in this case since it's in the __all__
and supposed to be an exported symbol. I can take a look and see what's going wrong.
@StellaHuang95, it looks like this is because of this code in autoImporter.ts. It looks like this code was introduced 3.5 years ago (on 10/7/2020) by Jake. The comment says "We don't include import alias in auto import for workspace files." I'm not sure why. Maybe it's to avoid duplicate symbols in the completion suggestions? In this case it's not a duplicate because the original symbol definition is not visible by virtue of being defined in a private submodule (i.e. one whose name begins with an underscore).
So this behavior is specific to: 1) workspace modules (as opposed to modules that are installed in the Python environment), 2. a non-private workspace module that imports a symbol from a private workspace submodule and re-exports it as public.
This has nothing to do with type stubs, so that was a complete red herring.
This is not supported yet due to perf considerations, but we have added it to our backlog for future enhancements. I am going to close this one as duplicate since it's a subitem of https://github.com/microsoft/pylance-release/issues/5434. Please track that ticket for progress. The order in which we address backlog items depends on their priority and our current bandwidth. We will provide an update below that ticket once it's resolved. Thanks for your patience.
This still doesn't explain the behaviour in the stdlib, let's track that further in #5731.
Environment data
Code Snippet
Repro Steps
hello_world
Expected behavior
First suggestion is
hello_world
fromhello
and can be imported with Tab.Actual behavior
hello_world
is not in the list:Workaround
This can be fixed with stubs though, but that's annoying if the source files are fully typed:
Logs