Commit 94e8befc authored by John (J5) Palmieri's avatar John (J5) Palmieri
Browse files

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
parent 9c5aee4f
......@@ -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()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment