[pygobject] GLib overrides: code cleanup
- From: Martin Pitt <martinpitt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] GLib overrides: code cleanup
- Date: Sat, 3 Nov 2012 10:25:56 +0000 (UTC)
commit ae6d0aada9587cd4dca168375527b80785b604a0
Author: Martin Pitt <martinpitt gnome org>
Date: Sat Nov 3 11:23:06 2012 +0100
GLib overrides: code cleanup
Factorize the logic to handle zero or multiple user_data arguments into
user_data_varargs_shim(), and put code that handles deprecated API into the
corresponding "then" branches, to improve readability.
gi/overrides/GLib.py | 87 +++++++++++++++++++++++++++-----------------------
1 files changed, 47 insertions(+), 40 deletions(-)
---
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index a53c5e6..2c03b6a 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -566,39 +566,47 @@ class Timeout(Source):
__all__.append('Timeout')
-_unspecified = object()
+def user_data_varargs_shim(callback, user_data, cb_num_args=0):
+ '''Adjust callback and user_data varargs for PyGTK backwards compatibility
+
+ GLib only accepts exactly one user_data argument, but older pygtk
+ traditionally accepted zero or more for some specific functions. For "one
+ argument", use the actual user-supplied callback for efficiency; for all
+ others, rewire it to accept zero or more than one.
+
+ Return the adjusted callback and the real user data to pass to GLib.
+ '''
+ if len(user_data) == 1:
+ return (callback, user_data[0])
+
+ if cb_num_args == 0:
+ return (lambda data: callback(*data), user_data)
+ if cb_num_args == 2:
+ return (lambda a1, a2, data: callback(a1, a2, *data), user_data)
+ raise NotImplementedError('%i number of callback arguments not supported' % cb_num_args)
# backwards compatible API
def idle_add(function, *user_data, **kwargs):
+ (fn, data) = user_data_varargs_shim(function, user_data)
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT_IDLE)
- if len(user_data) == 1:
- return GLib.idle_add(priority, function, user_data[0])
-
- # backwards compat: we have to call the callback with all the user_data arguments
- return GLib.idle_add(priority, lambda data: function(*data), user_data)
+ return GLib.idle_add(priority, fn, data)
__all__.append('idle_add')
def timeout_add(interval, function, *user_data, **kwargs):
+ (fn, data) = user_data_varargs_shim(function, user_data)
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
- if len(user_data) == 1:
- return GLib.timeout_add(priority, interval, function, user_data[0])
-
- # backwards compat: we have to call the callback with all the user_data arguments
- return GLib.timeout_add(priority, interval, lambda data: function(*data), user_data)
+ return GLib.timeout_add(priority, interval, fn, data)
__all__.append('timeout_add')
def timeout_add_seconds(interval, function, *user_data, **kwargs):
+ (fn, data) = user_data_varargs_shim(function, user_data)
priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
- if len(user_data) == 1:
- return GLib.timeout_add_seconds(priority, interval, function, user_data[0])
-
- # backwards compat: we have to call the callback with all the user_data arguments
- return GLib.timeout_add_seconds(priority, interval, lambda data: function(*data), user_data)
+ return GLib.timeout_add_seconds(priority, interval, fn, data)
__all__.append('timeout_add_seconds')
@@ -610,28 +618,31 @@ __all__.append('timeout_add_seconds')
# - calling without a priority as second argument
# and the usual "call without or multiple user_data", in which case the
# callback gets the same user data arguments.
-def io_add_watch(channel, priority_, condition, callback=_unspecified, *user_data, **kwargs):
+def io_add_watch(channel, priority_, condition, *cb_and_user_data, **kwargs):
if not isinstance(priority_, int) or isinstance(priority_, GLib.IOCondition):
warnings.warn('Calling io_add_watch without priority as second argument is deprecated',
PyGIDeprecationWarning)
# shift the arguments around
- if callback == _unspecified:
- user_data = ()
- else:
- user_data = (callback,) + user_data
+ user_data = cb_and_user_data
callback = condition
condition = priority_
- priority_ = GLib.PRIORITY_DEFAULT
-
- if len(user_data) != 1:
- # we have to call the callback with the user_data arguments
- func = lambda channel, cond, data: callback(channel, cond, *data)
- elif user_data[0] == _unspecified:
- user_data = None
- func = lambda channel, cond, data: callback(channel, cond)
+ if not callable(callback):
+ raise TypeError('third argument must be callable')
+
+ # backwards compatibility: Call with priority kwarg
+ if 'priority' in kwargs:
+ warnings.warn('Calling io_add_watch with priority keyword argument is deprecated, put it as second positional argument',
+ PyGIDeprecationWarning)
+ priority_ = kwargs['priority']
+ else:
+ priority_ = GLib.PRIORITY_DEFAULT
else:
- user_data = user_data[0]
- func = callback
+ if len(cb_and_user_data) < 1 or not callable(cb_and_user_data[0]):
+ raise TypeError('expecting callback as fourth argument')
+ callback = cb_and_user_data[0]
+ user_data = cb_and_user_data[1:]
+
+ (func, user_data) = user_data_varargs_shim(callback, user_data, 2)
# backwards compatibility: Allow calling with fd
if isinstance(channel, int):
@@ -650,12 +661,6 @@ def io_add_watch(channel, priority_, condition, callback=_unspecified, *user_dat
func_fdtransform = func
real_channel = channel
- # backwards compatibility: Call with priority kwarg
- if 'priority' in kwargs:
- warnings.warn('Calling io_add_watch with priority keyword argument is deprecated, put it as second positional argument',
- PyGIDeprecationWarning)
- priority_ = kwargs['priority']
-
return GLib.io_add_watch(real_channel, priority_, condition,
func_fdtransform, user_data)
@@ -719,9 +724,9 @@ class IOChannel(GLib.IOChannel):
raise ValueError("invalid 'whence' value")
return self.seek_position(offset, w)
- def add_watch(self, condition, callback, user_data=_unspecified,
- priority=GLib.PRIORITY_DEFAULT):
- return io_add_watch(self, priority, condition, callback, user_data)
+ def add_watch(self, condition, callback, *user_data, **kwargs):
+ priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
+ return io_add_watch(self, priority, condition, callback, *user_data)
add_watch = deprecated(add_watch, 'GLib.io_add_watch()')
@@ -748,6 +753,8 @@ __all__.append('IOChannel')
# and the usual "call without user_data", in which case the callback does not
# get an user_data either.
def child_watch_add(priority_or_pid, pid_or_callback, *args, **kwargs):
+ _unspecified = object()
+
if callable(pid_or_callback):
warnings.warn('Calling child_watch_add without priority as first argument is deprecated',
PyGIDeprecationWarning)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]