/usr/lib/python3/dist-packages/twisted/internet/gireactor.py is in python3-twisted-experimental 13.2.0-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | # Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
This module provides support for Twisted to interact with the glib
mainloop via GObject Introspection.
In order to use this support, simply do the following::
from twisted.internet import gireactor
gireactor.install()
If you wish to use a GApplication, register it with the reactor::
from twisted.internet import reactor
reactor.registerGApplication(app)
Then use twisted.internet APIs as usual.
On Python 3, pygobject v3.4 or later is required.
"""
from __future__ import division, absolute_import
from twisted.python.compat import _PY3
from twisted.internet.error import ReactorAlreadyRunning
from twisted.internet import _glibbase
from twisted.python import runtime
if _PY3:
# We require a sufficiently new version of pygobject, so always exists:
_pygtkcompatPresent = True
else:
# We can't just try to import gi.pygtkcompat, because that would import
# gi, and the goal here is to not import gi in cases where that would
# cause segfault.
from twisted.python.modules import theSystemPath
_pygtkcompatPresent = True
try:
theSystemPath["gi.pygtkcompat"]
except KeyError:
_pygtkcompatPresent = False
# Modules that we want to ensure aren't imported if we're on older versions of
# GI:
_PYGTK_MODULES = ['gobject', 'glib', 'gio', 'gtk']
def _oldGiInit():
"""
Make sure pygtk and gi aren't loaded at the same time, and import Glib if
possible.
"""
# We can't immediately prevent imports, because that confuses some buggy
# code in gi:
_glibbase.ensureNotImported(
_PYGTK_MODULES,
"Introspected and static glib/gtk bindings must not be mixed; can't "
"import gireactor since pygtk2 module is already imported.")
global GLib
from gi.repository import GLib
if getattr(GLib, "threads_init", None) is not None:
GLib.threads_init()
_glibbase.ensureNotImported([], "",
preventImports=_PYGTK_MODULES)
if not _pygtkcompatPresent:
# Older versions of gi don't have compatability layer, so just enforce no
# imports of pygtk and gi at same time:
_oldGiInit()
else:
# Newer version of gi, so we can try to initialize compatibility layer; if
# real pygtk was already imported we'll get ImportError at this point
# rather than segfault, so unconditional import is fine.
import gi.pygtkcompat
gi.pygtkcompat.enable()
# At this point importing gobject will get you gi version, and importing
# e.g. gtk will either fail in non-segfaulty way or use gi version if user
# does gi.pygtkcompat.enable_gtk(). So, no need to prevent imports of
# old school pygtk modules.
from gi.repository import GLib
if getattr(GLib, "threads_init", None) is not None:
GLib.threads_init()
class GIReactor(_glibbase.GlibReactorBase):
"""
GObject-introspection event loop reactor.
@ivar _gapplication: A C{Gio.Application} instance that was registered
with C{registerGApplication}.
"""
_POLL_DISCONNECTED = (GLib.IOCondition.HUP | GLib.IOCondition.ERR |
GLib.IOCondition.NVAL)
_POLL_IN = GLib.IOCondition.IN
_POLL_OUT = GLib.IOCondition.OUT
# glib's iochannel sources won't tell us about any events that we haven't
# asked for, even if those events aren't sensible inputs to the poll()
# call.
INFLAGS = _POLL_IN | _POLL_DISCONNECTED
OUTFLAGS = _POLL_OUT | _POLL_DISCONNECTED
# By default no Application is registered:
_gapplication = None
def __init__(self, useGtk=False):
_gtk = None
if useGtk is True:
from gi.repository import Gtk as _gtk
_glibbase.GlibReactorBase.__init__(self, GLib, _gtk, useGtk=useGtk)
def registerGApplication(self, app):
"""
Register a C{Gio.Application} or C{Gtk.Application}, whose main loop
will be used instead of the default one.
We will C{hold} the application so it doesn't exit on its own. In
versions of C{python-gi} 3.2 and later, we exit the event loop using
the C{app.quit} method which overrides any holds. Older versions are
not supported.
"""
if self._gapplication is not None:
raise RuntimeError(
"Can't register more than one application instance.")
if self._started:
raise ReactorAlreadyRunning(
"Can't register application after reactor was started.")
if not hasattr(app, "quit"):
raise RuntimeError("Application registration is not supported in"
" versions of PyGObject prior to 3.2.")
self._gapplication = app
def run():
app.hold()
app.run(None)
self._run = run
self._crash = app.quit
class PortableGIReactor(_glibbase.PortableGlibReactorBase):
"""
Portable GObject Introspection event loop reactor.
"""
def __init__(self, useGtk=False):
_gtk = None
if useGtk is True:
from gi.repository import Gtk as _gtk
_glibbase.PortableGlibReactorBase.__init__(self, GLib, _gtk,
useGtk=useGtk)
def registerGApplication(self, app):
"""
Register a C{Gio.Application} or C{Gtk.Application}, whose main loop
will be used instead of the default one.
"""
raise NotImplementedError("GApplication is not currently supported on Windows.")
def install(useGtk=False):
"""
Configure the twisted mainloop to be run inside the glib mainloop.
@param useGtk: should GTK+ rather than glib event loop be
used (this will be slightly slower but does support GUI).
"""
if runtime.platform.getType() == 'posix':
reactor = GIReactor(useGtk=useGtk)
else:
reactor = PortableGIReactor(useGtk=useGtk)
from twisted.internet.main import installReactor
installReactor(reactor)
return reactor
__all__ = ['install']
|