# HG changeset patch # User Ed Catmur # Date 1371493767 -3600 # Mon Jun 17 19:29:27 2013 +0100 # Branch singledispatch-mro-18244 # Node ID 22986b6763145c05d132e445b22c80ac6a9b198d # Parent ec4b0145f7e5e9d95c82b0b428d7daea2dde4a6b Issue 18244: When virtual-inheriting ABCs at distinct levels in the MRO, the composed MRO should not depend on the haystack ordering. diff -r ec4b0145f7e5 -r 22986b676314 Lib/functools.py --- a/Lib/functools.py Mon Jun 17 15:45:11 2013 +0200 +++ b/Lib/functools.py Mon Jun 17 19:29:27 2013 +0100 @@ -376,14 +376,18 @@ if (needle in bases or not hasattr(needle, '__mro__') or not issubclass(cls, needle)): continue # either present in the __mro__ already or unrelated - for index, base in enumerate(mro): - if not issubclass(base, needle): + for i, base in enumerate(mro): + if issubclass(base, needle): + index = i + 1 + elif base in bases: break - if base in bases and not issubclass(needle, base): + if not issubclass(needle, base): # Conflict resolution: put classes present in __mro__ and their # subclasses first. See test_mro_conflicts() in test_functools.py # for examples. - index += 1 + for index, base in enumerate(mro[i + 1:], i + 1): + if not issubclass(base, needle): + break mro.insert(index, needle) return mro diff -r ec4b0145f7e5 -r 22986b676314 Lib/test/test_functools.py --- a/Lib/test/test_functools.py Mon Jun 17 15:45:11 2013 +0200 +++ b/Lib/test/test_functools.py Mon Jun 17 19:29:27 2013 +0100 @@ -946,6 +946,15 @@ m = mro(c.defaultdict, [c.Container, c.Sized, str]) self.assertEqual(m, [c.defaultdict, dict, c.Sized, c.Container, object]) + # This MRO should not depend on haystack ordering + class C(c.defaultdict): + def __call__(self): + pass + m = mro(C, [c.Callable, c.Container]) + self.assertEqual(m, [C, c.defaultdict, c.Callable, dict, c.Container, object]) + m = mro(C, [c.Container, c.Callable]) + self.assertEqual(m, [C, c.defaultdict, c.Callable, dict, c.Container, object]) + def test_register_abc(self): c = collections d = {"a": "b"}