[pygobject] gi/types: make it possible to resolve ambiguous vmethod names
- From: Christoph Reiter <creiter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] gi/types: make it possible to resolve ambiguous vmethod names
- Date: Tue, 23 Jan 2018 23:08:27 +0000 (UTC)
commit f2100902c6fdfd6a3daaab39d3325ffc9ada9a7d
Author: Mathieu Duponchelle <mathieu centricular com>
Date: Sun Jan 21 19:17:10 2018 +0100
gi/types: make it possible to resolve ambiguous vmethod names
Related to https://gitlab.gnome.org/GNOME/pygobject/issues/105,
but the method exposed to resolve the ambiguities does not
use a decorator, as a decorator cannot rename the function it
wraps, which means that users will have to provide different names
if they want to implement ambiguous methods from multiple base
classes.
Instead, ambiguities can be resolved by implementing methods named
do_$namespaced_base_class_name_$vfunc_name, eg:
do_gst_base_src_query
gi/types.py | 50 ++++++++++++++++++++++++++++++++++++--------------
1 file changed, 36 insertions(+), 14 deletions(-)
---
diff --git a/gi/types.py b/gi/types.py
index 9bc3779c..f73f30c0 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -24,6 +24,7 @@ from __future__ import absolute_import
import sys
import warnings
+import re
from ._constants import TYPE_INVALID
from .docstring import generate_doc_string
@@ -49,6 +50,11 @@ if (3, 0) <= sys.version_info < (3, 3):
return hasattr(obj, '__call__')
+def snake_case(name):
+ s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
+ return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
+
+
class MetaClassHelper(object):
def _setup_methods(cls):
for method_info in cls.__info__.get_methods():
@@ -81,6 +87,8 @@ class MetaClassHelper(object):
if not vfunc_name.startswith("do_") or not callable(py_vfunc):
continue
+ skip_ambiguity_check = False
+
# 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 necessary as overriden methods in most immediate parent
@@ -92,6 +100,20 @@ class MetaClassHelper(object):
vfunc_info = method
break
+ if not hasattr(base, '__info__') or not hasattr(base.__info__, 'get_vfuncs'):
+ continue
+
+ base_name = snake_case(base.__info__.get_type_name())
+
+ for v in base.__info__.get_vfuncs():
+ if vfunc_name == 'do_%s_%s' % (base_name, v.get_name()):
+ vfunc_info = v
+ skip_ambiguity_check = True
+ break
+
+ if vfunc_info:
+ break
+
# If we did not find a matching method name in the bases, we might
# be overriding an interface virtual method. Since interfaces do not
# provide implementations, there will be no method attribute installed
@@ -102,22 +124,22 @@ class MetaClassHelper(object):
vfunc_info = find_vfunc_info_in_interface(cls.__bases__, vfunc_name[len("do_"):])
if vfunc_info is not None:
- assert vfunc_name == ('do_' + vfunc_info.get_name())
# 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:
- base_info = vfunc_info.get_container()
- raise TypeError('Method %s() on class %s.%s is ambiguous '
- 'with methods in base classes %s.%s and %s.%s' %
- (vfunc_name,
- cls.__info__.get_namespace(),
- cls.__info__.get_name(),
- base_info.get_namespace(),
- base_info.get_name(),
- ambiguous_base.__info__.get_namespace(),
- ambiguous_base.__info__.get_name()
- ))
+ if not skip_ambiguity_check:
+ ambiguous_base = find_vfunc_conflict_in_bases(vfunc_info, cls.__bases__)
+ if ambiguous_base is not None:
+ base_info = vfunc_info.get_container()
+ raise TypeError('Method %s() on class %s.%s is ambiguous '
+ 'with methods in base classes %s.%s and %s.%s' %
+ (vfunc_name,
+ cls.__info__.get_namespace(),
+ cls.__info__.get_name(),
+ base_info.get_namespace(),
+ base_info.get_name(),
+ ambiguous_base.__info__.get_namespace(),
+ ambiguous_base.__info__.get_name()
+ ))
hook_up_vfunc_implementation(vfunc_info, cls.__gtype__,
py_vfunc)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]