8000 stubtest: increase coverage by hauntsaninja · Pull Request #11634 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

stubtest: increase coverage #11634

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

Merged
merged 5 commits into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,23 +200,34 @@ def verify_mypyfile(
yield Error(object_path, "is not a module", stub, runtime)
return

# Check things in the stub that are public
# Check things in the stub
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))
if not o.module_hidden 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`, 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))

def _belongs_to_runtime(r: types.ModuleType, attr: str) -> bool:
obj = getattr(r, attr)
obj_mod = getattr(obj, "__module__", None)
if obj_mod is not None:
return obj_mod == r.__name__
return not isinstance(obj, types.ModuleType)

runtime 10000 _public_contents = (
runtime.__all__
if hasattr(runtime, "__all__")
else [
m
for m in dir(runtime)
if not m.startswith("_")
# 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 _belongs_to_runtime(runtime, m)
]
)
# Check all things declared in module's __all__, falling back to our best guess
to_check.update(runtime_public_contents)
to_check.difference_update({"__file__", "__doc__", "__name__", "__builtins__", "__package__"})

for entry in sorted(to_check):
Expand Down
18 changes: 17 additions & 1 deletion mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class bool(int): ...
class str: ...
class bytes: ...

class list(Sequence[T]): ...

def property(f: T) -> T: ...
def classmethod(f: T) -> T: ...
def staticmethod(f: T) -> T: ...
Expand Down Expand Up @@ -648,7 +650,7 @@ def h(x: str): ...
runtime="",
error="h",
)
yield Case("", "__all__ = []", None) # dummy case
yield Case(stub="", runtime="__all__ = []", error=None) # dummy case
yield Case(stub="", runtime="__all__ += ['y']\ny = 5", error="y")
yield Case(stub="", runtime="__all__ += ['g']\ndef g(): pass", error="g")
# Here we should only check that runtime has B, since the stub explicitly re-exports it
Expand All @@ -660,6 +662,20 @@ def h(x: str): ...
def test_missing_no_runtime_all(self) -> Iterator[Case]:
yield Case(stub="", runtime="import sys", error=None)
yield Case(stub="", runtime="def g(): ...", error="g")
yield Case(stub="", runtime="CONSTANT = 0", error="CONSTANT")

@collect_cases
def test_non_public_1(self) -> Iterator[Case]:
yield Case(stub="__all__: list[str]", runtime="", error=None) # dummy case
yield Case(stub="_f: int", runtime="def _f(): ...", error="_f")

@collect_cases
def test_non_public_2(self) -> Iterator[Case]:
yield Case(
stub="__all__: list[str] = ['f']", runtime="__all__ = ['f']", error=None
)
yield Case(stub="f: int", runtime="def f(): ...", error="f")
yield Case(stub="g: int", runtime="def g(): ...", error="g")

@collect_cases
def test_special_dunders(self) -> Iterator[Case]:
Expand Down
0