diff options
author | shmel1k <shmel1k@ydb.tech> | 2023-11-26 18:16:14 +0300 |
---|---|---|
committer | shmel1k <shmel1k@ydb.tech> | 2023-11-26 18:43:30 +0300 |
commit | b8cf9e88f4c5c64d9406af533d8948deb050d695 (patch) | |
tree | 218eb61fb3c3b96ec08b4d8cdfef383104a87d63 /contrib/python/Twisted/py2/twisted/internet/wxreactor.py | |
parent | 523f645a83a0ec97a0332dbc3863bb354c92a328 (diff) | |
download | ydb-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.py | 188 |
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'] |