From d0f10e78540cc86e9b141fbfc8b701ec91dedf71 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sun, 24 May 2020 19:07:37 -0700 Subject: [PATCH 1/4] stubtest: use stub.name over runtime.__name__ Seems to be a little more reliable --- mypy/stubtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index e176fb04e5a8..9a7a3b7f719e 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -254,7 +254,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): From 58e596a76eb904eaffea254bc82d0a469e0caf98 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sun, 24 May 2020 19:08:10 -0700 Subject: [PATCH 2/4] 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. --- mypy/stubtest.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 9a7a3b7f719e..245148c9eab3 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -662,15 +662,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) From 573ac89692b43eb77e2d49b571740d217fedbd79 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sun, 24 May 2020 19:09:46 -0700 Subject: [PATCH 3/4] 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. --- mypy/stubtest.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index 245148c9eab3..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 From c44e00ad1fb49884c72ecc3732523613930141f7 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Mon, 25 May 2020 01:26:14 -0700 Subject: [PATCH 4/4] teststubtest: add a test for the previous commit Also covers some of the MRO logic in verify_typeinfo --- mypy/test/teststubtest.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) 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!