aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/Twisted-12.2.0-py2.7-linux-x86_64.egg/twisted/internet/gireactor.py
blob: bf71bb5093a4bf65f6ee0e8f5598e5f2c667ce3c (plain)
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
# 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.
"""

import sys
from twisted.internet.error import ReactorAlreadyRunning
from twisted.internet import _glibbase
from twisted.python import runtime

# We can't immediately prevent imports, because that confuses some buggy code
# in gi:
_glibbase.ensureNotImported(
    ['gobject' 'glib', 'gio', 'gtk'],
    "Introspected and static glib/gtk bindings must not be mixed; can't "
    "import gireactor since pygtk2 module is already imported.")

from gi.repository import GLib
GLib.threads_init()

_glibbase.ensureNotImported([], "",
                            preventImports=['gobject' 'glib', 'gio', 'gtk'])



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']