From 584fdb02b944b3cbf366684412c1e8799b33a5ee Mon Sep 17 00:00:00 2001 From: rechen Date: Thu, 24 Sep 2020 14:29:24 -0700 Subject: [PATCH] Fix a bug in pytype's handling of classes with the same name. PiperOrigin-RevId: 333598812 --- pytype/attribute.py | 8 +++++--- pytype/tests/test_super.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pytype/attribute.py b/pytype/attribute.py index 2dbc671a6..586c5c1b3 100644 --- a/pytype/attribute.py +++ b/pytype/attribute.py @@ -310,11 +310,13 @@ def _get_attribute_from_super_instance( valself = obj.super_obj.to_binding(node) # When multiple inheritance is present, the two classes' MROs may differ. # In this case, we want to use the MRO of starting_cls but skip all the - # classes up to and including current_cls. + # classes up to and including current_cls. We traverse the MRO backwards + # to correctly handle the case in which the starting and current classes + # are different classes with the same name. skip = set() - for parent in starting_cls.mro: - skip.add(parent) + for i, parent in enumerate(reversed(starting_cls.mro)): if parent.full_name == current_cls.full_name: + skip.update(starting_cls.mro[:len(starting_cls.mro)-i]) break else: starting_cls = self.vm.convert.super_type diff --git a/pytype/tests/test_super.py b/pytype/tests/test_super.py index 6a5c5b199..99077bdfe 100644 --- a/pytype/tests/test_super.py +++ b/pytype/tests/test_super.py @@ -266,5 +266,15 @@ def __init__(self): """) self.assertErrorRegexes(errors, {"e": r"super"}) + def test_duplicate_class_names(self): + self.Check(""" + class Foo(object): + def __new__(self, *args, **kwargs): + typ = type('Foo', (Foo,), {}) + return super(Foo, typ).__new__(typ) + def __init__(self, x): + super(Foo, self).__init__() + """) + test_base.main(globals(), __name__ == "__main__")