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

Pyright fails to detect aliased module with submodules #3884

Closed
ianliu opened this issue Aug 31, 2022 · 3 comments
Closed

Pyright fails to detect aliased module with submodules #3884

ianliu opened this issue Aug 31, 2022 · 3 comments
Labels
as designed Not a bug, working as intended

Comments

@ianliu
Copy link

ianliu commented Aug 31, 2022

Describe the bug
When aliasing a module, like import foo as f, one can access submodules with f.sub in the code, considering the submodule was brought into scope with imoport foo.sub, but Pyright fails in two ways: it reports that import foo.sub is unused and errors on f.sub.whatever.

To Reproduce

First, create a module foo like so:

mkdir foo
touch foo/__init__.py
echo "class User: pass" > foo/user.py

Now the following code will fail in pyright:

import foo as f
import foo.user    # "foo.user" is not accessed
print(f.user.User) # "user" is not a known member of module

Pyright version
1.1.267

Expected behavior
I would expect the code to type-check.

Additional context
Tested on mypy, and it type-checks

@erictraut
Copy link
Collaborator

This is intended behavior. You are relying on implicit import side effects, and pyright intentionally does not model those because they lead to code fragility.

If you want your code to work with pyright, you will need to change it to avoid this pattern. Instead, you can do one of the following:

  1. Use the unaliased fully-qualified name to access symbols in the submodule.
  2. Use an as clause to create an explicit alias to the submodule, as in import foo.user as u and then u.User.

@erictraut erictraut added the as designed Not a bug, working as intended label Aug 31, 2022
@davidism
Copy link

davidism commented Sep 13, 2022

In Flask-SQLAlchemy, I want to do this with SQLAlchemy and its submodules. `sqlalchemy... is a long name to type everywhere, and there's so many objects used from there that I want to keep them all under the module namespace instead of importing them all locally.

import sqlalchemy as sa
import sqlalchemy.orm
import sqlalchemy.events
# etc.

sa.create_engine
sa.orm.relationship
sa.events.DDLEvents

If I add as sa to every import, I get the same "not a known member" errors, so option 2 doesn't seem to work.

Could you elaborate on what is implicit and fragile about this? Both aliasing imports and importing submodules to add to the module's namespace are documented features of the import system. Why does pyright raise the error when using the alias?

@Aran-Fey
Copy link

@davidism I believe you've misunderstood the suggestion - it says to alias the submodule, like import sqlalchemy.orm as sa_orm.

But you're right that there is nothing fragile about this. After import foo.user, foo.user is guaranteed to exist, and since f is an alias of foo, so is f.user. This issue should certainly not be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
as designed Not a bug, working as intended
Projects
None yet
Development

No branches or pull requests

4 participants