[pygobject] Fix lookup of vfuncs in parent classes
- From: Martin Pitt <martinpitt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Fix lookup of vfuncs in parent classes
- Date: Fri, 1 Jun 2012 08:05:25 +0000 (UTC)
commit 07a08b49aae83a297e2f91240448314e4663f724
Author: Carlos Garnacho <carlos lanedo com>
Date: Mon May 14 15:31:14 2012 +0200
Fix lookup of vfuncs in parent classes
https://bugzilla.gnome.org/show_bug.cgi?id=672864.
As subclasses implemented in python override the attribute for the
vfunc, __mro__ has to be used so subclasses of the subclass overriding
methods may find the corresponding VFuncInfo.
Co-Authored-by: Martin Pitt <martinpitt gnome org>
gi/types.py | 6 +++---
tests/test_gi.py | 27 +++++++++++++++++++++++++++
2 files changed, 30 insertions(+), 3 deletions(-)
---
diff --git a/gi/types.py b/gi/types.py
index e44edba..95f1059 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -121,10 +121,10 @@ class MetaClassHelper(object):
# If a method name starts with "do_" assume it is a vfunc, and search
# in the base classes for a method with the same name to override.
- # Recursion is not necessary here because getattr() searches all
- # super class attributes as well.
+ # Recursion is necessary as overriden methods in most immediate parent
+ # classes may shadow vfuncs from classes higher in the hierarchy.
vfunc_info = None
- for base in cls.__bases__:
+ for base in cls.__mro__:
method = getattr(base, vfunc_name, None)
if method is not None and hasattr(method, '__info__') and \
isinstance(method.__info__, VFuncInfo):
diff --git a/tests/test_gi.py b/tests/test_gi.py
index e948c9d..cc6ec2d 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1696,6 +1696,33 @@ class TestPythonGObject(unittest.TestCase):
GIMarshallingTests.SubSubObject.do_method_deep_hierarchy(sub_sub_sub_object, 5)
self.assertEqual(sub_sub_sub_object.props.int, 5)
+ def test_python_subsubobject_vfunc(self):
+ class PySubObject(GIMarshallingTests.Object):
+ def __init__(self):
+ GIMarshallingTests.Object.__init__(self)
+ self.sub_method_int8_called = 0
+
+ def do_method_int8_in(self, int8):
+ self.sub_method_int8_called += 1
+
+ class PySubSubObject(PySubObject):
+ def __init__(self):
+ PySubObject.__init__(self)
+ self.subsub_method_int8_called = 0
+
+ def do_method_int8_in(self, int8):
+ self.subsub_method_int8_called += 1
+
+ so = PySubObject()
+ so.method_int8_in(1)
+ self.assertEqual(so.sub_method_int8_called, 1)
+
+ # it should call the method on the SubSub object only
+ sso = PySubSubObject()
+ sso.method_int8_in(1)
+ self.assertEqual(sso.subsub_method_int8_called, 1)
+ self.assertEqual(sso.sub_method_int8_called, 0)
+
def test_callback_in_vfunc(self):
class SubObject(GIMarshallingTests.Object):
def __init__(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]