gtk2reactor.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. # -*- test-case-name: twisted.internet.test -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. This module provides support for Twisted to interact with the glib/gtk2
  6. mainloop.
  7. In order to use this support, simply do the following::
  8. from twisted.internet import gtk2reactor
  9. gtk2reactor.install()
  10. Then use twisted.internet APIs as usual. The other methods here are not
  11. intended to be called directly.
  12. """
  13. from incremental import Version
  14. from ._deprecate import deprecatedGnomeReactor
  15. deprecatedGnomeReactor("gtk2reactor", Version("Twisted", 23, 8, 0))
  16. # System Imports
  17. import sys
  18. # Twisted Imports
  19. from twisted.internet import _glibbase
  20. from twisted.python import runtime
  21. # Certain old versions of pygtk and gi crash if imported at the same
  22. # time. This is a problem when running Twisted's unit tests, since they will
  23. # attempt to run both gtk2 and gtk3/gi tests. However, gireactor makes sure
  24. # that if we are in such an old version, and gireactor was imported,
  25. # gtk2reactor will not be importable. So we don't *need* to enforce that here
  26. # as well; whichever is imported first will still win. Moreover, additional
  27. # enforcement in this module is unnecessary in modern versions, and downright
  28. # problematic in certain versions where for some reason importing gtk also
  29. # imports some subset of gi. So we do nothing here, relying on gireactor to
  30. # prevent the crash.
  31. try:
  32. if not hasattr(sys, "frozen"):
  33. # Don't want to check this for py2exe
  34. import pygtk
  35. pygtk.require("2.0")
  36. except (ImportError, AttributeError):
  37. pass # maybe we're using pygtk before this hack existed.
  38. import gobject
  39. if not hasattr(gobject, "IO_HUP"):
  40. # gi.repository's legacy compatibility helper raises an AttributeError with
  41. # a custom error message rather than a useful ImportError, so things tend
  42. # to fail loudly. Things that import this module expect an ImportError if,
  43. # well, something failed to import, and treat an AttributeError as an
  44. # arbitrary application code failure, so we satisfy that expectation here.
  45. raise ImportError("pygobject 2.x is not installed. Use the `gi` reactor.")
  46. if hasattr(gobject, "threads_init"):
  47. # recent versions of python-gtk expose this. python-gtk=2.4.1
  48. # (wrapping glib-2.4.7) does. python-gtk=2.0.0 (wrapping
  49. # glib-2.2.3) does not.
  50. gobject.threads_init()
  51. class Gtk2Reactor(_glibbase.GlibReactorBase):
  52. """
  53. PyGTK+ 2 event loop reactor.
  54. """
  55. def __init__(self, useGtk=True):
  56. _gtk = None
  57. if useGtk is True:
  58. import gtk as _gtk
  59. _glibbase.GlibReactorBase.__init__(self, gobject, _gtk, useGtk=useGtk)
  60. # We don't bother deprecating the PortableGtkReactor.
  61. # The original code was removed and replaced with the
  62. # backward compatible generic GTK reactor.
  63. PortableGtkReactor = Gtk2Reactor
  64. def install(useGtk=True):
  65. """
  66. Configure the twisted mainloop to be run inside the gtk mainloop.
  67. @param useGtk: should glib rather than GTK+ event loop be
  68. used (this will be slightly faster but does not support GUI).
  69. """
  70. reactor = Gtk2Reactor(useGtk)
  71. from twisted.internet.main import installReactor
  72. installReactor(reactor)
  73. return reactor
  74. def portableInstall(useGtk=True):
  75. """
  76. Configure the twisted mainloop to be run inside the gtk mainloop.
  77. """
  78. reactor = PortableGtkReactor()
  79. from twisted.internet.main import installReactor
  80. installReactor(reactor)
  81. return reactor
  82. if runtime.platform.getType() == "posix":
  83. install = install
  84. else:
  85. install = portableInstall
  86. __all__ = ["install"]