summaryrefslogtreecommitdiff
path: root/gi/types.py
diff options
context:
space:
mode:
Diffstat (limited to 'gi/types.py')
-rw-r--r--gi/types.py30
1 files changed, 27 insertions, 3 deletions
diff --git a/gi/types.py b/gi/types.py
index 47a81d84..69bb4944 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -23,6 +23,7 @@
from __future__ import absolute_import
import sys
+import warnings
from . import _gobject
from ._gobject._gobject import GInterface
@@ -309,17 +310,40 @@ class GObjectMeta(_gobject.GObjectMeta, MetaClassHelper):
def mro(C):
- """Compute the class precedence list (mro) according to C3
+ """Compute the class precedence list (mro) according to C3, with GObject
+ interface considerations.
+
+ We override Python's MRO calculation to account for the fact that
+ GObject classes are not affected by the diamond problem:
+ http://en.wikipedia.org/wiki/Diamond_problem
Based on http://www.python.org/download/releases/2.3/mro/
- Modified to consider that interfaces don't create the diamond problem
"""
# TODO: If this turns out being too slow, consider using generators
bases = []
bases_of_subclasses = [[C]]
if C.__bases__:
- bases_of_subclasses += list(map(mro, C.__bases__)) + [list(C.__bases__)]
+ for base in C.__bases__:
+ # Python causes MRO's to be calculated starting with the lowest
+ # base class and working towards the descendant, storing the result
+ # in __mro__ at each point. Therefore at this point we know that
+ # we already have our base class MRO's available to us, there is
+ # no need for us to (re)calculate them.
+ if hasattr(base, '__mro__'):
+ bases_of_subclasses += [list(base.__mro__)]
+ else:
+ warnings.warn('Mixin class %s is an old style class, please '
+ 'update this to derive from "object".' % base,
+ RuntimeWarning)
+ # For old-style classes (Python2 only), the MRO is not
+ # easily accessible. As we do need it here, we calculate
+ # it via recursion, according to the C3 algorithm. Using C3
+ # for old style classes deviates from Python's own behaviour,
+ # but visible effects here would be a corner case triggered by
+ # questionable design.
+ bases_of_subclasses += [mro(base)]
+ bases_of_subclasses += [list(C.__bases__)]
while bases_of_subclasses:
for subclass_bases in bases_of_subclasses: