1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # vim: tabstop=4 shiftwidth=4 expandtab
4 # Copyright (C) 2012 Canonical Ltd.
5 # Author: Martin Pitt <martin.pitt@ubuntu.com>
6 # Copyright (C) 2012 Simon Feltman <sfeltman@src.gnome.org>
7 # Copyright (C) 2012 Bastian Winkler <buz@netbuz.org>
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public
11 # License as published by the Free Software Foundation; either
12 # version 2.1 of the License, or (at your option) any later version.
14 # This library is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 # Lesser General Public License for more details.
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with this library; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
25 from collections import namedtuple
29 from gi.overrides import override
30 from gi.repository import GLib
32 from gi._gobject import _gobject
33 from gi._gobject import propertyhelper
34 from gi._gobject import signalhelper
36 GObjectModule = gi.module.get_introspection_module('GObject')
41 from gi._glib import option
42 sys.modules['gi._gobject.option'] = option
45 # API aliases for backwards compatibility
46 for name in ['markup_escape_text', 'get_application_name',
47 'set_application_name', 'get_prgname', 'set_prgname',
48 'main_depth', 'filename_display_basename',
49 'filename_display_name', 'filename_from_utf8',
50 'uri_list_extract_uris',
51 'MainLoop', 'MainContext', 'main_context_default',
52 'source_remove', 'Source', 'Idle', 'Timeout', 'PollFD',
53 'idle_add', 'timeout_add', 'timeout_add_seconds',
54 'io_add_watch', 'child_watch_add', 'get_current_time',
56 globals()[name] = gi.overrides.deprecated(getattr(GLib, name), 'GLib.' + name)
59 # constants are also deprecated, but cannot mark them as such
60 for name in ['PRIORITY_DEFAULT', 'PRIORITY_DEFAULT_IDLE', 'PRIORITY_HIGH',
61 'PRIORITY_HIGH_IDLE', 'PRIORITY_LOW',
62 'IO_IN', 'IO_OUT', 'IO_PRI', 'IO_ERR', 'IO_HUP', 'IO_NVAL',
63 'IO_STATUS_ERROR', 'IO_STATUS_NORMAL', 'IO_STATUS_EOF',
64 'IO_STATUS_AGAIN', 'IO_FLAG_APPEND', 'IO_FLAG_NONBLOCK',
65 'IO_FLAG_IS_READABLE', 'IO_FLAG_IS_WRITEABLE',
66 'IO_FLAG_IS_SEEKABLE', 'IO_FLAG_MASK', 'IO_FLAG_GET_MASK',
68 'SPAWN_LEAVE_DESCRIPTORS_OPEN', 'SPAWN_DO_NOT_REAP_CHILD',
69 'SPAWN_SEARCH_PATH', 'SPAWN_STDOUT_TO_DEV_NULL',
70 'SPAWN_STDERR_TO_DEV_NULL', 'SPAWN_CHILD_INHERITS_STDIN',
71 'SPAWN_FILE_AND_ARGV_ZERO',
72 'OPTION_FLAG_HIDDEN', 'OPTION_FLAG_IN_MAIN', 'OPTION_FLAG_REVERSE',
73 'OPTION_FLAG_NO_ARG', 'OPTION_FLAG_FILENAME', 'OPTION_FLAG_OPTIONAL_ARG',
74 'OPTION_FLAG_NOALIAS', 'OPTION_ERROR_UNKNOWN_OPTION',
75 'OPTION_ERROR_BAD_VALUE', 'OPTION_ERROR_FAILED', 'OPTION_REMAINING',
77 globals()[name] = getattr(GLib, name)
81 G_MININT8 = GLib.MININT8
82 G_MAXINT8 = GLib.MAXINT8
83 G_MAXUINT8 = GLib.MAXUINT8
84 G_MININT16 = GLib.MININT16
85 G_MAXINT16 = GLib.MAXINT16
86 G_MAXUINT16 = GLib.MAXUINT16
87 G_MININT32 = GLib.MININT32
88 G_MAXINT32 = GLib.MAXINT32
89 G_MAXUINT32 = GLib.MAXUINT32
90 G_MININT64 = GLib.MININT64
91 G_MAXINT64 = GLib.MAXINT64
92 G_MAXUINT64 = GLib.MAXUINT64
93 __all__ += ['G_MININT8', 'G_MAXINT8', 'G_MAXUINT8', 'G_MININT16',
94 'G_MAXINT16', 'G_MAXUINT16', 'G_MININT32', 'G_MAXINT32',
95 'G_MAXUINT32', 'G_MININT64', 'G_MAXINT64', 'G_MAXUINT64']
97 # these are not currently exported in GLib gir, presumably because they are
98 # platform dependent; so get them from our static bindings
99 for name in ['G_MINFLOAT', 'G_MAXFLOAT', 'G_MINDOUBLE', 'G_MAXDOUBLE',
100 'G_MINSHORT', 'G_MAXSHORT', 'G_MAXUSHORT', 'G_MININT', 'G_MAXINT',
101 'G_MAXUINT', 'G_MINLONG', 'G_MAXLONG', 'G_MAXULONG', 'G_MAXSIZE',
102 'G_MINSSIZE', 'G_MAXSSIZE', 'G_MINOFFSET', 'G_MAXOFFSET']:
103 globals()[name] = getattr(_gobject, name)
107 TYPE_INVALID = GObjectModule.type_from_name('invalid')
108 TYPE_NONE = GObjectModule.type_from_name('void')
109 TYPE_INTERFACE = GObjectModule.type_from_name('GInterface')
110 TYPE_CHAR = GObjectModule.type_from_name('gchar')
111 TYPE_UCHAR = GObjectModule.type_from_name('guchar')
112 TYPE_BOOLEAN = GObjectModule.type_from_name('gboolean')
113 TYPE_INT = GObjectModule.type_from_name('gint')
114 TYPE_UINT = GObjectModule.type_from_name('guint')
115 TYPE_LONG = GObjectModule.type_from_name('glong')
116 TYPE_ULONG = GObjectModule.type_from_name('gulong')
117 TYPE_INT64 = GObjectModule.type_from_name('gint64')
118 TYPE_UINT64 = GObjectModule.type_from_name('guint64')
119 TYPE_ENUM = GObjectModule.type_from_name('GEnum')
120 TYPE_FLAGS = GObjectModule.type_from_name('GFlags')
121 TYPE_FLOAT = GObjectModule.type_from_name('gfloat')
122 TYPE_DOUBLE = GObjectModule.type_from_name('gdouble')
123 TYPE_STRING = GObjectModule.type_from_name('gchararray')
124 TYPE_POINTER = GObjectModule.type_from_name('gpointer')
125 TYPE_BOXED = GObjectModule.type_from_name('GBoxed')
126 TYPE_PARAM = GObjectModule.type_from_name('GParam')
127 TYPE_OBJECT = GObjectModule.type_from_name('GObject')
128 TYPE_PYOBJECT = GObjectModule.type_from_name('PyObject')
129 TYPE_GTYPE = GObjectModule.type_from_name('GType')
130 TYPE_STRV = GObjectModule.type_from_name('GStrv')
131 TYPE_VARIANT = GObjectModule.type_from_name('GVariant')
132 TYPE_GSTRING = GObjectModule.type_from_name('GString')
133 TYPE_UNICHAR = TYPE_UINT
134 __all__ += ['TYPE_INVALID', 'TYPE_NONE', 'TYPE_INTERFACE', 'TYPE_CHAR',
135 'TYPE_UCHAR', 'TYPE_BOOLEAN', 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONG',
136 'TYPE_ULONG', 'TYPE_INT64', 'TYPE_UINT64', 'TYPE_ENUM', 'TYPE_FLAGS',
137 'TYPE_FLOAT', 'TYPE_DOUBLE', 'TYPE_STRING', 'TYPE_POINTER',
138 'TYPE_BOXED', 'TYPE_PARAM', 'TYPE_OBJECT', 'TYPE_PYOBJECT',
139 'TYPE_GTYPE', 'TYPE_STRV', 'TYPE_VARIANT', 'TYPE_GSTRING', 'TYPE_UNICHAR']
142 # Deprecated, use GLib directly
145 OptionGroup = GLib.OptionGroup
146 OptionContext = GLib.OptionContext
147 __all__ += ['Pid', 'GError', 'OptionGroup', 'OptionContext']
150 # Deprecated, use: GObject.ParamFlags.* directly
151 PARAM_CONSTRUCT = GObjectModule.ParamFlags.CONSTRUCT
152 PARAM_CONSTRUCT_ONLY = GObjectModule.ParamFlags.CONSTRUCT_ONLY
153 PARAM_LAX_VALIDATION = GObjectModule.ParamFlags.LAX_VALIDATION
154 PARAM_READABLE = GObjectModule.ParamFlags.READABLE
155 PARAM_WRITABLE = GObjectModule.ParamFlags.WRITABLE
156 # PARAM_READWRITE should come from the gi module but cannot due to:
157 # https://bugzilla.gnome.org/show_bug.cgi?id=687615
158 PARAM_READWRITE = PARAM_READABLE | PARAM_WRITABLE
159 __all__ += ['PARAM_CONSTRUCT', 'PARAM_CONSTRUCT_ONLY', 'PARAM_LAX_VALIDATION',
160 'PARAM_READABLE', 'PARAM_WRITABLE', 'PARAM_READWRITE']
163 # Deprecated, use: GObject.SignalFlags.* directly
164 SIGNAL_ACTION = GObjectModule.SignalFlags.ACTION
165 SIGNAL_DETAILED = GObjectModule.SignalFlags.DETAILED
166 SIGNAL_NO_HOOKS = GObjectModule.SignalFlags.NO_HOOKS
167 SIGNAL_NO_RECURSE = GObjectModule.SignalFlags.NO_RECURSE
168 SIGNAL_RUN_CLEANUP = GObjectModule.SignalFlags.RUN_CLEANUP
169 SIGNAL_RUN_FIRST = GObjectModule.SignalFlags.RUN_FIRST
170 SIGNAL_RUN_LAST = GObjectModule.SignalFlags.RUN_LAST
171 __all__ += ['SIGNAL_ACTION', 'SIGNAL_DETAILED', 'SIGNAL_NO_HOOKS',
172 'SIGNAL_NO_RECURSE', 'SIGNAL_RUN_CLEANUP', 'SIGNAL_RUN_FIRST',
177 GBoxed = _gobject.GBoxed
178 GEnum = _gobject.GEnum
179 GFlags = _gobject.GFlags
180 GInterface = _gobject.GInterface
181 GObject = _gobject.GObject
182 GObjectWeakRef = _gobject.GObjectWeakRef
183 GParamSpec = _gobject.GParamSpec
184 GPointer = _gobject.GPointer
185 GType = _gobject.GType
186 Warning = _gobject.Warning
187 __all__ += ['GBoxed', 'GEnum', 'GFlags', 'GInterface', 'GObject',
188 'GObjectWeakRef', 'GParamSpec', 'GPointer', 'GType',
192 add_emission_hook = _gobject.add_emission_hook
193 features = _gobject.features
194 list_properties = _gobject.list_properties
196 pygobject_version = _gobject.pygobject_version
197 remove_emission_hook = _gobject.remove_emission_hook
198 signal_accumulator_true_handled = _gobject.signal_accumulator_true_handled
199 signal_new = _gobject.signal_new
200 threads_init = _gobject.threads_init
201 type_register = _gobject.type_register
202 __all__ += ['add_emission_hook', 'features', 'list_properties',
203 'new', 'pygobject_version', 'remove_emission_hook',
204 'signal_accumulator_true_handled',
205 'signal_new', 'threads_init', 'type_register']
208 class Value(GObjectModule.Value):
209 def __new__(cls, *args, **kwargs):
210 return GObjectModule.Value.__new__(cls)
212 def __init__(self, value_type=None, py_value=None):
213 GObjectModule.Value.__init__(self)
214 if value_type is not None:
215 self.init(value_type)
216 if py_value is not None:
217 self.set_value(py_value)
220 if self._free_on_dealloc and self.g_type != TYPE_INVALID:
223 def set_value(self, py_value):
224 if self.g_type == _gobject.TYPE_INVALID:
225 raise TypeError("GObject.Value needs to be initialized first")
226 elif self.g_type == TYPE_BOOLEAN:
227 self.set_boolean(py_value)
228 elif self.g_type == TYPE_CHAR:
229 self.set_char(py_value)
230 elif self.g_type == TYPE_UCHAR:
231 self.set_uchar(py_value)
232 elif self.g_type == TYPE_INT:
233 self.set_int(py_value)
234 elif self.g_type == TYPE_UINT:
235 self.set_uint(py_value)
236 elif self.g_type == TYPE_LONG:
237 self.set_long(py_value)
238 elif self.g_type == TYPE_ULONG:
239 self.set_ulong(py_value)
240 elif self.g_type == TYPE_INT64:
241 self.set_int64(py_value)
242 elif self.g_type == TYPE_UINT64:
243 self.set_uint64(py_value)
244 elif self.g_type == TYPE_FLOAT:
245 self.set_float(py_value)
246 elif self.g_type == TYPE_DOUBLE:
247 self.set_double(py_value)
248 elif self.g_type == TYPE_STRING:
249 if isinstance(py_value, str):
250 py_value = str(py_value)
251 elif sys.version_info < (3, 0):
252 if isinstance(py_value, unicode):
253 py_value = py_value.encode('UTF-8')
255 raise ValueError("Expected string or unicode but got %s%s" %
256 (py_value, type(py_value)))
258 raise ValueError("Expected string but got %s%s" %
259 (py_value, type(py_value)))
260 self.set_string(py_value)
261 elif self.g_type == TYPE_PARAM:
262 self.set_param(py_value)
263 elif self.g_type.is_a(TYPE_ENUM):
264 self.set_enum(py_value)
265 elif self.g_type.is_a(TYPE_FLAGS):
266 self.set_flags(py_value)
267 elif self.g_type.is_a(TYPE_BOXED):
268 self.set_boxed(py_value)
269 elif self.g_type == TYPE_POINTER:
270 self.set_pointer(py_value)
271 elif self.g_type.is_a(TYPE_OBJECT):
272 self.set_object(py_value)
273 elif self.g_type == TYPE_UNICHAR:
274 self.set_uint(int(py_value))
275 # elif self.g_type == TYPE_OVERRIDE:
277 elif self.g_type == TYPE_GTYPE:
278 self.set_gtype(py_value)
279 elif self.g_type == TYPE_VARIANT:
280 self.set_variant(py_value)
281 elif self.g_type == TYPE_PYOBJECT:
282 self.set_boxed(py_value)
284 raise TypeError("Unknown value type %s" % self.g_type)
287 if self.g_type == TYPE_BOOLEAN:
288 return self.get_boolean()
289 elif self.g_type == TYPE_CHAR:
290 return self.get_char()
291 elif self.g_type == TYPE_UCHAR:
292 return self.get_uchar()
293 elif self.g_type == TYPE_INT:
294 return self.get_int()
295 elif self.g_type == TYPE_UINT:
296 return self.get_uint()
297 elif self.g_type == TYPE_LONG:
298 return self.get_long()
299 elif self.g_type == TYPE_ULONG:
300 return self.get_ulong()
301 elif self.g_type == TYPE_INT64:
302 return self.get_int64()
303 elif self.g_type == TYPE_UINT64:
304 return self.get_uint64()
305 elif self.g_type == TYPE_FLOAT:
306 return self.get_float()
307 elif self.g_type == TYPE_DOUBLE:
308 return self.get_double()
309 elif self.g_type == TYPE_STRING:
310 return self.get_string()
311 elif self.g_type == TYPE_PARAM:
312 return self.get_param()
313 elif self.g_type.is_a(TYPE_ENUM):
314 return self.get_enum()
315 elif self.g_type.is_a(TYPE_FLAGS):
316 return self.get_flags()
317 elif self.g_type.is_a(TYPE_BOXED):
318 return self.get_boxed()
319 elif self.g_type == TYPE_POINTER:
320 return self.get_pointer()
321 elif self.g_type.is_a(TYPE_OBJECT):
322 return self.get_object()
323 elif self.g_type == TYPE_UNICHAR:
324 return self.get_uint()
325 elif self.g_type == TYPE_GTYPE:
326 return self.get_gtype()
327 elif self.g_type == TYPE_VARIANT:
328 return self.get_variant()
329 elif self.g_type == TYPE_PYOBJECT:
335 return '<Value (%s) %s>' % (self.g_type.name, self.get_value())
337 Value = override(Value)
338 __all__.append('Value')
341 def type_from_name(name):
342 type_ = GObjectModule.type_from_name(name)
343 if type_ == TYPE_INVALID:
344 raise RuntimeError('unknown type name: %s' % name)
347 __all__.append('type_from_name')
350 def type_parent(type_):
351 parent = GObjectModule.type_parent(type_)
352 if parent == TYPE_INVALID:
353 raise RuntimeError('no parent for type')
356 __all__.append('type_parent')
359 def _validate_type_for_signal_method(type_):
360 if hasattr(type_, '__gtype__'):
361 type_ = type_.__gtype__
362 if not type_.is_instantiatable() and not type_.is_interface():
363 raise TypeError('type must be instantiable or an interface, got %s' % type_)
366 def signal_list_ids(type_):
367 _validate_type_for_signal_method(type_)
368 return GObjectModule.signal_list_ids(type_)
370 __all__.append('signal_list_ids')
373 def signal_list_names(type_):
374 ids = signal_list_ids(type_)
375 return tuple(GObjectModule.signal_name(i) for i in ids)
377 __all__.append('signal_list_names')
380 def signal_lookup(name, type_):
381 _validate_type_for_signal_method(type_)
382 return GObjectModule.signal_lookup(name, type_)
384 __all__.append('signal_lookup')
387 def signal_query(id_or_name, type_=None):
388 SignalQuery = namedtuple('SignalQuery',
397 # signal_query needs to use a static method until the following bugs are fixed:
398 # https://bugzilla.gnome.org/show_bug.cgi?id=687550
399 # https://bugzilla.gnome.org/show_bug.cgi?id=687545
400 # https://bugzilla.gnome.org/show_bug.cgi?id=687541
401 if type_ is not None:
402 id_or_name = signal_lookup(id_or_name, type_)
404 res = _gobject.signal_query(id_or_name)
408 # Return a named tuple which allows indexing like the static bindings
409 # along with field like access of the gi struct.
410 # Note however that the n_params was not returned from the static bindings.
411 return SignalQuery(*res)
413 __all__.append('signal_query')
416 class _HandlerBlockManager(object):
417 def __init__(self, obj, handler_id):
419 self.handler_id = handler_id
424 def __exit__(self, exc_type, exc_value, traceback):
425 _gobject.GObject.handler_unblock(self.obj, self.handler_id)
428 class _FreezeNotifyManager(object):
429 def __init__(self, obj):
435 def __exit__(self, exc_type, exc_value, traceback):
436 self.obj.thaw_notify()
439 class Object(GObjectModule.Object):
440 def _unsupported_method(self, *args, **kargs):
441 raise RuntimeError('This method is currently unsupported.')
443 def _unsupported_data_method(self, *args, **kargs):
444 raise RuntimeError('Data access methods are unsupported. '
445 'Use normal Python attributes instead')
447 # Generic data methods are not needed in python as it can be handled
448 # with standard attribute access: https://bugzilla.gnome.org/show_bug.cgi?id=641944
449 get_data = _unsupported_data_method
450 get_qdata = _unsupported_data_method
451 set_data = _unsupported_data_method
452 steal_data = _unsupported_data_method
453 steal_qdata = _unsupported_data_method
454 replace_data = _unsupported_data_method
455 replace_qdata = _unsupported_data_method
457 # The following methods as unsupported until we verify
458 # they work as gi methods.
459 bind_property_full = _unsupported_method
460 compat_control = _unsupported_method
461 force_floating = _unsupported_method
462 interface_find_property = _unsupported_method
463 interface_install_property = _unsupported_method
464 interface_list_properties = _unsupported_method
465 is_floating = _unsupported_method
466 notify_by_pspec = _unsupported_method
467 ref = _unsupported_method
468 ref_count = _unsupported_method
469 ref_sink = _unsupported_method
470 run_dispose = _unsupported_method
471 unref = _unsupported_method
472 watch_closure = _unsupported_method
474 # The following methods are static APIs which need to leap frog the
475 # gi methods until we verify the gi methods can replace them.
476 get_property = _gobject.GObject.get_property
477 get_properties = _gobject.GObject.get_properties
478 set_property = _gobject.GObject.set_property
479 set_properties = _gobject.GObject.set_properties
480 bind_property = _gobject.GObject.bind_property
481 connect = _gobject.GObject.connect
482 connect_after = _gobject.GObject.connect_after
483 connect_object = _gobject.GObject.connect_object
484 connect_object_after = _gobject.GObject.connect_object_after
485 disconnect = _gobject.GObject.disconnect
486 disconnect_by_func = _gobject.GObject.disconnect_by_func
487 handler_disconnect = _gobject.GObject.handler_disconnect
488 handler_is_connected = _gobject.GObject.handler_is_connected
489 handler_block_by_func = _gobject.GObject.handler_block_by_func
490 handler_unblock_by_func = _gobject.GObject.handler_unblock_by_func
491 emit = _gobject.GObject.emit
492 emit_stop_by_name = _gobject.GObject.emit_stop_by_name
493 stop_emission = _gobject.GObject.stop_emission
494 chain = _gobject.GObject.chain
495 weak_ref = _gobject.GObject.weak_ref
496 __copy__ = _gobject.GObject.__copy__
497 __deepcopy__ = _gobject.GObject.__deepcopy__
499 def handler_block(self, handler_id):
500 """Blocks the signal handler from being invoked until handler_unblock() is called.
502 Returns a context manager which optionally can be used to
503 automatically unblock the handler:
505 >>> with obj.handler_block(id):
509 # Note Object.handler_block is a static method specific to pygobject and not
510 # found in introspection. We need to continue using the static method
511 # until we figure out a technique to call the global signal_handler_block.
512 # But this requires a gpointer to the Object which we currently don't have
513 # access to in python.
514 _gobject.GObject.handler_block(self, handler_id)
515 return _HandlerBlockManager(self, handler_id)
517 def freeze_notify(self):
518 """Freezes the object's property-changed notification queue.
520 This will freeze the object so that "notify" signals are blocked until
521 the thaw_notify() method is called.
523 Returns a context manager which optionally can be used to
524 automatically thaw notifications:
526 >>> with obj.freeze_notify():
529 super(Object, self).freeze_notify()
530 return _FreezeNotifyManager(self)
533 Object = override(Object)
535 __all__ += ['Object', 'GObject']
538 Property = propertyhelper.Property
539 Signal = signalhelper.Signal
540 SignalOverride = signalhelper.SignalOverride
541 # Deprecated naming "property" available for backwards compatibility.
542 # Keep this at the end of the file to avoid clobbering the builtin.
544 __all__ += ['Property', 'Signal', 'SignalOverride', 'property']