[pygobject] Replace Python VFunc descriptor directly with PyGIVFuncInfo



commit 91c49822363d8a1efc82163b46daa667d6cfc1b7
Author: Simon Feltman <sfeltman src gnome org>
Date:   Wed Jul 17 16:10:25 2013 -0700

    Replace Python VFunc descriptor directly with PyGIVFuncInfo
    
    Add tp_getdesc (__get__) to PyGIVFuncInfo to allow the object
    to be used directly as a callable descriptor. This piggy backs
    off the added support for functions and constructors in previous
    patches.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=704037

 gi/pygi-info.c |   25 +++++++++++++++++++++++--
 gi/types.py    |   33 ++++-----------------------------
 2 files changed, 27 insertions(+), 31 deletions(-)
---
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 23ace9a..7164ff9 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -544,6 +544,25 @@ _function_info_descr_get (PyGICallableInfo *self, PyObject *obj, PyObject *type)
     return (PyObject *)_new_bound_callable_info (self, bound_arg);
 }
 
+/* _vfunc_info_descr_get
+ *
+ * Descriptor protocol implementation for virtual functions.
+ */
+static PyObject *
+_vfunc_info_descr_get (PyGICallableInfo *self, PyObject *obj, PyObject *type) {
+    PyObject *result;
+    PyObject *bound_arg = NULL;
+
+    bound_arg = PyObject_GetAttrString (type, "__gtype__");
+    if (bound_arg == NULL)
+        return NULL;
+
+    /* _new_bound_callable_info adds its own ref so free the one from GetAttrString */
+    result = (PyObject *)_new_bound_callable_info (self, bound_arg);
+    Py_DECREF (bound_arg);
+    return result;
+}
+
 static void
 _callable_info_dealloc (PyGICallableInfo *self)
 {
@@ -2002,6 +2021,10 @@ _pygi_info_register_types (PyObject *m)
     PyGIFunctionInfo_Type.tp_call = (ternaryfunc) _function_info_call;
     PyGIFunctionInfo_Type.tp_descr_get = (descrgetfunc) _function_info_descr_get;
 
+    _PyGI_REGISTER_TYPE (m, PyGIVFuncInfo_Type, VFuncInfo,
+                         PyGICallableInfo_Type);
+    PyGIVFuncInfo_Type.tp_descr_get = (descrgetfunc) _vfunc_info_descr_get;
+
     _PyGI_REGISTER_TYPE (m, PyGIUnresolvedInfo_Type, UnresolvedInfo,
                          PyGIBaseInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGICallbackInfo_Type, CallbackInfo,
@@ -2022,8 +2045,6 @@ _pygi_info_register_types (PyObject *m)
                          PyGIBaseInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGIFieldInfo_Type, FieldInfo,
                          PyGIBaseInfo_Type);
-    _PyGI_REGISTER_TYPE (m, PyGIVFuncInfo_Type, VFuncInfo,
-                         PyGICallableInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGIUnionInfo_Type, UnionInfo,
                          PyGIRegisteredTypeInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGIBoxedInfo_Type, BoxedInfo,
diff --git a/gi/types.py b/gi/types.py
index abc52d3..7c0f617 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -46,29 +46,6 @@ if (3, 0) <= sys.version_info < (3, 3):
         return hasattr(obj, '__call__')
 
 
-def wraps_callable_info(info):
-    """Similar to functools.wraps but with specific GICallableInfo support."""
-    def update_func(func):
-        func.__info__ = info
-        func.__name__ = info.__name__
-        func.__module__ = info.__module__
-        func.__doc__ = info.__doc__
-        return func
-    return update_func
-
-
-class NativeVFunc(object):
-    """Wraps GINativeVFuncInfo"""
-    def __init__(self, info):
-        self.__info__ = info
-
-    def __get__(self, instance, klass):
-        @wraps_callable_info(self.__info__)
-        def native_vfunc(*args, **kwargs):
-            return self.__info__.invoke(klass.__gtype__, *args, **kwargs)
-        return native_vfunc
-
-
 class MetaClassHelper(object):
     def _setup_methods(cls):
         for method_info in cls.__info__.get_methods():
@@ -97,9 +74,8 @@ class MetaClassHelper(object):
             vfunc_info = None
             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):
-                    vfunc_info = method.__info__
+                if method is not None and isinstance(method, VFuncInfo):
+                    vfunc_info = method
                     break
 
             # If we did not find a matching method name in the bases, we might
@@ -146,9 +122,8 @@ class MetaClassHelper(object):
             return
 
         for vfunc_info in class_info.get_vfuncs():
-            name = 'do_%s' % vfunc_info.get_name()
-            value = NativeVFunc(vfunc_info)
-            setattr(cls, name, value)
+            name = 'do_%s' % vfunc_info.__name__
+            setattr(cls, name, vfunc_info)
 
 
 def find_vfunc_info_in_interface(bases, vfunc_name):


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]