From b3d4398403be29b1828e0a7a149af8958753fde2 Mon Sep 17 00:00:00 2001 From: Shantanu Date: Tue, 26 May 2020 13:48:40 -0700 Subject: [PATCH] stubtest: fix false negative with dunder methods, small changes (#8886) * 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 <> --- mypy/stubtest.py | 16 +++++----------- mypy/test/teststubtest.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index e176fb04e5a8..3dc0468868bd 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -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 @@ -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): @@ -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) diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index 34be30d43627..fe7c67261ded 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -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!