[pygobject] Fix GObject signal methods to work with new annotations



commit 9df8eb79929025f12d51bc7f79b1d160156c2755
Author: Simon Feltman <sfeltman src gnome org>
Date:   Mon Sep 2 04:19:35 2013 -0700

    Fix GObject signal methods to work with new annotations
    
    Add conditional support for signal methods annotated as gpointer
    or GObject.Object. This is needed to work with newer versions of
    glib which changed annotations to GObject.Object (bug #685387).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=707280

 gi/overrides/GObject.py |  106 +++++++++++++++++++++++++++++------------------
 1 files changed, 66 insertions(+), 40 deletions(-)
---
diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py
index 044c36e..b3aad47 100644
--- a/gi/overrides/GObject.py
+++ b/gi/overrides/GObject.py
@@ -425,20 +425,21 @@ def signal_query(id_or_name, type_=None):
 __all__.append('signal_query')
 
 
+# Check needed for glib versions which annotate signal related methods
+# with a void pointer instead of GObject.Object.
+# See: https://bugzilla.gnome.org/show_bug.cgi?id=685387
+_is_first_signal_arg_void = GObjectModule.signal_stop_emission.get_arguments()[0].get_pytype_hint() == 'void'
+
+
 def _get_instance_for_signal(obj):
-    if isinstance(obj, GObjectModule.Object):
+    if not _is_first_signal_arg_void:
+        return obj
+    elif isinstance(obj, GObjectModule.Object):
         return obj.__gpointer__
     else:
         raise TypeError('Unsupported object "%s" for signal function' % obj)
 
 
-def _wrap_signal_func(func):
-    @functools.wraps(func)
-    def wrapper(obj, *args, **kwargs):
-        return func(_get_instance_for_signal(obj), *args, **kwargs)
-    return wrapper
-
-
 class _HandlerBlockManager(object):
     def __init__(self, obj, handler_id):
         self.obj = obj
@@ -466,32 +467,47 @@ def signal_handler_block(obj, handler_id):
 __all__.append('signal_handler_block')
 
 
-# The following functions wrap GI functions but coerce the first arg into
-# something compatible with gpointer
-
-signal_handler_unblock = _wrap_signal_func(GObjectModule.signal_handler_unblock)
-signal_handler_disconnect = _wrap_signal_func(GObjectModule.signal_handler_disconnect)
-signal_handler_is_connected = _wrap_signal_func(GObjectModule.signal_handler_is_connected)
-signal_stop_emission = _wrap_signal_func(GObjectModule.signal_stop_emission)
-signal_stop_emission_by_name = _wrap_signal_func(GObjectModule.signal_stop_emission_by_name)
-signal_has_handler_pending = _wrap_signal_func(GObjectModule.signal_has_handler_pending)
-signal_get_invocation_hint = _wrap_signal_func(GObjectModule.signal_get_invocation_hint)
-signal_connect_closure = _wrap_signal_func(GObjectModule.signal_connect_closure)
-signal_connect_closure_by_id = _wrap_signal_func(GObjectModule.signal_connect_closure_by_id)
-signal_handler_find = _wrap_signal_func(GObjectModule.signal_handler_find)
-signal_handlers_destroy = _wrap_signal_func(GObjectModule.signal_handlers_destroy)
-signal_handlers_block_matched = _wrap_signal_func(GObjectModule.signal_handlers_block_matched)
-signal_handlers_unblock_matched = _wrap_signal_func(GObjectModule.signal_handlers_unblock_matched)
-signal_handlers_disconnect_matched = _wrap_signal_func(GObjectModule.signal_handlers_disconnect_matched)
-
-__all__ += ['signal_handler_unblock',
-            'signal_handler_disconnect', 'signal_handler_is_connected',
-            'signal_stop_emission', 'signal_stop_emission_by_name',
-            'signal_has_handler_pending', 'signal_get_invocation_hint',
-            'signal_connect_closure', 'signal_connect_closure_by_id',
-            'signal_handler_find', 'signal_handlers_destroy',
-            'signal_handlers_block_matched', 'signal_handlers_unblock_matched',
-            'signal_handlers_disconnect_matched']
+if _is_first_signal_arg_void:
+    # The following functions wrap GI functions but coerce the first arg into
+    # something compatible with gpointer
+
+    def _wrap_signal_func(func):
+        @functools.wraps(func)
+        def wrapper(obj, *args, **kwargs):
+            return func(_get_instance_for_signal(obj), *args, **kwargs)
+        return wrapper
+
+    signal_handler_unblock = _wrap_signal_func(GObjectModule.signal_handler_unblock)
+    signal_handler_disconnect = _wrap_signal_func(GObjectModule.signal_handler_disconnect)
+    signal_handler_is_connected = _wrap_signal_func(GObjectModule.signal_handler_is_connected)
+    signal_stop_emission = _wrap_signal_func(GObjectModule.signal_stop_emission)
+    signal_stop_emission_by_name = _wrap_signal_func(GObjectModule.signal_stop_emission_by_name)
+    signal_has_handler_pending = _wrap_signal_func(GObjectModule.signal_has_handler_pending)
+    signal_get_invocation_hint = _wrap_signal_func(GObjectModule.signal_get_invocation_hint)
+    signal_connect_closure = _wrap_signal_func(GObjectModule.signal_connect_closure)
+    signal_connect_closure_by_id = _wrap_signal_func(GObjectModule.signal_connect_closure_by_id)
+    signal_handler_find = _wrap_signal_func(GObjectModule.signal_handler_find)
+    signal_handlers_destroy = _wrap_signal_func(GObjectModule.signal_handlers_destroy)
+    signal_handlers_block_matched = _wrap_signal_func(GObjectModule.signal_handlers_block_matched)
+    signal_handlers_unblock_matched = _wrap_signal_func(GObjectModule.signal_handlers_unblock_matched)
+    signal_handlers_disconnect_matched = _wrap_signal_func(GObjectModule.signal_handlers_disconnect_matched)
+
+    __all__ += ['signal_handler_unblock',
+                'signal_handler_disconnect', 'signal_handler_is_connected',
+                'signal_stop_emission', 'signal_stop_emission_by_name',
+                'signal_has_handler_pending', 'signal_get_invocation_hint',
+                'signal_connect_closure', 'signal_connect_closure_by_id',
+                'signal_handler_find', 'signal_handlers_destroy',
+                'signal_handlers_block_matched', 'signal_handlers_unblock_matched',
+                'signal_handlers_disconnect_matched']
+else:
+    # First signal arg is GObject.Object but we need these as globals for
+    # our GObject.Object class override below
+    signal_handler_disconnect = GObjectModule.signal_handler_disconnect
+    signal_handler_unblock = GObjectModule.signal_handler_unblock
+    signal_handler_disconnect = GObjectModule.signal_handler_disconnect
+    signal_handler_is_connected = GObjectModule.signal_handler_is_connected
+    signal_stop_emission_by_name = GObjectModule.signal_stop_emission_by_name
 
 
 def signal_parse_name(detailed_signal, itype, force_detail_quark):
@@ -556,6 +572,16 @@ class _FreezeNotifyManager(object):
         self.obj.thaw_notify()
 
 
+def _signalmethod(func):
+    # Function wrapper for signal functions used as instance methods.
+    # This is needed when the signal functions come directly from GI.
+    # (they are not already wrapped)
+    @functools.wraps(func)
+    def meth(*args, **kwargs):
+        return func(*args, **kwargs)
+    return meth
+
+
 class Object(GObjectModule.Object):
     def _unsupported_method(self, *args, **kargs):
         raise RuntimeError('This method is currently unsupported.')
@@ -635,12 +661,12 @@ class Object(GObjectModule.Object):
     # Aliases
     #
 
-    disconnect = signal_handler_disconnect
-    handler_block = signal_handler_block
-    handler_unblock = signal_handler_unblock
-    handler_disconnect = signal_handler_disconnect
-    handler_is_connected = signal_handler_is_connected
-    stop_emission_by_name = signal_stop_emission_by_name
+    disconnect = _signalmethod(signal_handler_disconnect)
+    handler_block = _signalmethod(signal_handler_block)
+    handler_unblock = _signalmethod(signal_handler_unblock)
+    handler_disconnect = _signalmethod(signal_handler_disconnect)
+    handler_is_connected = _signalmethod(signal_handler_is_connected)
+    stop_emission_by_name = _signalmethod(signal_stop_emission_by_name)
 
     #
     # Deprecated Methods


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