[pygobject] refactor Jonathan Matthew recurse vfunc patch so it applys and clean up a bit
- From: John Palmieri <johnp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] refactor Jonathan Matthew recurse vfunc patch so it applys and clean up a bit
- Date: Tue, 30 Nov 2010 22:01:59 +0000 (UTC)
commit 94e8befc935d4a6c7f766e34195e10fc3fb3b93a
Author: John (J5) Palmieri <johnp redhat com>
Date: Tue Nov 30 16:57:05 2010 -0500
refactor Jonathan Matthew recurse vfunc patch so it applys and clean up a bit
* this patch does the recursion using the previous patche's support functions
gi/types.py | 55 +++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 45 insertions(+), 10 deletions(-)
---
diff --git a/gi/types.py b/gi/types.py
index 18b4013..1ebc194 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -31,7 +31,8 @@ from ._gi import \
StructInfo, \
set_object_has_new_constructor, \
register_interface_info, \
- hook_up_vfunc_implementation
+ hook_up_vfunc_implementation, \
+ has_vfunc_implementation
def Function(info):
@@ -92,28 +93,62 @@ class MetaClassHelper(object):
value = constant_info.get_value()
setattr(cls, name, value)
- def _setup_vfuncs(cls):
+ def _setup_vfuncs(cls, impl):
for base in cls.__bases__:
if not hasattr(base, '__info__') or \
not hasattr(base.__info__, 'get_vfuncs'):
continue
for vfunc_info in base.__info__.get_vfuncs():
- vfunc = getattr(cls, 'do_' + vfunc_info.get_name(), None)
+ vfunc_name = 'do_' + vfunc_info.get_name()
+ vfunc = getattr(impl, vfunc_name, None)
if vfunc is None and isinstance(base.__info__, InterfaceInfo) and \
- (not hasattr(cls, vfunc_info.get_name()) and not vfunc_info.get_invoker()):
+ impl.__module__.startswith('gi.overrides') is False and \
+ not has_vfunc_implementation(vfunc_info, impl.__gtype__):
raise TypeError('Class implementing %s.%s should implement '
- 'the method do_%s()' % (base.__info__.get_namespace(),
- base.__info__.get_name(),
- vfunc_info.get_name()))
+ 'the method %s()' % (base.__info__.get_namespace(),
+ base.__info__.get_name(),
+ vfunc_name()))
elif vfunc is not None:
+ # check to see if there are vfuncs with the same name in the bases
+ # we have no way of specifying which one we are supposed to override
+ ambiguous_base = find_vfunc_conflict_in_bases(vfunc_info, cls.__bases__)
+ if ambiguous_base is not None:
+ raise TypeError('Method %s() on class %s.%s is ambiguous '
+ 'with methods in base classes %s.%s and %s.%s' %
+ (vfunc_name,
+ impl.__info__.get_namespace(),
+ impl.__info__.get_name(),
+ base.__info__.get_namespace(),
+ base.__info__.get_name(),
+ ambiguous_base.__info__.get_namespace(),
+ ambiguous_base.__info__.get_name()))
+
function = vfunc
if sys.version_info < (3, 0):
function = vfunc.im_func
- if not is_function_in_classes(function, cls.__bases__):
- hook_up_vfunc_implementation(vfunc_info, cls.__gtype__,
+ if not is_function_in_classes(function, impl.__bases__):
+ hook_up_vfunc_implementation(vfunc_info, impl.__gtype__,
vfunc)
+ base._setup_vfuncs(impl)
+
+def find_vfunc_conflict_in_bases(vfunc, bases):
+ for klass in bases:
+ if not hasattr(klass, '__info__') or \
+ not hasattr(klass.__info__, 'get_vfuncs'):
+ continue
+ vfuncs = klass.__info__.get_vfuncs()
+ vfunc_name = vfunc.get_name()
+ for v in vfuncs:
+ if v.get_name() == vfunc_name and v != vfunc:
+ return klass
+
+ aklass = find_vfunc_conflict_in_bases(vfunc, klass.__bases__)
+ if aklass is not None:
+ return aklass
+ return None
+
def is_function_in_classes(function, classes):
for klass in classes:
if function in klass.__dict__.values():
@@ -136,7 +171,7 @@ class GObjectMeta(gobject.GObjectMeta, MetaClassHelper):
is_python_defined = True
if is_python_defined:
- cls._setup_vfuncs()
+ cls._setup_vfuncs(cls)
elif is_gi_defined:
cls._setup_methods()
cls._setup_constants()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]