summaryrefslogtreecommitdiff
path: root/gi/overrides/GLib.py
diff options
context:
space:
mode:
Diffstat (limited to 'gi/overrides/GLib.py')
-rw-r--r--gi/overrides/GLib.py557
1 files changed, 533 insertions, 24 deletions
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index 27fe017..f4b1ef5 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -2,6 +2,7 @@
# vim: tabstop=4 shiftwidth=4 expandtab
#
# Copyright (C) 2010 Tomeu Vizoso <tomeu.vizoso@collabora.co.uk>
+# Copyright (C) 2011, 2012 Canonical Ltd.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -18,13 +19,44 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
-from ..importer import modules
-from .._gi import variant_new_tuple, variant_type_from_string
+import signal
+import warnings
+import sys
-GLib = modules['GLib']._introspection_module
+from ..module import get_introspection_module
+from .._gi import (variant_new_tuple, variant_type_from_string, source_new,
+ source_set_callback, io_channel_read)
+from ..overrides import override, deprecated
+from gi import PyGIDeprecationWarning, version_info
+
+GLib = get_introspection_module('GLib')
__all__ = []
+from gi._glib import option
+option # pyflakes
+__all__.append('option')
+
+
+# Types and functions still needed from static bindings
+from gi._glib import _glib
+GError = _glib.GError
+OptionContext = _glib.OptionContext
+OptionGroup = _glib.OptionGroup
+Pid = _glib.Pid
+spawn_async = _glib.spawn_async
+
+
+def threads_init():
+ warnings.warn('threads_init no longer needs to be called. '
+ 'See: https://bugzilla.gnome.org/show_bug.cgi?id=686914',
+ PyGIDeprecationWarning)
+
+
+__all__ += ['GError', 'OptionContext', 'OptionGroup', 'Pid',
+ 'spawn_async', 'threads_init']
+
+
class _VariantCreator(object):
_LEAF_CONSTRUCTORS = {
@@ -83,20 +115,36 @@ class _VariantCreator(object):
def _create_tuple(self, format, args):
'''Handle the case where the outermost type of format is a tuple.'''
- format = format[1:] # eat the '('
- builder = GLib.VariantBuilder.new(variant_type_from_string('r'))
- if args is not None:
- if not args or type(args[0]) != type(()):
- raise (TypeError, 'expected tuple argument')
+ format = format[1:] # eat the '('
+ if args is None:
+ # empty value: we need to call _create() to parse the subtype
+ rest_format = format
+ while rest_format:
+ if rest_format.startswith(')'):
+ break
+ rest_format = self._create(rest_format, None)[1]
+ else:
+ raise TypeError('tuple type string not closed with )')
+ rest_format = rest_format[1:] # eat the )
+ return (None, rest_format, None)
+ else:
+ if not args or not isinstance(args[0], tuple):
+ raise TypeError('expected tuple argument')
+
+ builder = GLib.VariantBuilder.new(variant_type_from_string('r'))
for i in range(len(args[0])):
if format.startswith(')'):
- raise (TypeError, 'too many arguments for tuple signature')
+ raise TypeError('too many arguments for tuple signature')
(v, format, _) = self._create(format, args[0][i:])
builder.add_value(v)
args = args[1:]
- return (builder.end(), format[1:], args)
+ if not format.startswith(')'):
+ raise TypeError('tuple type string not closed with )')
+
+ rest_format = format[1:] # eat the )
+ return (builder.end(), rest_format, args)
def _create_dict(self, format, args):
'''Handle the case where the outermost type of format is a dict.'''
@@ -108,8 +156,8 @@ class _VariantCreator(object):
rest_format = self._create(format[2:], None)[1]
rest_format = self._create(rest_format, None)[1]
if not rest_format.startswith('}'):
- raise ValueError('dictionary type string not closed with }')
- rest_format = rest_format[1:] # eat the }
+ raise TypeError('dictionary type string not closed with }')
+ rest_format = rest_format[1:] # eat the }
element_type = format[:len(format) - len(rest_format)]
builder = GLib.VariantBuilder.new(variant_type_from_string(element_type))
else:
@@ -119,8 +167,8 @@ class _VariantCreator(object):
(val_v, rest_format, _) = self._create(rest_format, [v])
if not rest_format.startswith('}'):
- raise ValueError('dictionary type string not closed with }')
- rest_format = rest_format[1:] # eat the }
+ raise TypeError('dictionary type string not closed with }')
+ rest_format = rest_format[1:] # eat the }
entry = GLib.VariantBuilder.new(variant_type_from_string('{?*}'))
entry.add_value(key_v)
@@ -150,27 +198,39 @@ class _VariantCreator(object):
args = args[1:]
return (builder.end(), rest_format, args)
+
class Variant(GLib.Variant):
def __new__(cls, format_string, value):
'''Create a GVariant from a native Python object.
format_string is a standard GVariant type signature, value is a Python
object whose structure has to match the signature.
-
+
Examples:
GLib.Variant('i', 1)
GLib.Variant('(is)', (1, 'hello'))
- GLib.Variant('(asa{sv})', ([], {'foo': GLib.Variant('b', True),
+ GLib.Variant('(asa{sv})', ([], {'foo': GLib.Variant('b', True),
'bar': GLib.Variant('i', 2)}))
'''
creator = _VariantCreator()
(v, rest_format, _) = creator._create(format_string, [value])
if rest_format:
raise TypeError('invalid remaining format string: "%s"' % rest_format)
+ v.format_string = format_string
return v
+ def __del__(self):
+ self.unref()
+
+ def __str__(self):
+ return self.print_(True)
+
def __repr__(self):
- return '<GLib.Variant(%s)>' % getattr(self, 'print')(True)
+ if hasattr(self, 'format_string'):
+ f = self.format_string
+ else:
+ f = self.get_type_string()
+ return "GLib.Variant('%s', %s)" % (f, self.print_(False))
def __eq__(self, other):
try:
@@ -205,8 +265,8 @@ class Variant(GLib.Variant):
'h': self.get_handle,
'd': self.get_double,
's': self.get_string,
- 'o': self.get_string, # object path
- 'g': self.get_string, # signature
+ 'o': self.get_string, # object path
+ 'g': self.get_string, # signature
}
# simple values
@@ -216,8 +276,8 @@ class Variant(GLib.Variant):
# tuple
if self.get_type_string().startswith('('):
- res = [self.get_child_value(i).unpack()
- for i in range(self.n_children())]
+ res = [self.get_child_value(i).unpack()
+ for i in range(self.n_children())]
return tuple(res)
# dictionary
@@ -230,13 +290,18 @@ class Variant(GLib.Variant):
# array
if self.get_type_string().startswith('a'):
- return [self.get_child_value(i).unpack()
+ return [self.get_child_value(i).unpack()
for i in range(self.n_children())]
# variant (just unbox transparently)
if self.get_type_string().startswith('v'):
return self.get_variant().unpack()
+ # maybe
+ if self.get_type_string().startswith('m'):
+ m = self.get_maybe()
+ return m.unpack() if m else None
+
raise NotImplementedError('unsupported GVariant type ' + self.get_type_string())
@classmethod
@@ -245,7 +310,7 @@ class Variant(GLib.Variant):
If the signature is not a tuple, it returns one element with the entire
signature. If the signature is an empty tuple, the result is [].
-
+
This is useful for e. g. iterating over method parameters which are
passed as a single Variant.
'''
@@ -257,7 +322,7 @@ class Variant(GLib.Variant):
result = []
head = ''
- tail = signature[1:-1] # eat the surrounding ( )
+ tail = signature[1:-1] # eat the surrounding ()
while tail:
c = tail[0]
head += c
@@ -292,6 +357,7 @@ class Variant(GLib.Variant):
#
# Pythonic iterators
#
+
def __len__(self):
if self.get_type_string() in ['s', 'o', 'g']:
return len(self.get_string())
@@ -336,6 +402,7 @@ class Variant(GLib.Variant):
#
# Pythonic bool operations
#
+
def __nonzero__(self):
return self.__bool__()
@@ -365,10 +432,12 @@ class Variant(GLib.Variant):
res.append(v.get_child_value(0).unpack())
return res
+
@classmethod
def new_tuple(cls, *elements):
return variant_new_tuple(elements)
+
def get_string(self):
value, length = GLib.Variant.get_string(self)
return value
@@ -378,3 +447,443 @@ setattr(Variant, 'get_string', get_string)
__all__.append('Variant')
+
+def markup_escape_text(text, length=-1):
+ if isinstance(text, bytes):
+ return GLib.markup_escape_text(text.decode('UTF-8'), length)
+ else:
+ return GLib.markup_escape_text(text, length)
+__all__.append('markup_escape_text')
+
+
+# backwards compatible names from old static bindings
+for n in ['DESKTOP', 'DOCUMENTS', 'DOWNLOAD', 'MUSIC', 'PICTURES',
+ 'PUBLIC_SHARE', 'TEMPLATES', 'VIDEOS']:
+ globals()['USER_DIRECTORY_' + n] = getattr(GLib.UserDirectory, 'DIRECTORY_' + n)
+ __all__.append('USER_DIRECTORY_' + n)
+
+for n in ['ERR', 'HUP', 'IN', 'NVAL', 'OUT', 'PRI']:
+ globals()['IO_' + n] = getattr(GLib.IOCondition, n)
+ __all__.append('IO_' + n)
+
+for n in ['APPEND', 'GET_MASK', 'IS_READABLE', 'IS_SEEKABLE',
+ 'MASK', 'NONBLOCK', 'SET_MASK']:
+ globals()['IO_FLAG_' + n] = getattr(GLib.IOFlags, n)
+ __all__.append('IO_FLAG_' + n)
+# spelling for the win
+IO_FLAG_IS_WRITEABLE = GLib.IOFlags.IS_WRITABLE
+__all__.append('IO_FLAG_IS_WRITEABLE')
+
+for n in ['AGAIN', 'EOF', 'ERROR', 'NORMAL']:
+ globals()['IO_STATUS_' + n] = getattr(GLib.IOStatus, n)
+ __all__.append('IO_STATUS_' + n)
+
+for n in ['CHILD_INHERITS_STDIN', 'DO_NOT_REAP_CHILD', 'FILE_AND_ARGV_ZERO',
+ 'LEAVE_DESCRIPTORS_OPEN', 'SEARCH_PATH', 'STDERR_TO_DEV_NULL',
+ 'STDOUT_TO_DEV_NULL']:
+ globals()['SPAWN_' + n] = getattr(GLib.SpawnFlags, n)
+ __all__.append('SPAWN_' + n)
+
+for n in ['HIDDEN', 'IN_MAIN', 'REVERSE', 'NO_ARG', 'FILENAME', 'OPTIONAL_ARG',
+ 'NOALIAS']:
+ globals()['OPTION_FLAG_' + n] = getattr(GLib.OptionFlags, n)
+ __all__.append('OPTION_FLAG_' + n)
+
+for n in ['UNKNOWN_OPTION', 'BAD_VALUE', 'FAILED']:
+ globals()['OPTION_ERROR_' + n] = getattr(GLib.OptionError, n)
+ __all__.append('OPTION_ERROR_' + n)
+
+
+class MainLoop(GLib.MainLoop):
+ # Backwards compatible constructor API
+ def __new__(cls, context=None):
+ return GLib.MainLoop.new(context, False)
+
+ # Retain classic pygobject behaviour of quitting main loops on SIGINT
+ def __init__(self, context=None):
+ def _handler(loop):
+ loop.quit()
+ loop._quit_by_sigint = True
+ if sys.platform != 'win32':
+ # compatibility shim, keep around until we depend on glib 2.36
+ if hasattr(GLib, 'unix_signal_add'):
+ fn = GLib.unix_signal_add
+ else:
+ fn = GLib.unix_signal_add_full
+ self._signal_source = fn(GLib.PRIORITY_DEFAULT, signal.SIGINT, _handler, self)
+
+ def __del__(self):
+ if hasattr(self, '_signal_source'):
+ GLib.source_remove(self._signal_source)
+
+ def run(self):
+ super(MainLoop, self).run()
+ if hasattr(self, '_quit_by_sigint'):
+ # caught by _main_loop_sigint_handler()
+ raise KeyboardInterrupt
+
+MainLoop = override(MainLoop)
+__all__.append('MainLoop')
+
+
+class MainContext(GLib.MainContext):
+ # Backwards compatible API with default value
+ def iteration(self, may_block=True):
+ return super(MainContext, self).iteration(may_block)
+
+MainContext = override(MainContext)
+__all__.append('MainContext')
+
+
+class Source(GLib.Source):
+ def __new__(cls, *args, **kwargs):
+ # use our custom pyg_source_new() here as g_source_new() is not
+ # bindable
+ source = source_new()
+ source.__class__ = cls
+ setattr(source, '__pygi_custom_source', True)
+ return source
+
+ def __del__(self):
+ if hasattr(self, '__pygi_custom_source'):
+ self.unref()
+
+ # Backwards compatible API for optional arguments
+ def attach(self, context=None):
+ id = super(Source, self).attach(context)
+ return id
+
+ def set_callback(self, fn, user_data=None):
+ if hasattr(self, '__pygi_custom_source'):
+ # use our custom pyg_source_set_callback() if for a GSource object
+ # with custom functions
+ source_set_callback(self, fn, user_data)
+ else:
+ # otherwise, for Idle and Timeout, use the standard method
+ super(Source, self).set_callback(fn, user_data)
+
+ def get_current_time(self):
+ return GLib.get_real_time() * 0.000001
+
+ get_current_time = deprecated(get_current_time,
+ 'GLib.Source.get_time() or GLib.get_real_time()')
+
+ # as get/set_priority are introspected, we can't use the static
+ # property(get_priority, ..) here
+ def __get_priority(self):
+ return self.get_priority()
+
+ def __set_priority(self, value):
+ self.set_priority(value)
+
+ priority = property(__get_priority, __set_priority)
+
+ def __get_can_recurse(self):
+ return self.get_can_recurse()
+
+ def __set_can_recurse(self, value):
+ self.set_can_recurse(value)
+
+ can_recurse = property(__get_can_recurse, __set_can_recurse)
+
+Source = override(Source)
+__all__.append('Source')
+
+
+class Idle(Source):
+ def __new__(cls, priority=GLib.PRIORITY_DEFAULT):
+ source = GLib.idle_source_new()
+ source.__class__ = cls
+ return source
+
+ def __init__(self, priority=GLib.PRIORITY_DEFAULT):
+ super(Source, self).__init__()
+ if priority != GLib.PRIORITY_DEFAULT:
+ self.set_priority(priority)
+
+__all__.append('Idle')
+
+
+class Timeout(Source):
+ def __new__(cls, interval=0, priority=GLib.PRIORITY_DEFAULT):
+ source = GLib.timeout_source_new(interval)
+ source.__class__ = cls
+ return source
+
+ def __init__(self, interval=0, priority=GLib.PRIORITY_DEFAULT):
+ if priority != GLib.PRIORITY_DEFAULT:
+ self.set_priority(priority)
+
+__all__.append('Timeout')
+
+
+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)
+ 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)
+ 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)
+ return GLib.timeout_add_seconds(priority, interval, fn, data)
+
+__all__.append('timeout_add_seconds')
+
+
+# The real GLib API is io_add_watch(IOChannel, priority, condition, callback,
+# user_data). This needs to take into account several historical APIs:
+# - calling with an fd as first argument
+# - calling with a Python file object as first argument (we keep this one as
+# it's really convenient and does not change the number of arguments)
+# - 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, *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
+ user_data = cb_and_user_data
+ callback = condition
+ condition = priority_
+ 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:
+ 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):
+ func_fdtransform = lambda _, cond, data: func(channel, cond, data)
+ real_channel = GLib.IOChannel.unix_new(channel)
+ elif hasattr(channel, 'fileno'):
+ # backwards compatibility: Allow calling with Python file
+ func_fdtransform = lambda _, cond, data: func(channel, cond, data)
+ real_channel = GLib.IOChannel.unix_new(channel.fileno())
+ else:
+ assert isinstance(channel, GLib.IOChannel)
+ func_fdtransform = func
+ real_channel = channel
+
+ return GLib.io_add_watch(real_channel, priority_, condition,
+ func_fdtransform, user_data)
+
+__all__.append('io_add_watch')
+
+
+# backwards compatible API
+class IOChannel(GLib.IOChannel):
+ def __new__(cls, filedes=None, filename=None, mode=None, hwnd=None):
+ if filedes is not None:
+ return GLib.IOChannel.unix_new(filedes)
+ if filename is not None:
+ return GLib.IOChannel.new_file(filename, mode or 'r')
+ if hwnd is not None:
+ return GLib.IOChannel.win32_new_fd(hwnd)
+ raise TypeError('either a valid file descriptor, file name, or window handle must be supplied')
+
+ def read(self, max_count=-1):
+ return io_channel_read(self, max_count)
+
+ def readline(self, size_hint=-1):
+ # note, size_hint is just to maintain backwards compatible API; the
+ # old static binding did not actually use it
+ (status, buf, length, terminator_pos) = self.read_line()
+ if buf is None:
+ return ''
+ return buf
+
+ def readlines(self, size_hint=-1):
+ # note, size_hint is just to maintain backwards compatible API;
+ # the old static binding did not actually use it
+ lines = []
+ status = GLib.IOStatus.NORMAL
+ while status == GLib.IOStatus.NORMAL:
+ (status, buf, length, terminator_pos) = self.read_line()
+ # note, this appends an empty line after EOF; this is
+ # bug-compatible with the old static bindings
+ if buf is None:
+ buf = ''
+ lines.append(buf)
+ return lines
+
+ def write(self, buf, buflen=-1):
+ if not isinstance(buf, bytes):
+ buf = buf.encode('UTF-8')
+ if buflen == -1:
+ buflen = len(buf)
+ (status, written) = self.write_chars(buf, buflen)
+ return written
+
+ def writelines(self, lines):
+ for line in lines:
+ self.write(line)
+
+ _whence_map = {0: GLib.SeekType.SET, 1: GLib.SeekType.CUR, 2: GLib.SeekType.END}
+
+ def seek(self, offset, whence=0):
+ try:
+ w = self._whence_map[whence]
+ except KeyError:
+ raise ValueError("invalid 'whence' value")
+ return self.seek_position(offset, w)
+
+ 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()')
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ (status, buf, length, terminator_pos) = self.read_line()
+ if status == GLib.IOStatus.NORMAL:
+ return buf
+ raise StopIteration
+
+ # Python 2.x compatibility
+ next = __next__
+
+IOChannel = override(IOChannel)
+__all__.append('IOChannel')
+
+
+class PollFD(GLib.PollFD):
+ def __new__(cls, fd, events):
+ pollfd = GLib.PollFD()
+ pollfd.__class__ = cls
+ return pollfd
+
+ def __init__(self, fd, events):
+ self.fd = fd
+ self.events = events
+
+PollFD = override(PollFD)
+__all__.append('PollFD')
+
+
+# The real GLib API is child_watch_add(priority, pid, callback, data).
+# The old static bindings had the following API which we still need to support
+# for a while:
+# child_watch_add(pid, callback, data=None, priority=GLib.PRIORITY_DEFAULT)
+# 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)
+ pid = priority_or_pid
+ callback = pid_or_callback
+ if len(args) == 0:
+ user_data = kwargs.get('data', _unspecified)
+ priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
+ elif len(args) == 1:
+ user_data = args[0]
+ priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
+ elif len(args) == 2:
+ user_data = args[0]
+ priority = args[1]
+ else:
+ raise TypeError('expected at most 4 positional arguments')
+ else:
+ priority = priority_or_pid
+ pid = pid_or_callback
+ if len(args) == 0 or not callable(args[0]):
+ raise TypeError('expected callback as third argument')
+ callback = args[0]
+ if len(args) == 1:
+ user_data = kwargs.get('data', _unspecified)
+ else:
+ user_data = args[1]
+
+ if user_data is _unspecified:
+ # we have to call the callback without the user_data argument
+ func = lambda pid, status, data: callback(pid, status)
+ user_data = None
+ else:
+ func = callback
+
+ return GLib.child_watch_add(priority, pid, func, user_data)
+
+__all__.append('child_watch_add')
+
+
+def get_current_time():
+ return GLib.get_real_time() * 0.000001
+
+get_current_time = deprecated(get_current_time, 'GLib.get_real_time()')
+
+__all__.append('get_current_time')
+
+
+# backwards compatible API with default argument, and ignoring bytes_read
+# output argument
+def filename_from_utf8(utf8string, len=-1):
+ return GLib.filename_from_utf8(utf8string, len)[0]
+
+__all__.append('filename_from_utf8')
+
+
+# backwards compatible API for renamed function
+if not hasattr(GLib, 'unix_signal_add_full'):
+ def add_full_compat(*args):
+ warnings.warn('GLib.unix_signal_add_full() was renamed to GLib.unix_signal_add()',
+ PyGIDeprecationWarning)
+ return GLib.unix_signal_add(*args)
+
+ GLib.unix_signal_add_full = add_full_compat
+
+
+# obsolete constants for backwards compatibility
+glib_version = (GLib.MAJOR_VERSION, GLib.MINOR_VERSION, GLib.MICRO_VERSION)
+__all__.append('glib_version')
+pyglib_version = version_info
+__all__.append('pyglib_version')