Skip to content

Commit

Permalink
clean up pygobject support to remove dead APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
glyph committed Oct 6, 2022
1 parent c5b30bd commit 6ee1148
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 128 deletions.
38 changes: 9 additions & 29 deletions src/twisted/internet/_glibbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,28 +101,17 @@ def __init__(self, glib_module, gtk_module, useGtk=False):
self._writes = set()
self._sources = {}
self._glib = glib_module
self._gtk = gtk_module
posixbase.PosixReactorBase.__init__(self)

self._source_remove = self._glib.source_remove
self._timeout_add = self._glib.timeout_add

def _mainquit():
if self._gtk.main_level():
self._gtk.main_quit()

if useGtk:
self._pending = self._gtk.events_pending
self._iteration = self._gtk.main_iteration_do
self._crash = _mainquit
self._run = self._gtk.main
else:
self.context = self._glib.main_context_default()
self._pending = self.context.pending
self._iteration = self.context.iteration
self.loop = self._glib.MainLoop()
self._crash = lambda: self._glib.idle_add(self.loop.quit)
self._run = self.loop.run
self.context = self._glib.main_context_default()
self._pending = self.context.pending
self._iteration = self.context.iteration
self.loop = self._glib.MainLoop()
self._crash = lambda: self._glib.idle_add(self.loop.quit)
self._run = self.loop.run

def _handleSignals(self):
# First, install SIGINT and friends:
Expand Down Expand Up @@ -319,23 +308,14 @@ class PortableGlibReactorBase(selectreactor.SelectReactor):
def __init__(self, glib_module, gtk_module, useGtk=False):
self._simtag = None
self._glib = glib_module
self._gtk = gtk_module
selectreactor.SelectReactor.__init__(self)

self._source_remove = self._glib.source_remove
self._timeout_add = self._glib.timeout_add

def _mainquit():
if self._gtk.main_level():
self._gtk.main_quit()

if useGtk:
self._crash = _mainquit
self._run = self._gtk.main
else:
self.loop = self._glib.MainLoop()
self._crash = lambda: self._glib.idle_add(self.loop.quit)
self._run = self.loop.run
self.loop = self._glib.MainLoop()
self._crash = lambda: self._glib.idle_add(self.loop.quit)
self._run = self.loop.run

def crash(self):
selectreactor.SelectReactor.crash(self)
Expand Down
30 changes: 8 additions & 22 deletions src/twisted/internet/gireactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,14 @@
"""


import gi.pygtkcompat # type: ignore[import]
from gi.repository import GLib # type: ignore[import]
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

# We require a sufficiently new version of pygobject, so always exists:
_pygtkcompatPresent = True

# 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.
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.
if getattr(GLib, "threads_init", None) is not None:
GLib.threads_init()

Expand Down Expand Up @@ -71,7 +61,7 @@ def __init__(self, useGtk=False):
if useGtk is True:
from gi.repository import Gtk as _gtk

_glibbase.GlibReactorBase.__init__(self, GLib, _gtk, useGtk=useGtk)
_glibbase.GlibReactorBase.__init__(self, GLib, _gtk)

def registerGApplication(self, app):
"""
Expand Down Expand Up @@ -111,11 +101,7 @@ class PortableGIReactor(_glibbase.PortableGlibReactorBase):
"""

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)
_glibbase.PortableGlibReactorBase.__init__(self, GLib, None, useGtk=useGtk)

def registerGApplication(self, app):
"""
Expand All @@ -125,12 +111,12 @@ def registerGApplication(self, app):
raise NotImplementedError("GApplication is not currently supported on Windows.")


def install(useGtk=False):
def install(useGtk=False) -> Union[GIReactor, PortableGIReactor]:
"""
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).
@param useGtk: A hint that the Gtk GUI will or will not be used. Currently
does not modify any behavior.
"""
if runtime.platform.getType() == "posix":
reactor = GIReactor(useGtk=useGtk)
Expand Down
59 changes: 5 additions & 54 deletions src/twisted/internet/gtk3reactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,15 @@
# See LICENSE for details.

"""
This module provides support for Twisted to interact with the gtk3 mainloop
via Gobject introspection. This is like gi, but slightly slower and requires a
working $DISPLAY.

In order to use this support, simply do the following::

from twisted.internet import gtk3reactor
gtk3reactor.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.
This module is a legacy compatibility alias for L{twisted.internet.gireactor}.
See that module instead.
"""

from twisted.internet import gireactor
from twisted.python import runtime


class Gtk3Reactor(gireactor.GIReactor):
"""
A reactor using the gtk3+ event loop.
"""

def __init__(self):
"""
Override init to set the C{useGtk} flag.
"""
gireactor.GIReactor.__init__(self, useGtk=True)


class PortableGtk3Reactor(gireactor.PortableGIReactor):
"""
Portable GTK+ 3.x reactor.
"""

def __init__(self):
"""
Override init to set the C{useGtk} flag.
"""
gireactor.PortableGIReactor.__init__(self, useGtk=True)


def install():
"""
Configure the Twisted mainloop to be run inside the gtk3+ mainloop.
"""
if runtime.platform.getType() == "posix":
reactor = Gtk3Reactor()
else:
reactor = PortableGtk3Reactor()

from twisted.internet.main import installReactor

installReactor(reactor)
return reactor
Gtk3Reactor = gireactor.GIReactor
PortableGtk3Reactor = gireactor.PortableGIReactor

install = gireactor.install

__all__ = ["install"]
5 changes: 0 additions & 5 deletions src/twisted/internet/test/reactormixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,20 +141,15 @@ class ReactorBuilder:
# since no one really wants to use it on other platforms.
_reactors.extend(
[
"twisted.internet.gtk2reactor.PortableGtkReactor",
"twisted.internet.gireactor.PortableGIReactor",
"twisted.internet.gtk3reactor.PortableGtk3Reactor",
"twisted.internet.win32eventreactor.Win32Reactor",
"twisted.internet.iocpreactor.reactor.IOCPReactor",
]
)
else:
_reactors.extend(
[
"twisted.internet.glib2reactor.Glib2Reactor",
"twisted.internet.gtk2reactor.Gtk2Reactor",
"twisted.internet.gireactor.GIReactor",
"twisted.internet.gtk3reactor.Gtk3Reactor",
]
)

Expand Down
18 changes: 0 additions & 18 deletions src/twisted/internet/test/test_gireactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,21 +175,3 @@ def test_cantRegisterTwice(self):
self.assertEqual(
exc.args[0], "Can't register more than one application instance."
)


class PygtkCompatibilityTests(TestCase):
"""
pygtk imports are either prevented, or a compatibility layer is used if
possible.
"""

def test_compatibilityLayer(self):
"""
If compatibility layer is present, importing gobject uses
the gi compatibility layer.
"""
if "gi.pygtkcompat" not in sys.modules:
raise SkipTest("This version of gi doesn't include pygtkcompat.")
import gobject # type: ignore[import]

self.assertTrue(gobject.__name__.startswith("gi."))

0 comments on commit 6ee1148

Please sign in to comment.