123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- # 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 typing import Union
- from gi.repository import GLib
- from twisted.internet import _glibbase
- from twisted.internet.error import ReactorAlreadyRunning
- from twisted.python import runtime
- 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}.
- """
- # By default no Application is registered:
- _gapplication = None
- def __init__(self, useGtk=False):
- _glibbase.GlibReactorBase.__init__(self, GLib, None)
- 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.GlibReactorBase):
- """
- Portable GObject Introspection event loop reactor.
- """
- def __init__(self, useGtk=False):
- super().__init__(GLib, None, 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 simulate(self) -> None:
- """
- For compatibility only. Do nothing.
- """
- def install(useGtk: bool = False) -> Union[GIReactor, PortableGIReactor]:
- """
- Configure the twisted mainloop to be run inside the glib mainloop.
- @param useGtk: A hint that the Gtk GUI will or will not be used. Currently
- does not modify any behavior.
- """
- reactor: Union[GIReactor, PortableGIReactor]
- 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"]
|