diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2015-10-26 12:30:08 +0000 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2015-10-26 12:30:08 +0000 |
commit | 8a0343728bc9b578d533ef5aa21e1412a8951ce6 (patch) | |
tree | 0bfe86d443ed10dc9a5b41d83d8e1ab6b240dd69 | |
parent | 033a215bb1d1a7f4b954ef99667e41d9e6fed92b (diff) | |
download | astroid-8a0343728bc9b578d533ef5aa21e1412a8951ce6.tar.gz |
Class.getattr('__mro__') returns the actual MRO.
Also, Class.getattr('__bases__') returns actual bases.
It previously didn't work correctly, because it was putting the
entire ancestors into the Tuple object and it put those classes
into the wrong attribute.
Closes issue #128.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | astroid/scoped_nodes.py | 14 | ||||
-rw-r--r-- | astroid/tests/unittest_scoped_nodes.py | 23 |
3 files changed, 34 insertions, 6 deletions
@@ -2,6 +2,9 @@ Change log for the astroid package (used to be astng) ===================================================== -- + + * Class.getattr('__mro__') returns the actual MRO. Closes issue #128. + * The logilab-common dependency is not needed anymore as the needed code was integrated into astroid. diff --git a/astroid/scoped_nodes.py b/astroid/scoped_nodes.py index 31fc2f8..e6e3324 100644 --- a/astroid/scoped_nodes.py +++ b/astroid/scoped_nodes.py @@ -1359,14 +1359,16 @@ class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG, if name in self.special_attributes: if name == '__module__': return [node_classes.const_factory(self.root().qname())] + values - # FIXME: do we really need the actual list of ancestors? - # returning [Tuple()] + values don't break any test - # this is ticket http://www.logilab.org/ticket/52785 - # XXX need proper meta class handling + MRO implementation - if name == '__bases__' or (name == '__mro__' and self.newstyle): + if name == '__bases__': node = node_classes.Tuple() - node.items = self.ancestors(recurs=True, context=context) + elts = list(self._inferred_bases(context)) + node.postinit(elts=elts) return [node] + values + if name == '__mro__' and self.newstyle: + mro = self.mro() + node = node_classes.Tuple() + node.postinit(elts=mro) + return [node] return std_special_attributes(self, name) # don't modify the list in self.locals! values = list(values) diff --git a/astroid/tests/unittest_scoped_nodes.py b/astroid/tests/unittest_scoped_nodes.py index bf090da..8e82290 100644 --- a/astroid/tests/unittest_scoped_nodes.py +++ b/astroid/tests/unittest_scoped_nodes.py @@ -584,6 +584,29 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase): self.assertEqual(len(cls.getattr('__dict__')), 1) self.assertEqual(len(cls.getattr('__mro__')), 1) + def test__mro__attribute(self): + node = test_utils.extract_node(''' + class A(object): pass + class B(object): pass + class C(A, B): pass + ''') + mro = node.getattr('__mro__')[0] + self.assertIsInstance(mro, nodes.Tuple) + self.assertEqual(mro.elts, node.mro()) + + def test__bases__attribute(self): + node = test_utils.extract_node(''' + class A(object): pass + class B(object): pass + class C(A, B): pass + class D(C): pass + ''') + bases = node.getattr('__bases__')[0] + self.assertIsInstance(bases, nodes.Tuple) + self.assertEqual(len(bases.elts), 1) + self.assertIsInstance(bases.elts[0], nodes.ClassDef) + self.assertEqual(bases.elts[0].name, 'C') + def test_cls_special_attributes_2(self): astroid = builder.parse(''' class A: pass |