[pygobject] Remove static idle_add/timeout_add bindings



commit 1b27432abf6004553e9476d5ffeb2bf603534419
Author: Martin Pitt <martinpitt gnome org>
Date:   Wed Oct 24 08:50:37 2012 +0200

    Remove static idle_add/timeout_add bindings
    
    Use the GLib functions through GI instead. Add overrides to ensure that default
    arguments continue to work as before, and that callbacks are called without an
    userdata argument if it wasn't specified.

 docs/reference/pyglib-functions.xml |  165 -----------------------------------
 gi/_glib/__init__.py                |    3 -
 gi/_glib/glibmodule.c               |  139 -----------------------------
 gi/_gobject/__init__.py             |    3 -
 gi/overrides/GLib.py                |   31 +++++++
 gi/overrides/GObject.py             |    3 +-
 tests/test_source.py                |   19 ++++
 7 files changed, 52 insertions(+), 311 deletions(-)
---
diff --git a/docs/reference/pyglib-functions.xml b/docs/reference/pyglib-functions.xml
index 0354082..e3a63ac 100644
--- a/docs/reference/pyglib-functions.xml
+++ b/docs/reference/pyglib-functions.xml
@@ -14,23 +14,6 @@
     <programlisting>
 <methodsynopsis language="python">
 	<methodname><link
-linkend="function-glib--idle-add">glib.idle_add</link></methodname>
-	<methodparam><parameter>callback</parameter></methodparam>
-	<methodparam><parameter>...</parameter></methodparam>
-  </methodsynopsis><methodsynopsis language="python">
-	<methodname><link
-linkend="function-glib--timeout-add">glib.timeout_add</link></methodname>
-	<methodparam><parameter>interval</parameter></methodparam>
-	<methodparam><parameter>callback</parameter></methodparam>
-	<methodparam><parameter>...</parameter></methodparam>
-  </methodsynopsis><methodsynopsis language="python">
-	<methodname><link
-linkend="function-glib--timeout-add-seconds">glib.timeout_add_seconds</link></methodname>
-	<methodparam><parameter>interval</parameter></methodparam>
-	<methodparam><parameter>callback</parameter></methodparam>
-	<methodparam><parameter>...</parameter></methodparam>
-  </methodsynopsis><methodsynopsis language="python">
-	<methodname><link
 linkend="function-glib--io-add-watch">glib.io_add_watch</link></methodname>
 	<methodparam><parameter>fd</parameter></methodparam>
 	<methodparam><parameter>condition</parameter></methodparam>
@@ -79,154 +62,6 @@ module but are not directly associated with a specific class.</para>
   <refsect1>
     <title>Functions</title>
 
-    <refsect2 id="function-glib--idle-add">
-      <title>glib.idle_add</title>
-
-      <programlisting><methodsynopsis language="python">
-	  <methodname>glib.idle_add</methodname>
-	  <methodparam><parameter>callback</parameter></methodparam>
-	  <methodparam><parameter>...</parameter></methodparam>
-	</methodsynopsis></programlisting>
-      <variablelist>
-	<varlistentry>
-	  <term><parameter>callback</parameter>&nbsp;:</term>
-	  <listitem><simpara>a function to call when
-<literal>PyGTK</literal> is idle</simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><parameter>...</parameter>&nbsp;:</term>
-	  <listitem><simpara>optionals arguments to be passed to
-<parameter>callback</parameter></simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><emphasis>Returns</emphasis>&nbsp;:</term>
-	  <listitem><simpara>an integer ID</simpara></listitem>
-	</varlistentry>
-      </variablelist>
-
-      <para>The <function>glib.idle_add</function>() function adds a
-function (specified by <parameter>callback</parameter>) to be called
-whenever there are no higher priority events pending to the default main
-loop. The function is given the default idle priority,
-<literal>glib.PRIORITY_DEFAULT_IDLE</literal>. Additional arguments to
-pass to <parameter>callback</parameter> can be specified after
-<parameter>callback</parameter>. The idle priority can be specified as a
-keyword-value pair with the keyword "priority". If
-<parameter>callback</parameter> returns <literal>False</literal> it is
-automatically removed from the list of event sources and will not be called
-again.</para>
-
-    </refsect2>
-
-    <refsect2 id="function-glib--timeout-add">
-      <title>glib.timeout_add</title>
-
-      <programlisting><methodsynopsis language="python">
-	  <methodname>glib.timeout_add</methodname>
-	  <methodparam><parameter>interval</parameter></methodparam>
-	  <methodparam><parameter>callback</parameter></methodparam>
-	  <methodparam><parameter>...</parameter></methodparam>
-	</methodsynopsis></programlisting>
-      <variablelist>
-	<varlistentry>
-	  <term><parameter>interval</parameter>&nbsp;:</term>
-	  <listitem><simpara>the time between calls to the function, in
-milliseconds </simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><parameter>callback</parameter>&nbsp;:</term>
-	  <listitem><simpara>the function to call</simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><parameter>...</parameter>&nbsp;:</term>
-	  <listitem><simpara>zero or more arguments that will be passed to
-<parameter>callback</parameter></simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><emphasis>Returns</emphasis>&nbsp;:</term>
-	  <listitem><simpara>an integer ID of the event
-source</simpara></listitem>
-	</varlistentry>
-      </variablelist>
-
-      <para>The <function>glib.timeout_add</function>() function sets a
-function (specified by <parameter>callback</parameter>) to be called at
-regular intervals (specified by <parameter>interval</parameter>, with the
-default priority, <literal>glib.PRIORITY_DEFAULT</literal>. Additional
-arguments to pass to <parameter>callback</parameter> can be specified after
-<parameter>callback</parameter>. The idle priority may be specified as a
-keyword-value pair with the keyword "priority".</para>
-
-      <para>The function is called repeatedly until it returns
-<literal>False</literal>, at which point the timeout is automatically
-destroyed and the function will not be called again. The first call to the
-function will be at the end of the first interval. Note that timeout
-functions may be delayed, due to the processing of other event sources. Thus
-they should not be relied on for precise timing. After each call to the
-timeout function, the time of the next timeout is recalculated based on the
-current time and the given interval (it does not try to 'catch up' time lost
-in delays).</para>
-
-    </refsect2>
-
-    <refsect2 id="function-glib--timeout-add-seconds">
-      <title>glib.timeout_add_seconds</title>
-
-      <programlisting><methodsynopsis language="python">
-	  <methodname>glib.timeout_add_seconds</methodname>
-	  <methodparam><parameter>interval</parameter></methodparam>
-	  <methodparam><parameter>callback</parameter></methodparam>
-	  <methodparam><parameter>...</parameter></methodparam>
-	</methodsynopsis></programlisting>
-      <variablelist>
-	<varlistentry>
-	  <term><parameter>interval</parameter>&nbsp;:</term>
-	  <listitem><simpara>the time between calls to the function, in
-seconds </simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><parameter>callback</parameter>&nbsp;:</term>
-	  <listitem><simpara>the function to call</simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><parameter>...</parameter>&nbsp;:</term>
-	  <listitem><simpara>zero or more arguments that will be passed to
-<parameter>callback</parameter></simpara></listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term><emphasis>Returns</emphasis>&nbsp;:</term>
-	  <listitem><simpara>an integer ID of the event
-source</simpara></listitem>
-	</varlistentry>
-      </variablelist>
-
-      <para>The <function>glib.timeout_add_seconds</function>() is similar to
-	<function>glib.timeout_add</function>() except
-	that <parameter>interval</parameter> must be specified in seconds, not
-	milliseconds, and the function should cause less CPU wakeups, which is important
-	for laptops' batteries.</para>
-
-      <para>Unlike <function>glib.timeout_add</function>(), this function operates at
-	whole second granularity.  The initial starting point of the timer is determined
-	by the implementation and the implementation is expected to group multiple timers
-	together so that they fire all at the same time.  To allow this grouping, the
-	interval to the first timer is rounded and can deviate up to one second from the
-	specified interval.  Subsequent timer iterations will generally run at the
-	specified interval.</para>
-
-      <para>Note that timeout functions may be delayed, due to the processing of other
-	event sources.  Thus they should not be relied on for precise timing.  After each
-	call to the timeout function, the time of the next timeout is recalculated based
-	on the current time and the given interval.</para>
-
-      <para>The grouping of timers to fire at the same time results in a more power and
-	CPU efficient behavior so if your timer is in multiples of seconds and you don't
-	require the first timer exactly one second from now, the use of
-	<function>glib.timeout_add_seconds</function>() is preferred
-	over <function>glib.timeout_add</function>().</para>
-
-    </refsect2>
-
     <refsect2 id="function-glib--io-add-watch">
       <title>glib.io_add_watch</title>
 
diff --git a/gi/_glib/__init__.py b/gi/_glib/__init__.py
index b9e5fa4..c65c20b 100644
--- a/gi/_glib/__init__.py
+++ b/gi/_glib/__init__.py
@@ -76,10 +76,7 @@ child_watch_add = _glib.child_watch_add
 filename_from_utf8 = _glib.filename_from_utf8
 get_current_time = _glib.get_current_time
 glib_version = _glib.glib_version
-idle_add = _glib.idle_add
 io_add_watch = _glib.io_add_watch
 pyglib_version = _glib.pyglib_version
 spawn_async = _glib.spawn_async
 threads_init = _glib.threads_init
-timeout_add = _glib.timeout_add
-timeout_add_seconds = _glib.timeout_add_seconds
diff --git a/gi/_glib/glibmodule.c b/gi/_glib/glibmodule.c
index dbe5054..a2b3e25 100644
--- a/gi/_glib/glibmodule.c
+++ b/gi/_glib/glibmodule.c
@@ -97,124 +97,6 @@ pyglib_threads_init(PyObject *unused, PyObject *args, PyObject *kwargs)
     return Py_None;
 }
 
-static PyObject *
-pyglib_idle_add(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    PyObject *first, *callback, *cbargs = NULL, *data;
-    gint len, priority = G_PRIORITY_DEFAULT_IDLE;
-    guint handler_id;
-
-    len = PyTuple_Size(args);
-    if (len < 1) {
-	PyErr_SetString(PyExc_TypeError,
-			"idle_add requires at least 1 argument");
-	return NULL;
-    }
-    first = PySequence_GetSlice(args, 0, 1);
-    if (!PyArg_ParseTuple(first, "O:idle_add", &callback)) {
-	Py_DECREF(first);
-        return NULL;
-    }
-    Py_DECREF(first);
-    if (!PyCallable_Check(callback)) {
-        PyErr_SetString(PyExc_TypeError, "first argument not callable");
-        return NULL;
-    }
-    if (get_handler_priority(&priority, kwargs) < 0)
-	return NULL;
-
-    cbargs = PySequence_GetSlice(args, 1, len);
-    if (cbargs == NULL)
-	return NULL;
-
-    data = Py_BuildValue("(ON)", callback, cbargs);
-    if (data == NULL)
-	return NULL;
-    handler_id = g_idle_add_full(priority,
-				 _pyglib_handler_marshal, data,
-				 _pyglib_destroy_notify);
-    return PYGLIB_PyLong_FromLong(handler_id);
-}
-
-
-static PyObject *
-pyglib_timeout_add(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    PyObject *first, *callback, *cbargs = NULL, *data;
-    gint len, priority = G_PRIORITY_DEFAULT;
-    guint interval, handler_id;
-
-    len = PyTuple_Size(args);
-    if (len < 2) {
-	PyErr_SetString(PyExc_TypeError,
-			"timeout_add requires at least 2 args");
-	return NULL;
-    }
-    first = PySequence_GetSlice(args, 0, 2);
-    if (!PyArg_ParseTuple(first, "IO:timeout_add", &interval, &callback)) {
-	Py_DECREF(first);
-        return NULL;
-    }
-    Py_DECREF(first);
-    if (!PyCallable_Check(callback)) {
-        PyErr_SetString(PyExc_TypeError, "second argument not callable");
-        return NULL;
-    }
-    if (get_handler_priority(&priority, kwargs) < 0)
-	return NULL;
-
-    cbargs = PySequence_GetSlice(args, 2, len);
-    if (cbargs == NULL)
-	return NULL;
-
-    data = Py_BuildValue("(ON)", callback, cbargs);
-    if (data == NULL)
-	return NULL;
-    handler_id = g_timeout_add_full(priority, interval,
-				    _pyglib_handler_marshal, data,
-				    _pyglib_destroy_notify);
-    return PYGLIB_PyLong_FromLong(handler_id);
-}
-
-static PyObject *
-pyglib_timeout_add_seconds(PyObject *self, PyObject *args, PyObject *kwargs)
-{
-    PyObject *first, *callback, *cbargs = NULL, *data;
-    gint len, priority = G_PRIORITY_DEFAULT;
-    guint interval, handler_id;
-
-    len = PyTuple_Size(args);
-    if (len < 2) {
-	PyErr_SetString(PyExc_TypeError,
-			"timeout_add_seconds requires at least 2 args");
-	return NULL;
-    }
-    first = PySequence_GetSlice(args, 0, 2);
-    if (!PyArg_ParseTuple(first, "IO:timeout_add_seconds", &interval, &callback)) {
-	Py_DECREF(first);
-        return NULL;
-    }
-    Py_DECREF(first);
-    if (!PyCallable_Check(callback)) {
-        PyErr_SetString(PyExc_TypeError, "second argument not callable");
-        return NULL;
-    }
-    if (get_handler_priority(&priority, kwargs) < 0)
-	return NULL;
-
-    cbargs = PySequence_GetSlice(args, 2, len);
-    if (cbargs == NULL)
-	return NULL;
-
-    data = Py_BuildValue("(ON)", callback, cbargs);
-    if (data == NULL)
-	return NULL;
-    handler_id = g_timeout_add_seconds_full(priority, interval,
-                                            _pyglib_handler_marshal, data,
-                                            _pyglib_destroy_notify);
-    return PYGLIB_PyLong_FromLong(handler_id);
-}
-
 static gboolean
 iowatch_marshal(GIOChannel *source,
 		GIOCondition condition,
@@ -409,27 +291,6 @@ static PyMethodDef _glib_functions[] = {
       "Initialize GLib for use from multiple threads. If you also use GTK+\n"
       "itself (i.e. GUI, not just PyGObject), use gtk.gdk.threads_init()\n"
       "instead." },
-    { "idle_add",
-      (PyCFunction)pyglib_idle_add, METH_VARARGS|METH_KEYWORDS,
-      "idle_add(callable, user_data=None, priority=None) -> source id\n"
-      "  callable receives (user_data)\n"
-      "Adds a callable to be called whenever there are no higher priority\n"
-      "events pending to the default main loop." },
-    { "timeout_add",
-      (PyCFunction)pyglib_timeout_add, METH_VARARGS|METH_KEYWORDS,
-      "timeout_add(interval, callable, user_data=None,\n"
-      "            priority=None) -> source id\n"
-      "  callable receives (user_data)\n"
-      "Sets a callable be called repeatedly until it returns False." },
-    { "timeout_add_seconds",
-      (PyCFunction)pyglib_timeout_add_seconds, METH_VARARGS|METH_KEYWORDS,
-      "timeout_add(interval, callable, user_data=None,\n"
-      "            priority=None) -> source_id\n"
-      "  callable receives (user_data)\n"
-      "Sets a callable be called repeatedly until it returns False.\n"
-      "Use this if you want to have a timer in the \"seconds\" range\n"
-      "and do not care about the exact time of the first call of the\n"
-      "timer, use this for more efficient system power usage." },
     { "io_add_watch",
       (PyCFunction)pyglib_io_add_watch, METH_VARARGS|METH_KEYWORDS,
       "io_add_watch(fd, condition, callback, user_data=None) -> source id\n"
diff --git a/gi/_gobject/__init__.py b/gi/_gobject/__init__.py
index 2098d27..5e18246 100644
--- a/gi/_gobject/__init__.py
+++ b/gi/_gobject/__init__.py
@@ -82,9 +82,6 @@ type_parent = _gobject.type_parent
 type_register = _gobject.type_register
 
 spawn_async = _glib.spawn_async
-idle_add = _glib.idle_add
-timeout_add = _glib.timeout_add
-timeout_add_seconds = _glib.timeout_add_seconds
 io_add_watch = _glib.io_add_watch
 child_watch_add = _glib.child_watch_add
 get_current_time = _glib.get_current_time
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index 7b656e8..2b704af 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -541,6 +541,37 @@ class Timeout(Source):
 __all__.append('Timeout')
 
 
+__unspecified = object()
+
+
+# backwards compatible API
+def _glib_idle_adjust_callback(function, user_data):
+    if user_data is __unspecified:
+        # we have to call the callback without the user_data argument
+        return (lambda data: function(), None)
+    return (function, user_data)
+
+
+def idle_add(function, user_data=__unspecified, priority=GLib.PRIORITY_DEFAULT_IDLE):
+    (function, user_data) = _glib_idle_adjust_callback(function, user_data)
+    return GLib.idle_add(priority, function, user_data)
+
+__all__.append('idle_add')
+
+
+def timeout_add(interval, function, user_data=__unspecified, priority=GLib.PRIORITY_DEFAULT):
+    (function, user_data) = _glib_idle_adjust_callback(function, user_data)
+    return GLib.timeout_add(priority, interval, function, user_data)
+
+__all__.append('timeout_add')
+
+
+def timeout_add_seconds(interval, function, user_data=__unspecified, priority=GLib.PRIORITY_DEFAULT):
+    (function, user_data) = _glib_idle_adjust_callback(function, user_data)
+    return GLib.timeout_add_seconds(priority, interval, function, user_data)
+
+__all__.append('timeout_add_seconds')
+
 # work around wrong constants in GLib GIR, see
 # https://bugzilla.gnome.org/show_bug.cgi?id=685022
 MININT64 = -9223372036854775808
diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py
index 3bc2189..a2a8741 100644
--- a/gi/overrides/GObject.py
+++ b/gi/overrides/GObject.py
@@ -30,7 +30,8 @@ for name in ['markup_escape_text', 'get_application_name',
              'main_depth', 'filename_display_basename',
              'filename_display_name', 'uri_list_extract_uris',
              'MainLoop', 'MainContext', 'main_context_default',
-             'source_remove', 'Source', 'Idle', 'Timeout', 'PollFD']:
+             'source_remove', 'Source', 'Idle', 'Timeout', 'PollFD',
+             'idle_add', 'timeout_add', 'timeout_add_seconds']:
     globals()[name] = gi.overrides.deprecated(getattr(GLib, name), 'GLib.' + name)
     __all__.append(name)
 
diff --git a/tests/test_source.py b/tests/test_source.py
index cca4a94..38d03ab 100644
--- a/tests/test_source.py
+++ b/tests/test_source.py
@@ -276,6 +276,25 @@ class TestUserData(unittest.TestCase):
         ml.run()
         self.assertTrue(data['called'])
 
+    def cb_no_data(self):
+        self.loop.quit()
+
+    def test_idle_method_callback_no_data(self):
+        self.loop = GLib.MainLoop()
+        GLib.idle_add(self.cb_no_data)
+        self.loop.run()
+
+    def cb_with_data(self, data):
+        data['called'] = True
+        self.loop.quit()
+
+    def test_idle_method_callback_with_data(self):
+        self.loop = GLib.MainLoop()
+        data = {}
+        GLib.idle_add(self.cb_with_data, data)
+        self.loop.run()
+        self.assertTrue(data['called'])
+
 
 if __name__ == '__main__':
     unittest.main()



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