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

stubtest: Spurious warning related to symbols in '__all__' #9935

Closed
dalcinl opened this issue Jan 21, 2021 · 4 comments · Fixed by #9943
Closed

stubtest: Spurious warning related to symbols in '__all__' #9935

dalcinl opened this issue Jan 21, 2021 · 4 comments · Fixed by #9943
Labels
bug mypy got something wrong topic-stubtest

Comments

@dalcinl
Copy link

dalcinl commented Jan 21, 2021

Bug Report

I'm getting an error from stubtest checking a package that lists a submodule in __all__.

To Reproduce

  1. Create a package with a submodule
$ mkdir pkg
$ touch pkg/__init__.py
$ touch pkg/mod.py
  1. So far, stubtest seems to be happy with it
$ PYTHONPATH=$PWD stubtest pkg
  1. Now add mod to __all__ in __init.py and run stubtest again
$ echo "__all__=['mod']" > pkg/__init__.py
$ PYTHONPATH=$PWD stubtest pkg
error: pkg.mod is not present in stub
Stub:
MISSING
Runtime:
MISSING

Note, adding respective *.pyi files do not fix the problem.

  • Mypy version used: latest master
  • Python version used: 3.9
  • Operating system and version: Linux (Fedora 33)
@dalcinl dalcinl added the bug mypy got something wrong label Jan 21, 2021
@hauntsaninja
Copy link
Collaborator

This example is confusing, since the "stub" stubtest is looking at is actually just the source file. This is a weird way of using stubtest — what are you trying to accomplish?

Moreover, the complaint is kind of true.

λ PYTHONPATH=$(pwd) python3 -c 'import pkg; pkg.mod'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: module 'pkg' has no attribute 'mod'

Note if you were to add from . import mod to your __init__.py, things would work.

Finally, the flag --ignore-missing-stub will let you ignore errors caused by things missing from your stubs.

@dalcinl
Copy link
Author

dalcinl commented Jan 22, 2021

As I mentioned before, adding *.pyi files do not fix the problem.

Let's try again, using *.pyi stub files alongside the *.py files:

$ mkdir pkg
$ touch pkg/__init__.py
$ touch pkg/__init__.pyi
$ touch pkg/mod.py
$ touch pkg/mod.pyi
$ PYTHONPATH=$PWD stubtest pkg
$ echo "__all__=['mod']" > pkg/__init__.py
$ PYTHONPATH=$PWD stubtest pkg
error: pkg.mod is not present in stub
Stub:
MISSING
Runtime:
MISSING

IMHO, the complaint is not true, this is a perfectly valid Python package. The fact that mod is listed in __all__ does not imply that the package's __init__.py should import the submodule. To the best of my knowledge, the purpose of __all__ is to control how from pkg import * behaves, look yourself:

$ PYTHONPATH=$PWD python -c "from pkg import *; print(mod)"
<module 'pkg.mod' from '/tmp/pkg/mod.py'>

so there is no real requirement for from . import mod in pkg/__init__.py.

I'm not sure of this behavior of stubtest on handling __all__ is a bug or it is intentional, but in any case it is incorrect. Again, listing 'something' in __all__ does not mean that something has to be present in the namespace. That's my understanding from Python's documentation, and it has worked that way at least since the beginnings of this century, when we where using Python 2.2.

I'm trying to use stubtest to setup a sort of "lint" for my manually maintained stubs. The flag --ignore-missing-stub is not an option, it does not operate at the stub file level, it will ignore actual missing stub entries.

hauntsaninja pushed a commit to hauntsaninja/mypy that referenced this issue Jan 22, 2021
hauntsaninja pushed a commit to hauntsaninja/mypy that referenced this issue Jan 22, 2021
@hauntsaninja
Copy link
Collaborator

Okay, gotcha. I think mypy in general doesn't handle this use of __all__ correctly. Leaving stubtest aside for now, something like:

cat > pkg/__init__.py <<HERE
__all__ = ["mod", "x"]
x: int
y: str
HERE

touch pkg/mod.py

cat > script.py <<HERE
from pkg import *
reveal_type(mod)  # incorrectly does not resolve
reveal_type(x)  # correctly resolves
reveal_type(y)  # correctly does not resolve
HERE

Anyway, for now I opened #9943 which should fix the runtime half of stubtest. That is, after that PR you would be able to get things working by adding from . import mod to your stub.

cc @srittau since you were resurrecting the stub PEP and you might have opinions about how __all__ in stubs should work

@srittau
Copy link
Contributor

srittau commented Jan 23, 2021

We decided that it's probably best if __all__ in stubs works exactly like it does in implementations. It must be a list literal of string and customizes export behavior.

hauntsaninja added a commit that referenced this issue Jul 26, 2021
* stubtest: import submodules mentioned in __all__

This kind of helps resolves #9935 

Co-authored-by: hauntsaninja <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-stubtest
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants