##// END OF EJS Templates
capture rich output as well as stdout/err in capture_output...
capture rich output as well as stdout/err in capture_output closes #3742

File last commit:

r11126:b337c5c3
r12223:e10d2ee4
Show More
inputhookqt4.py
180 lines | 6.6 KiB | text/x-python | PythonLexer
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 # -*- coding: utf-8 -*-
"""
Qt4's inputhook support function
Author: Christian Boos
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2011 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
Siyu Zhang
Changed sleep in signal thread to .01 sec. Moved imports to top.
r10352 import os
import signal
import threading
Christian Boos
inputhookqt4: use InteractiveShell.instance instead of get_ipython...
r5132 from IPython.core.interactiveshell import InteractiveShell
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 from IPython.external.qt_for_kernel import QtCore, QtGui
Christian Boos
inputhook: disable CTRL+C when a hook is active....
r4944 from IPython.lib.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931
#-----------------------------------------------------------------------------
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 # Module Globals
#-----------------------------------------------------------------------------
got_kbdint = False
sigint_timer = None
#-----------------------------------------------------------------------------
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 # Code
#-----------------------------------------------------------------------------
def create_inputhook_qt4(mgr, app=None):
"""Create an input hook for running the Qt4 application event loop.
Parameters
----------
mgr : an InputHookManager
app : Qt Application, optional.
Running application to use. If not given, we probe Qt for an
existing application object, and create a new one if none is found.
Returns
-------
A pair consisting of a Qt Application (either the one given or the
one found or created) and a inputhook.
Notes
-----
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936 We use a custom input hook instead of PyQt4's default one, as it
interacts better with the readline packages (issue #481).
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 The inputhook function works in tandem with a 'pre_prompt_hook'
which automatically restores the hook as an inputhook in case the
latter has been temporarily disabled after having intercepted a
KeyboardInterrupt.
"""
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 if app is None:
app = QtCore.QCoreApplication.instance()
if app is None:
app = QtGui.QApplication([" "])
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936 # Re-use previously created inputhook if any
Christian Boos
inputhookqt4: use InteractiveShell.instance instead of get_ipython...
r5132 ip = InteractiveShell.instance()
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936 if hasattr(ip, '_inputhook_qt4'):
return app, ip._inputhook_qt4
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936 # Otherwise create the inputhook_qt4/preprompthook_qt4 pair of
# hooks (they both share the got_kbdint flag)
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931
def inputhook_qt4():
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936 """PyOS_InputHook python hook for Qt4.
Process pending Qt events and if there's no pending keyboard
input, spend a short slice of time (50ms) running the Qt event
loop.
As a Python ctypes callback can't raise an exception, we catch
the KeyboardInterrupt and temporarily deactivate the hook,
which will let a *second* CTRL+C be processed normally and go
back to a clean prompt line.
"""
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 try:
Christian Boos
inputhook: disable CTRL+C when a hook is active....
r4944 allow_CTRL_C()
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936 app = QtCore.QCoreApplication.instance()
Christian Boos
inputhookqt4: make hook more robust in case of unexpected conditions...
r5180 if not app: # shouldn't happen, but safer if it happens anyway...
return 0
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 app.processEvents(QtCore.QEventLoop.AllEvents, 300)
if not stdin_ready():
Bradley M. Froehle
inputhook_qt4: Use QEventLoop instead of starting up the QCoreApplication....
r8402 # Generally a program would run QCoreApplication::exec()
# from main() to enter and process the Qt event loop until
# quit() or exit() is called and the program terminates.
#
# For our input hook integration, we need to repeatedly
# enter and process the Qt event loop for only a short
# amount of time (say 50ms) to ensure that Python stays
# responsive to other user inputs.
#
# A naive approach would be to repeatedly call
# QCoreApplication::exec(), using a timer to quit after a
# short amount of time. Unfortunately, QCoreApplication
# emits an aboutToQuit signal before stopping, which has
# the undesirable effect of closing all modal windows.
#
# To work around this problem, we instead create a
# QEventLoop and call QEventLoop::exec(). Other than
# setting some state variables which do not seem to be
# used anywhere, the only thing QCoreApplication adds is
# the aboutToQuit signal which is precisely what we are
# trying to avoid.
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 timer = QtCore.QTimer()
Bradley M. Froehle
inputhook_qt4: Use QEventLoop instead of starting up the QCoreApplication....
r8402 event_loop = QtCore.QEventLoop()
timer.timeout.connect(event_loop.quit)
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 while not stdin_ready():
timer.start(50)
Bradley M. Froehle
inputhook_qt4: Use QEventLoop instead of starting up the QCoreApplication....
r8402 event_loop.exec_()
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 timer.stop()
except KeyboardInterrupt:
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 global got_kbdint, sigint_timer
Christian Boos
inputhook: disable CTRL+C when a hook is active....
r4944 ignore_CTRL_C()
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 got_kbdint = True
Christian Boos
inputhook: disable CTRL+C when a hook is active....
r4944 mgr.clear_inputhook()
Siyu Zhang
Added comments explaining the SIGINT timer
r10387
# This generates a second SIGINT so the user doesn't have to
# press CTRL+C twice to get a clean prompt.
#
# Since we can't catch the resulting KeyboardInterrupt here
# (because this is a ctypes callback), we use a timer to
# generate the SIGINT after we leave this callback.
#
# Unfortunately this doesn't work on Windows (SIGINT kills
# Python and CTRL_C_EVENT doesn't work).
Siyu Zhang
Workaround so only one CTRL-C is required for a new prompt in --gui=qt...
r10350 if(os.name == 'posix'):
pid = os.getpid()
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 if(not sigint_timer):
sigint_timer = threading.Timer(.01, os.kill,
Siyu Zhang
Added comments explaining the SIGINT timer
r10387 args=[pid, signal.SIGINT] )
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 sigint_timer.start()
Siyu Zhang
Workaround so only one CTRL-C is required for a new prompt in --gui=qt...
r10350 else:
print("\nKeyboardInterrupt - Ctrl-C again for new prompt")
Christian Boos
inputhookqt4: make hook more robust in case of unexpected conditions...
r5180 except: # NO exceptions are allowed to escape from a ctypes callback
MinRK
Don't ignore ctrl-C during normal execution in inputhook_qt4
r5741 ignore_CTRL_C()
Christian Boos
inputhookqt4: make hook more robust in case of unexpected conditions...
r5180 from traceback import print_exc
print_exc()
print("Got exception from inputhook_qt4, unregistering.")
Fernando Perez
Clear inputhook after printing exception information....
r5761 mgr.clear_inputhook()
MinRK
Don't ignore ctrl-C during normal execution in inputhook_qt4
r5741 finally:
allow_CTRL_C()
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 return 0
def preprompthook_qt4(ishell):
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936 """'pre_prompt_hook' used to restore the Qt4 input hook
(in case the latter was temporarily deactivated after a
CTRL+C)
"""
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 global got_kbdint, sigint_timer
if(sigint_timer):
sigint_timer.cancel()
sigint_timer = None
Siyu Zhang
keep track of the sigint timer, and cancel it on a new prompt
r10383
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 if got_kbdint:
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931 mgr.set_inputhook(inputhook_qt4)
Siyu Zhang
Made sigint_timer and got_kbdint module globals
r10405 got_kbdint = False
Christian Boos
inputhookqt4: polish the qt4 related hooks...
r4936
ip._inputhook_qt4 = inputhook_qt4
ip.set_hook('pre_prompt_hook', preprompthook_qt4)
Christian Boos
inputhook: move inputhook_qt4 related code in own file
r4931
return app, inputhook_qt4