Skip to content

Commit

Permalink
stubtest: import submodules mentioned in __all__ (#9943)
Browse files Browse the repository at this point in the history
* stubtest: import submodules mentioned in __all__

This kind of helps resolves #9935 

Co-authored-by: hauntsaninja <>
  • Loading branch information
hauntsaninja authored Jul 26, 2021
1 parent bc1dc95 commit 6fd2dc2
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ def test_module(module_name: str) -> Iterator[Error]:
with warnings.catch_warnings():
warnings.simplefilter("ignore")
runtime = importlib.import_module(module_name)
# Also run the equivalent of `from module import *`
# This could have the additional effect of loading not-yet-loaded submodules
# mentioned in __all__
__import__(module_name, fromlist=["*"])
except Exception as e:
yield Error([module_name], "failed to import: {}".format(e), stub, MISSING)
return
Expand Down Expand Up @@ -200,26 +204,29 @@ def verify_mypyfile(
to_check = set(
m
for m, o in stub.names.items()
# TODO: change `o.module_public` to `not o.module_hidden`
if o.module_public and (not m.startswith("_") or hasattr(runtime, m))
)
runtime_public_contents = [
m
for m in dir(runtime)
if not m.startswith("_")
# Ensure that the object's module is `runtime`, e.g. so that we don't pick up reexported
# modules and infinitely recurse. Unfortunately, there's no way to detect an explicit
# reexport missing from the stubs (that isn't specified in __all__)
# Ensure that the object's module is `runtime`, since in the absence of __all__ we don't
# have a good way to detect re-exports at runtime.
and getattr(getattr(runtime, m), "__module__", None) == runtime.__name__
]
# Check all things declared in module's __all__, falling back to runtime_public_contents
to_check.update(getattr(runtime, "__all__", runtime_public_contents))
to_check.difference_update({"__file__", "__doc__", "__name__", "__builtins__", "__package__"})

for entry in sorted(to_check):
stub_to_verify = stub.names[entry].node if entry in stub.names else MISSING
assert stub_to_verify is not None
stub_entry = stub.names[entry].node if entry in stub.names else MISSING
if isinstance(stub_entry, nodes.MypyFile):
# Don't recursively check exported modules, since that leads to infinite recursion
continue
assert stub_entry is not None
yield from verify(
stub_to_verify,
stub_entry,
getattr(runtime, entry, MISSING),
object_path + [entry],
)
Expand Down

0 comments on commit 6fd2dc2

Please sign in to comment.