You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			91 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			91 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
import sys
 | 
						|
import os
 | 
						|
from IPython.external.qt_for_kernel import QtCore, QtGui, enum_helper
 | 
						|
from IPython import get_ipython
 | 
						|
 | 
						|
# If we create a QApplication, QEventLoop, or a QTimer, keep a reference to them
 | 
						|
# so that they don't get garbage collected or leak memory when created multiple times.
 | 
						|
_appref = None
 | 
						|
_eventloop = None
 | 
						|
_timer = None
 | 
						|
_already_warned = False
 | 
						|
 | 
						|
 | 
						|
def _exec(obj):
 | 
						|
    # exec on PyQt6, exec_ elsewhere.
 | 
						|
    obj.exec() if hasattr(obj, "exec") else obj.exec_()
 | 
						|
 | 
						|
 | 
						|
def _reclaim_excepthook():
 | 
						|
    shell = get_ipython()
 | 
						|
    if shell is not None:
 | 
						|
        sys.excepthook = shell.excepthook
 | 
						|
 | 
						|
 | 
						|
def inputhook(context):
 | 
						|
    global _appref, _eventloop, _timer
 | 
						|
    app = QtCore.QCoreApplication.instance()
 | 
						|
    if not app:
 | 
						|
        if sys.platform == 'linux':
 | 
						|
            if not os.environ.get('DISPLAY') \
 | 
						|
                    and not os.environ.get('WAYLAND_DISPLAY'):
 | 
						|
                import warnings
 | 
						|
                global _already_warned
 | 
						|
                if not _already_warned:
 | 
						|
                    _already_warned = True
 | 
						|
                    warnings.warn(
 | 
						|
                        'The DISPLAY or WAYLAND_DISPLAY environment variable is '
 | 
						|
                        'not set or empty and Qt5 requires this environment '
 | 
						|
                        'variable. Deactivate Qt5 code.'
 | 
						|
                    )
 | 
						|
                return
 | 
						|
        try:
 | 
						|
            QtCore.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
 | 
						|
        except AttributeError:  # Only for Qt>=5.6, <6.
 | 
						|
            pass
 | 
						|
        try:
 | 
						|
            QtCore.QApplication.setHighDpiScaleFactorRoundingPolicy(
 | 
						|
                QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
 | 
						|
            )
 | 
						|
        except AttributeError:  # Only for Qt>=5.14.
 | 
						|
            pass
 | 
						|
        _appref = app = QtGui.QApplication([" "])
 | 
						|
 | 
						|
        # "reclaim" IPython sys.excepthook after event loop starts
 | 
						|
        # without this, it defaults back to BaseIPythonApplication.excepthook
 | 
						|
        # and exceptions in the Qt event loop are rendered without traceback
 | 
						|
        # formatting and look like "bug in IPython".
 | 
						|
        QtCore.QTimer.singleShot(0, _reclaim_excepthook)
 | 
						|
 | 
						|
    if _eventloop is None:
 | 
						|
        _eventloop = QtCore.QEventLoop(app)
 | 
						|
 | 
						|
    if sys.platform == 'win32':
 | 
						|
        # The QSocketNotifier method doesn't appear to work on Windows.
 | 
						|
        # Use polling instead.
 | 
						|
        if _timer is None:
 | 
						|
            _timer = QtCore.QTimer()
 | 
						|
            _timer.timeout.connect(_eventloop.quit)
 | 
						|
        while not context.input_is_ready():
 | 
						|
            # NOTE: run the event loop, and after 10 ms, call `quit` to exit it.
 | 
						|
            _timer.start(10)  # 10 ms
 | 
						|
            _exec(_eventloop)
 | 
						|
            _timer.stop()
 | 
						|
    else:
 | 
						|
        # On POSIX platforms, we can use a file descriptor to quit the event
 | 
						|
        # loop when there is input ready to read.
 | 
						|
        notifier = QtCore.QSocketNotifier(
 | 
						|
            context.fileno(), enum_helper("QtCore.QSocketNotifier.Type").Read
 | 
						|
        )
 | 
						|
        try:
 | 
						|
            # connect the callback we care about before we turn it on
 | 
						|
            # lambda is necessary as PyQT inspect the function signature to know
 | 
						|
            # what arguments to pass to. See https://github.com/ipython/ipython/pull/12355
 | 
						|
            notifier.activated.connect(lambda: _eventloop.exit())
 | 
						|
            notifier.setEnabled(True)
 | 
						|
            # only start the event loop we are not already flipped
 | 
						|
            if not context.input_is_ready():
 | 
						|
                _exec(_eventloop)
 | 
						|
        finally:
 | 
						|
            notifier.setEnabled(False)
 |