Skip to content

Commit f1a1b66

Browse files
author
hauntsaninja
committed
stubtest: handle name mangling
1 parent 6312406 commit f1a1b66

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

mypy/stubtest.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,12 @@ def verify_typeinfo(
241241
to_check.update(m for m in cast(Any, vars)(runtime) if not m.startswith("_"))
242242

243243
for entry in sorted(to_check):
244+
mangled_entry = entry
245+
if entry.startswith("__") and not entry.endswith("__"):
246+
mangled_entry = "_{}{}".format(stub.name, entry)
244247
yield from verify(
245248
next((t.names[entry].node for t in stub.mro if entry in t.names), MISSING),
246-
getattr(runtime, entry, MISSING),
249+
getattr(runtime, mangled_entry, MISSING),
247250
object_path + [entry],
248251
)
249252

@@ -267,7 +270,13 @@ def _verify_static_class_methods(
267270
# Look the object up statically, to avoid binding by the descriptor protocol
268271
static_runtime = importlib.import_module(object_path[0])
269272
for entry in object_path[1:]:
270-
static_runtime = inspect.getattr_static(static_runtime, entry)
273+
try:
274+
static_runtime = inspect.getattr_static(static_runtime, entry)
275+
except AttributeError:
276+
# This can happen with mangled names, ignore for now.
277+
# TODO: pass more information about ancestors of nodes/objects to verify, so we don't
278+
# have to do this hacky lookup. Would be useful in a couple other places too.
279+
return
271280

272281
if isinstance(static_runtime, classmethod) and not stub.is_class:
273282
yield "runtime is a classmethod but stub is not"

mypy/test/teststubtest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,22 @@ def h(x: str): ...
572572
yield Case(stub="", runtime="__all__ += ['y']\ny = 5", error="y")
573573
yield Case(stub="", runtime="__all__ += ['g']\ndef g(): pass", error="g")
574574

575+
@collect_cases
576+
def test_name_mangling(self) -> Iterator[Case]:
577+
yield Case(
578+
stub="""
579+
class X:
580+
def __mangle_good(self, text: str) -> None: ...
581+
def __mangle_bad(self, number: int) -> None: ...
582+
""",
583+
runtime="""
584+
class X:
585+
def __mangle_good(self, text): pass
586+
def __mangle_bad(self, text): pass
587+
""",
588+
error="X.__mangle_bad"
589+
)
590+
575591

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

0 commit comments

Comments
 (0)