Imported Upstream version 3.24.0
[platform/upstream/python-gobject.git] / gi / overrides / GObject.py
index 2187ce5..2e8f755 100644 (file)
 
 import sys
 import warnings
-import functools
 from collections import namedtuple
 
 import gi.overrides
 import gi.module
-from gi.overrides import override
+from gi.overrides import override, deprecated_attr
 from gi.repository import GLib
 from gi import PyGIDeprecationWarning
 
-from gi._gobject import _gobject
-from gi._gobject import propertyhelper
-from gi._gobject import signalhelper
+from gi import _propertyhelper as propertyhelper
+from gi import _signalhelper as signalhelper
+
+_gobject = gi._gi._gobject
 
 GObjectModule = gi.module.get_introspection_module('GObject')
 
 __all__ = []
 
 
-from gi._glib import option
+from gi import _option as option
 sys.modules['gi._gobject.option'] = option
 
 
@@ -56,10 +56,11 @@ for name in ['markup_escape_text', 'get_application_name',
              'idle_add', 'timeout_add', 'timeout_add_seconds',
              'io_add_watch', 'child_watch_add', 'get_current_time',
              'spawn_async']:
-    globals()[name] = gi.overrides.deprecated(getattr(GLib, name), 'GLib.' + name)
+    globals()[name] = getattr(GLib, name)
+    deprecated_attr("GObject", name, "GLib." + name)
     __all__.append(name)
 
-# constants are also deprecated, but cannot mark them as such
+# deprecated constants
 for name in ['PRIORITY_DEFAULT', 'PRIORITY_DEFAULT_IDLE', 'PRIORITY_HIGH',
              'PRIORITY_HIGH_IDLE', 'PRIORITY_LOW',
              'IO_IN', 'IO_OUT', 'IO_PRI', 'IO_ERR', 'IO_HUP', 'IO_NVAL',
@@ -77,25 +78,21 @@ for name in ['PRIORITY_DEFAULT', 'PRIORITY_DEFAULT_IDLE', 'PRIORITY_HIGH',
              'OPTION_FLAG_NOALIAS', 'OPTION_ERROR_UNKNOWN_OPTION',
              'OPTION_ERROR_BAD_VALUE', 'OPTION_ERROR_FAILED', 'OPTION_REMAINING',
              'glib_version']:
-    globals()[name] = getattr(GLib, name)
+    with warnings.catch_warnings():
+        # TODO: this uses deprecated Glib attributes, silence for now
+        warnings.simplefilter('ignore', PyGIDeprecationWarning)
+        globals()[name] = getattr(GLib, name)
+    deprecated_attr("GObject", name, "GLib." + name)
     __all__.append(name)
 
 
-G_MININT8 = GLib.MININT8
-G_MAXINT8 = GLib.MAXINT8
-G_MAXUINT8 = GLib.MAXUINT8
-G_MININT16 = GLib.MININT16
-G_MAXINT16 = GLib.MAXINT16
-G_MAXUINT16 = GLib.MAXUINT16
-G_MININT32 = GLib.MININT32
-G_MAXINT32 = GLib.MAXINT32
-G_MAXUINT32 = GLib.MAXUINT32
-G_MININT64 = GLib.MININT64
-G_MAXINT64 = GLib.MAXINT64
-G_MAXUINT64 = GLib.MAXUINT64
-__all__ += ['G_MININT8', 'G_MAXINT8', 'G_MAXUINT8', 'G_MININT16',
-            'G_MAXINT16', 'G_MAXUINT16', 'G_MININT32', 'G_MAXINT32',
-            'G_MAXUINT32', 'G_MININT64', 'G_MAXINT64', 'G_MAXUINT64']
+for name in ['G_MININT8', 'G_MAXINT8', 'G_MAXUINT8', 'G_MININT16',
+             'G_MAXINT16', 'G_MAXUINT16', 'G_MININT32', 'G_MAXINT32',
+             'G_MAXUINT32', 'G_MININT64', 'G_MAXINT64', 'G_MAXUINT64']:
+    new_name = name.split("_", 1)[-1]
+    globals()[name] = getattr(GLib, new_name)
+    deprecated_attr("GObject", name, "GLib." + new_name)
+    __all__.append(name)
 
 # these are not currently exported in GLib gir, presumably because they are
 # platform dependent; so get them from our static bindings
@@ -103,7 +100,9 @@ for name in ['G_MINFLOAT', 'G_MAXFLOAT', 'G_MINDOUBLE', 'G_MAXDOUBLE',
              'G_MINSHORT', 'G_MAXSHORT', 'G_MAXUSHORT', 'G_MININT', 'G_MAXINT',
              'G_MAXUINT', 'G_MINLONG', 'G_MAXLONG', 'G_MAXULONG', 'G_MAXSIZE',
              'G_MINSSIZE', 'G_MAXSSIZE', 'G_MINOFFSET', 'G_MAXOFFSET']:
-    globals()[name] = getattr(_gobject, name)
+    new_name = name.split("_", 1)[-1]
+    globals()[name] = getattr(GLib, new_name)
+    deprecated_attr("GObject", name, "GLib." + new_name)
     __all__.append(name)
 
 
@@ -145,38 +144,44 @@ __all__ += ['TYPE_INVALID', 'TYPE_NONE', 'TYPE_INTERFACE', 'TYPE_CHAR',
 
 
 # Deprecated, use GLib directly
-Pid = GLib.Pid
-GError = GLib.GError
-OptionGroup = GLib.OptionGroup
-OptionContext = GLib.OptionContext
-__all__ += ['Pid', 'GError', 'OptionGroup', 'OptionContext']
+for name in ['Pid', 'GError', 'OptionGroup', 'OptionContext']:
+    globals()[name] = getattr(GLib, name)
+    deprecated_attr("GObject", name, "GLib." + name)
+    __all__.append(name)
 
 
 # Deprecated, use: GObject.ParamFlags.* directly
-PARAM_CONSTRUCT = GObjectModule.ParamFlags.CONSTRUCT
-PARAM_CONSTRUCT_ONLY = GObjectModule.ParamFlags.CONSTRUCT_ONLY
-PARAM_LAX_VALIDATION = GObjectModule.ParamFlags.LAX_VALIDATION
-PARAM_READABLE = GObjectModule.ParamFlags.READABLE
-PARAM_WRITABLE = GObjectModule.ParamFlags.WRITABLE
+for name in ['PARAM_CONSTRUCT', 'PARAM_CONSTRUCT_ONLY', 'PARAM_LAX_VALIDATION',
+             'PARAM_READABLE', 'PARAM_WRITABLE']:
+    new_name = name.split("_", 1)[-1]
+    globals()[name] = getattr(GObjectModule.ParamFlags, new_name)
+    deprecated_attr("GObject", name, "GObject.ParamFlags." + new_name)
+    __all__.append(name)
+
 # PARAM_READWRITE should come from the gi module but cannot due to:
 # https://bugzilla.gnome.org/show_bug.cgi?id=687615
-PARAM_READWRITE = PARAM_READABLE | PARAM_WRITABLE
-__all__ += ['PARAM_CONSTRUCT', 'PARAM_CONSTRUCT_ONLY', 'PARAM_LAX_VALIDATION',
-            'PARAM_READABLE', 'PARAM_WRITABLE', 'PARAM_READWRITE']
+PARAM_READWRITE = GObjectModule.ParamFlags.READABLE | \
+    GObjectModule.ParamFlags.WRITABLE
+__all__.append("PARAM_READWRITE")
 
+# READWRITE is part of ParamFlags since glib 2.42. Only mark PARAM_READWRITE as
+# deprecated in case ParamFlags.READWRITE is available. Also include the glib
+# version in the warning so it's clear that this needs a newer glib, unlike
+# the other ParamFlags related deprecations.
+# https://bugzilla.gnome.org/show_bug.cgi?id=726037
+if hasattr(GObjectModule.ParamFlags, "READWRITE"):
+    deprecated_attr("GObject", "PARAM_READWRITE",
+                    "GObject.ParamFlags.READWRITE (glib 2.42+)")
 
-# Deprecated, use: GObject.SignalFlags.* directly
-SIGNAL_ACTION = GObjectModule.SignalFlags.ACTION
-SIGNAL_DETAILED = GObjectModule.SignalFlags.DETAILED
-SIGNAL_NO_HOOKS = GObjectModule.SignalFlags.NO_HOOKS
-SIGNAL_NO_RECURSE = GObjectModule.SignalFlags.NO_RECURSE
-SIGNAL_RUN_CLEANUP = GObjectModule.SignalFlags.RUN_CLEANUP
-SIGNAL_RUN_FIRST = GObjectModule.SignalFlags.RUN_FIRST
-SIGNAL_RUN_LAST = GObjectModule.SignalFlags.RUN_LAST
-__all__ += ['SIGNAL_ACTION', 'SIGNAL_DETAILED', 'SIGNAL_NO_HOOKS',
-            'SIGNAL_NO_RECURSE', 'SIGNAL_RUN_CLEANUP', 'SIGNAL_RUN_FIRST',
-            'SIGNAL_RUN_LAST']
 
+# Deprecated, use: GObject.SignalFlags.* directly
+for name in ['SIGNAL_ACTION', 'SIGNAL_DETAILED', 'SIGNAL_NO_HOOKS',
+             'SIGNAL_NO_RECURSE', 'SIGNAL_RUN_CLEANUP', 'SIGNAL_RUN_FIRST',
+             'SIGNAL_RUN_LAST']:
+    new_name = name.split("_", 1)[-1]
+    globals()[name] = getattr(GObjectModule.SignalFlags, new_name)
+    deprecated_attr("GObject", name, "GObject.SignalFlags." + new_name)
+    __all__.append(name)
 
 # Static types
 GBoxed = _gobject.GBoxed
@@ -216,6 +221,9 @@ class Value(GObjectModule.Value):
         if self._free_on_dealloc and self.g_type != TYPE_INVALID:
             self.unset()
 
+        # We must call base class __del__() after unset.
+        super(Value, self).__del__()
+
     def set_boxed(self, boxed):
         # Workaround the introspection marshalers inability to know
         # these methods should be marshaling boxed types. This is because
@@ -343,6 +351,7 @@ class Value(GObjectModule.Value):
     def __repr__(self):
         return '<Value (%s) %s>' % (self.g_type.name, self.get_value())
 
+
 Value = override(Value)
 __all__.append('Value')
 
@@ -353,6 +362,7 @@ def type_from_name(name):
         raise RuntimeError('unknown type name: %s' % name)
     return type_
 
+
 __all__.append('type_from_name')
 
 
@@ -362,6 +372,7 @@ def type_parent(type_):
         raise RuntimeError('no parent for type')
     return parent
 
+
 __all__.append('type_parent')
 
 
@@ -376,6 +387,7 @@ def signal_list_ids(type_):
     _validate_type_for_signal_method(type_)
     return GObjectModule.signal_list_ids(type_)
 
+
 __all__.append('signal_list_ids')
 
 
@@ -383,6 +395,7 @@ def signal_list_names(type_):
     ids = signal_list_ids(type_)
     return tuple(GObjectModule.signal_name(i) for i in ids)
 
+
 __all__.append('signal_list_names')
 
 
@@ -390,34 +403,39 @@ def signal_lookup(name, type_):
     _validate_type_for_signal_method(type_)
     return GObjectModule.signal_lookup(name, type_)
 
+
 __all__.append('signal_lookup')
 
 
+SignalQuery = namedtuple('SignalQuery',
+                         ['signal_id',
+                          'signal_name',
+                          'itype',
+                          'signal_flags',
+                          'return_type',
+                          # n_params',
+                          'param_types'])
+
+
 def signal_query(id_or_name, type_=None):
-    SignalQuery = namedtuple('SignalQuery',
-                             ['signal_id',
-                              'signal_name',
-                              'itype',
-                              'signal_flags',
-                              'return_type',
-                              # n_params',
-                              'param_types'])
-
-    # signal_query needs to use a static method until the following bugs are fixed:
-    # https://bugzilla.gnome.org/show_bug.cgi?id=687550
-    # https://bugzilla.gnome.org/show_bug.cgi?id=687545
-    # https://bugzilla.gnome.org/show_bug.cgi?id=687541
     if type_ is not None:
         id_or_name = signal_lookup(id_or_name, type_)
 
-    res = _gobject.signal_query(id_or_name)
+    res = GObjectModule.signal_query(id_or_name)
     if res is None:
         return None
 
-    # Return a named tuple which allows indexing like the static bindings
-    # along with field like access of the gi struct.
-    # Note however that the n_params was not returned from the static bindings.
-    return SignalQuery(*res)
+    if res.signal_id == 0:
+        return None
+
+    # Return a named tuple to allows indexing which is compatible with the
+    # static bindings along with field like access of the gi struct.
+    # Note however that the n_params was not returned from the static bindings
+    # so we must skip over it.
+    return SignalQuery(res.signal_id, res.signal_name, res.itype,
+                       res.signal_flags, res.return_type,
+                       tuple(res.param_types))
+
 
 __all__.append('signal_query')
 
@@ -435,28 +453,39 @@ class _HandlerBlockManager(object):
 
 
 def signal_handler_block(obj, handler_id):
-    """Blocks the signal handler from being invoked until handler_unblock() is called.
+    """Blocks the signal handler from being invoked until
+    handler_unblock() is called.
 
-    Returns a context manager which optionally can be used to
-    automatically unblock the handler:
+    :param GObject.Object obj:
+        Object instance to block handlers for.
+    :param int handler_id:
+        Id of signal to block.
+    :returns:
+        A context manager which optionally can be used to
+        automatically unblock the handler:
 
-      with GObject.signal_handler_block(obj, id):
-         pass
+    .. code-block:: python
+
+        with GObject.signal_handler_block(obj, id):
+            pass
     """
     GObjectModule.signal_handler_block(obj, handler_id)
     return _HandlerBlockManager(obj, handler_id)
 
+
 __all__.append('signal_handler_block')
 
 
 def signal_parse_name(detailed_signal, itype, force_detail_quark):
     """Parse a detailed signal name into (signal_id, detail).
 
-    :Raises ValueError:
-        If the given signal is unknown.
-
-    :Returns:
+    :param str detailed_signal:
+        Signal name which can include detail.
+        For example: "notify:prop_name"
+    :returns:
         Tuple of (signal_id, detail)
+    :raises ValueError:
+        If the given signal is unknown.
     """
     res, signal_id, detail = GObjectModule.signal_parse_name(detailed_signal, itype,
                                                              force_detail_quark)
@@ -465,6 +494,7 @@ def signal_parse_name(detailed_signal, itype, force_detail_quark):
     else:
         raise ValueError('%s: unknown signal name: %s' % (itype, detailed_signal))
 
+
 __all__.append('signal_parse_name')
 
 
@@ -472,6 +502,7 @@ def remove_emission_hook(obj, detailed_signal, hook_id):
     signal_id, detail = signal_parse_name(detailed_signal, obj, True)
     GObjectModule.signal_remove_emission_hook(signal_id, hook_id)
 
+
 __all__.append('remove_emission_hook')
 
 
@@ -482,6 +513,7 @@ def signal_accumulator_first_wins(ihint, return_accu, handler_return, user_data=
     # Stop emission but return the result of the last handler
     return (False, handler_return)
 
+
 __all__.append('signal_accumulator_first_wins')
 
 
@@ -489,6 +521,7 @@ def signal_accumulator_true_handled(ihint, return_accu, handler_return, user_dat
     # Stop emission if the last handler returns True
     return (not handler_return, handler_return)
 
+
 __all__.append('signal_accumulator_true_handled')
 
 
@@ -515,7 +548,7 @@ 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)
+    @gi.overrides.wraps(func)
     def meth(*args, **kwargs):
         return func(*args, **kwargs)
     return meth
@@ -584,18 +617,58 @@ class Object(GObjectModule.Object):
     def freeze_notify(self):
         """Freezes the object's property-changed notification queue.
 
+        :returns:
+            A context manager which optionally can be used to
+            automatically thaw notifications.
+
         This will freeze the object so that "notify" signals are blocked until
         the thaw_notify() method is called.
 
-        Returns a context manager which optionally can be used to
-        automatically thaw notifications:
+        .. code-block:: python
 
-          with obj.freeze_notify():
-              pass
+            with obj.freeze_notify():
+                pass
         """
         super(Object, self).freeze_notify()
         return _FreezeNotifyManager(self)
 
+    def connect_data(self, detailed_signal, handler, *data, **kwargs):
+        """Connect a callback to the given signal with optional user data.
+
+        :param str detailed_signal:
+            A detailed signal to connect to.
+        :param callable handler:
+            Callback handler to connect to the signal.
+        :param *data:
+            Variable data which is passed through to the signal handler.
+        :param GObject.ConnectFlags connect_flags:
+            Flags used for connection options.
+        :returns:
+            A signal id which can be used with disconnect.
+        """
+        flags = kwargs.get('connect_flags', 0)
+        if flags & GObjectModule.ConnectFlags.AFTER:
+            connect_func = _gobject.GObject.connect_after
+        else:
+            connect_func = _gobject.GObject.connect
+
+        if flags & GObjectModule.ConnectFlags.SWAPPED:
+            if len(data) != 1:
+                raise ValueError('Using GObject.ConnectFlags.SWAPPED requires exactly '
+                                 'one argument for user data, got: %s' % [data])
+
+            def new_handler(obj, *args):
+                # Swap obj with the last element in args which will be the user
+                # data passed to the connect function.
+                args = list(args)
+                swap = args.pop()
+                args = args + [obj]
+                return handler(swap, *args)
+        else:
+            new_handler = handler
+
+        return connect_func(self, detailed_signal, new_handler, *data)
+
     #
     # Aliases
     #
@@ -649,4 +722,5 @@ SignalOverride = signalhelper.SignalOverride
 # Deprecated naming "property" available for backwards compatibility.
 # Keep this at the end of the file to avoid clobbering the builtin.
 property = Property
+deprecated_attr("GObject", "property", "GObject.Property")
 __all__ += ['Property', 'Signal', 'SignalOverride', 'property']