Skip to content

Commit

Permalink
stubtest: fix false negative with dunder methods, small changes (#8886)
Browse files Browse the repository at this point in the history
* stubtest: use stub.name over runtime.__name__

Seems to be a little more reliable

* stubtest: remove unnecessary code

I can no longer repro any of the behaviour related to distutils.command.
I found one case it can come up involving builtins, but overall I think
this code is just simpler like this.

* stubtest: fix false negatives

If the stub doesn't list dunder methods, we wouldn't check them earlier.
There are a lot of false negatives due to this.

* teststubtest: add a test for the previous commit

Also covers some of the MRO logic in verify_typeinfo

Co-authored-by: hauntsaninja <>
  • Loading branch information
hauntsaninja authored May 26, 2020
1 parent 10195b8 commit b3d4398
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
16 changes: 5 additions & 11 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,11 @@ def verify_typeinfo(
return

to_check = set(stub.names)
dunders_to_check = ("__init__", "__new__", "__call__")
# cast to workaround mypyc complaints
to_check.update(m for m in cast(Any, vars)(runtime) if not m.startswith("_"))
to_check.update(
m for m in cast(Any, vars)(runtime) if m in dunders_to_check or not m.startswith("_")
)

for entry in sorted(to_check):
mangled_entry = entry
Expand All @@ -254,7 +257,7 @@ def verify_typeinfo(
def _verify_static_class_methods(
stub: nodes.FuncItem, runtime: types.FunctionType, object_path: List[str]
) -> Iterator[str]:
if runtime.__name__ == "__new__":
if stub.name == "__new__":
# Special cased by Python, so never declared as staticmethod
return
if inspect.isbuiltin(runtime):
Expand Down Expand Up @@ -662,15 +665,6 @@ def verify_funcitem(
def verify_none(
stub: Missing, runtime: MaybeMissing[Any], object_path: List[str]
) -> Iterator[Error]:
if isinstance(runtime, Missing):
try:
# We shouldn't really get here since that would involve something not existing both in
# the stub and the runtime, however, some modules like distutils.command have some
# weird things going on. Try to see if we can find a runtime object by importing it,
# otherwise crash.
runtime = importlib.import_module(".".join(object_path))
except ImportError:
raise RuntimeError
yield Error(object_path, "is not present in stub", stub, runtime)


Expand Down
32 changes: 32 additions & 0 deletions mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,38 @@ def __mangle_bad(self, text): pass
error="X.__mangle_bad"
)

@collect_cases
def test_mro(self) -> Iterator[Case]:
yield Case(
stub="""
class A:
def foo(self, x: int) -> None: ...
class B(A):
pass
class C(A):
pass
""",
runtime="""
class A:
def foo(self, x: int) -> None: ...
class B(A):
def foo(self, x: int) -> None: ...
class C(A):
def foo(self, y: int) -> None: ...
""",
error="C.foo"
)
yield Case(
stub="""
class X: ...
""",
runtime="""
class X:
def __init__(self, x): pass
""",
error="X.__init__"
)


def remove_color_code(s: str) -> str:
return re.sub("\\x1b.*?m", "", s) # this works!
Expand Down

0 comments on commit b3d4398

Please sign in to comment.