aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/Twisted/py2/twisted/internet/wxreactor.py
diff options
context:
space:
mode:
authorshmel1k <shmel1k@ydb.tech>2023-11-26 18:16:14 +0300
committershmel1k <shmel1k@ydb.tech>2023-11-26 18:43:30 +0300
commitb8cf9e88f4c5c64d9406af533d8948deb050d695 (patch)
tree218eb61fb3c3b96ec08b4d8cdfef383104a87d63 /contrib/python/Twisted/py2/twisted/internet/wxreactor.py
parent523f645a83a0ec97a0332dbc3863bb354c92a328 (diff)
downloadydb-b8cf9e88f4c5c64d9406af533d8948deb050d695.tar.gz
add kikimr_configure
Diffstat (limited to 'contrib/python/Twisted/py2/twisted/internet/wxreactor.py')
-rw-r--r--contrib/python/Twisted/py2/twisted/internet/wxreactor.py188
1 files changed, 188 insertions, 0 deletions
diff --git a/contrib/python/Twisted/py2/twisted/internet/wxreactor.py b/contrib/python/Twisted/py2/twisted/internet/wxreactor.py
new file mode 100644
index 0000000000..ae24c599e1
--- /dev/null
+++ b/contrib/python/Twisted/py2/twisted/internet/wxreactor.py
@@ -0,0 +1,188 @@
+# Copyright (c) Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+This module provides wxPython event loop support for Twisted.
+
+In order to use this support, simply do the following::
+
+ | from twisted.internet import wxreactor
+ | wxreactor.install()
+
+Then, when your root wxApp has been created::
+
+ | from twisted.internet import reactor
+ | reactor.registerWxApp(yourApp)
+ | reactor.run()
+
+Then use twisted.internet APIs as usual. Stop the event loop using
+reactor.stop(), not yourApp.ExitMainLoop().
+
+IMPORTANT: tests will fail when run under this reactor. This is
+expected and probably does not reflect on the reactor's ability to run
+real applications.
+"""
+
+try:
+ from queue import Empty, Queue
+except ImportError:
+ from Queue import Empty, Queue
+
+try:
+ from wx import PySimpleApp as wxPySimpleApp, CallAfter as wxCallAfter, \
+ Timer as wxTimer
+except ImportError:
+ # older version of wxPython:
+ from wxPython.wx import wxPySimpleApp, wxCallAfter, wxTimer
+
+from twisted.python import log, runtime
+from twisted.internet import _threadedselect
+
+
+class ProcessEventsTimer(wxTimer):
+ """
+ Timer that tells wx to process pending events.
+
+ This is necessary on macOS, probably due to a bug in wx, if we want
+ wxCallAfters to be handled when modal dialogs, menus, etc. are open.
+ """
+ def __init__(self, wxapp):
+ wxTimer.__init__(self)
+ self.wxapp = wxapp
+
+
+ def Notify(self):
+ """
+ Called repeatedly by wx event loop.
+ """
+ self.wxapp.ProcessPendingEvents()
+
+
+
+class WxReactor(_threadedselect.ThreadedSelectReactor):
+ """
+ wxPython reactor.
+
+ wxPython drives the event loop, select() runs in a thread.
+ """
+
+ _stopping = False
+
+ def registerWxApp(self, wxapp):
+ """
+ Register wxApp instance with the reactor.
+ """
+ self.wxapp = wxapp
+
+
+ def _installSignalHandlersAgain(self):
+ """
+ wx sometimes removes our own signal handlers, so re-add them.
+ """
+ try:
+ # make _handleSignals happy:
+ import signal
+ signal.signal(signal.SIGINT, signal.default_int_handler)
+ except ImportError:
+ return
+ self._handleSignals()
+
+
+ def stop(self):
+ """
+ Stop the reactor.
+ """
+ if self._stopping:
+ return
+ self._stopping = True
+ _threadedselect.ThreadedSelectReactor.stop(self)
+
+
+ def _runInMainThread(self, f):
+ """
+ Schedule function to run in main wx/Twisted thread.
+
+ Called by the select() thread.
+ """
+ if hasattr(self, "wxapp"):
+ wxCallAfter(f)
+ else:
+ # wx shutdown but twisted hasn't
+ self._postQueue.put(f)
+
+
+ def _stopWx(self):
+ """
+ Stop the wx event loop if it hasn't already been stopped.
+
+ Called during Twisted event loop shutdown.
+ """
+ if hasattr(self, "wxapp"):
+ self.wxapp.ExitMainLoop()
+
+
+ def run(self, installSignalHandlers=True):
+ """
+ Start the reactor.
+ """
+ self._postQueue = Queue()
+ if not hasattr(self, "wxapp"):
+ log.msg("registerWxApp() was not called on reactor, "
+ "registering my own wxApp instance.")
+ self.registerWxApp(wxPySimpleApp())
+
+ # start select() thread:
+ self.interleave(self._runInMainThread,
+ installSignalHandlers=installSignalHandlers)
+ if installSignalHandlers:
+ self.callLater(0, self._installSignalHandlersAgain)
+
+ # add cleanup events:
+ self.addSystemEventTrigger("after", "shutdown", self._stopWx)
+ self.addSystemEventTrigger("after", "shutdown",
+ lambda: self._postQueue.put(None))
+
+ # On macOS, work around wx bug by starting timer to ensure
+ # wxCallAfter calls are always processed. We don't wake up as
+ # often as we could since that uses too much CPU.
+ if runtime.platform.isMacOSX():
+ t = ProcessEventsTimer(self.wxapp)
+ t.Start(2) # wake up every 2ms
+
+ self.wxapp.MainLoop()
+ wxapp = self.wxapp
+ del self.wxapp
+
+ if not self._stopping:
+ # wx event loop exited without reactor.stop() being
+ # called. At this point events from select() thread will
+ # be added to _postQueue, but some may still be waiting
+ # unprocessed in wx, thus the ProcessPendingEvents()
+ # below.
+ self.stop()
+ wxapp.ProcessPendingEvents() # deal with any queued wxCallAfters
+ while 1:
+ try:
+ f = self._postQueue.get(timeout=0.01)
+ except Empty:
+ continue
+ else:
+ if f is None:
+ break
+ try:
+ f()
+ except:
+ log.err()
+
+
+def install():
+ """
+ Configure the twisted mainloop to be run inside the wxPython mainloop.
+ """
+ reactor = WxReactor()
+ from twisted.internet.main import installReactor
+ installReactor(reactor)
+ return reactor
+
+
+__all__ = ['install']