Skip to content

Commit 5092504

Browse files
committed
mro() can be computed for classes with old style classes in the hierarchy
1 parent 7eb703d commit 5092504

File tree

3 files changed

+45
-12
lines changed

3 files changed

+45
-12
lines changed

ChangeLog

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ Change log for the astroid package (used to be astng)
55

66
* Basic support for the class form of typing.NamedTuple
77

8+
* mro() can be computed for classes with old style classes in the hierarchy
9+
810

911
2017-04-13 -- 1.5.0
1012

astroid/scoped_nodes.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -1777,25 +1777,15 @@ def _inferred_bases(self, context=None):
17771777
for base in baseobj.bases:
17781778
yield base
17791779

1780-
def mro(self, context=None):
1781-
"""Get the method resolution order, using C3 linearization.
1782-
1783-
It returns the list of ancestors sorted by the mro.
1784-
This will raise `NotImplementedError` for old-style classes, since
1785-
they don't have the concept of MRO.
1786-
"""
1787-
if not self.newstyle:
1788-
raise NotImplementedError(
1789-
"Could not obtain mro for old-style classes.")
1790-
1780+
def _compute_mro(self, context=None):
17911781
inferred_bases = list(self._inferred_bases(context=context))
17921782
bases_mro = []
17931783
for base in inferred_bases:
17941784
if base is self:
17951785
continue
17961786

17971787
try:
1798-
mro = base.mro(context=context)
1788+
mro = base._compute_mro(context=context)
17991789
bases_mro.append(mro)
18001790
except NotImplementedError:
18011791
# Some classes have in their ancestors both newstyle and
@@ -1810,6 +1800,20 @@ def mro(self, context=None):
18101800
_verify_duplicates_mro(unmerged_mro, self, context)
18111801
return _c3_merge(unmerged_mro, self, context)
18121802

1803+
def mro(self, context=None):
1804+
"""Get the method resolution order, using C3 linearization.
1805+
1806+
It returns the list of ancestors sorted by the mro.
1807+
This will raise `NotImplementedError` for old-style classes, since
1808+
they don't have the concept of MRO.
1809+
"""
1810+
1811+
if not self.newstyle:
1812+
raise NotImplementedError(
1813+
"Could not obtain mro for old-style classes.")
1814+
1815+
return self._compute_mro(context=context)
1816+
18131817
def bool_value(self):
18141818
return True
18151819

astroid/tests/unittest_scoped_nodes.py

+27
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,33 @@ class Old: pass""")
13231323
self.assertEqual(str(cm.exception), "Could not obtain mro for "
13241324
"old-style classes.")
13251325

1326+
@test_utils.require_version(maxver='3.0')
1327+
def test_mro_for_classes_with_old_style_in_mro(self):
1328+
node = builder.extract_node('''
1329+
class Factory:
1330+
pass
1331+
class ClientFactory(Factory):
1332+
pass
1333+
class ReconnectingClientFactory(ClientFactory):
1334+
pass
1335+
class WebSocketAdapterFactory(object):
1336+
pass
1337+
class WebSocketClientFactory(WebSocketAdapterFactory, ClientFactory):
1338+
pass
1339+
class WampWebSocketClientFactory(WebSocketClientFactory):
1340+
pass
1341+
class RetryFactory(WampWebSocketClientFactory, ReconnectingClientFactory):
1342+
pas
1343+
''')
1344+
self.assertEqualMro(
1345+
node,
1346+
['RetryFactory', 'WampWebSocketClientFactory',
1347+
'WebSocketClientFactory', 'WebSocketAdapterFactory', 'object',
1348+
'ReconnectingClientFactory', 'ClientFactory',
1349+
'Factory'
1350+
]
1351+
)
1352+
13261353
@test_utils.require_version(maxver='3.0')
13271354
def test_combined_newstyle_oldstyle_in_mro(self):
13281355
node = builder.extract_node('''

0 commit comments

Comments
 (0)