##// END OF EJS Templates
inputhook: disable CTRL+C when a hook is active....
inputhook: disable CTRL+C when a hook is active. On systems with 'readline', it's very likely to intercept a signal during a select() call. The default SIGINT handler will schedule a KeyboardInterrupt exception to be raised as soon as possible. If ctypes is used to install a Python callback for PyOS_InputHook, this will happen as soon as the bytecode execution starts, so even if the first instruction of the callback is a `try: ... except KeyboardInterrupt` clause, it's actually too late. As ctypes doesn't allow a Python callback to raise an exception, this ends up with IPython detecting an internal error... not pretty. We must therefore ignore the SIGINT signals until we are sure the exception handler is active, in the Python callback.

File last commit:

r3938:ec698f9f
r4944:0fc80df3
Show More
rlineimpl.py
112 lines | 3.8 KiB | text/x-python | PythonLexer
# -*- coding: utf-8 -*-
""" Imports and provides the 'correct' version of readline for the platform.
Readline is used throughout IPython as::
import IPython.utils.rlineimpl as readline
In addition to normal readline stuff, this module provides have_readline
boolean and _outputfile variable used in IPython.utils.
"""
import os
import re
import sys
import time
import warnings
from subprocess import Popen, PIPE
try:
from readline import *
import readline as _rl
have_readline = True
except ImportError:
try:
from pyreadline import *
import pyreadline as _rl
have_readline = True
except ImportError:
have_readline = False
if have_readline and hasattr(_rl, 'rlmain'):
# patch add_history to allow for strings in pyreadline <= 1.5:
# fix copied from pyreadline 1.6
import pyreadline
if pyreadline.release.version <= '1.5':
def add_history(line):
"""add a line to the history buffer."""
from pyreadline import lineobj
if not isinstance(line, lineobj.TextLine):
line = lineobj.TextLine(line)
return _rl.add_history(line)
if sys.platform == 'win32' and have_readline:
try:
_outputfile=_rl.GetOutputFile()
except AttributeError:
warnings.warn("Failed GetOutputFile")
have_readline = False
# Test to see if libedit is being used instead of GNU readline.
# Thanks to Boyd Waters for the original patch.
uses_libedit = False
if sys.platform == 'darwin' and have_readline:
# Previously this used commands.getstatusoutput, which uses os.popen.
# Switching to subprocess.Popen, and exponential falloff for EINTR
# seems to make this better behaved in environments such as PyQt and gdb
dt = 1e-3
while dt < 1:
try:
p = Popen(['otool', '-L', _rl.__file__], stdout=PIPE, stderr=PIPE)
except OSError:
try:
# otool not available (no XCode), use lsof instead.
# This *could* have a false positive
# if another package that uses libedit explicitly
# has been imported prior to this test.
p = Popen(['lsof', '-p', str(os.getpid())], stdout=PIPE, stderr=PIPE)
except OSError:
# This is highly unlikely, but let's be sure
# we don't crash IPython just because we can't find lsof
p = out = err = None
warnings.warn("libedit detection failed")
break
out,err = p.communicate()
if p.returncode == 4:
# EINTR
time.sleep(dt)
dt *= 2
continue
elif p is None or p.returncode:
warnings.warn("libedit detection failed: %s"%err)
break
else:
break
if p is not None and p.returncode == 0 and re.search(br'/libedit[\.\d+]*\.dylib\s', out):
# we are bound to libedit - new in Leopard
_rl.parse_and_bind("bind ^I rl_complete")
warnings.warn("Leopard libedit detected - readline will not be well behaved "
"including some crashes on tab completion, and incorrect history navigation. "
"It is highly recommended that you install readline, "
"which is easy_installable with: 'easy_install readline'",
RuntimeWarning)
uses_libedit = True
# cleanup names
del dt,p,out,err
# the clear_history() function was only introduced in Python 2.4 and is
# actually optional in the readline API, so we must explicitly check for its
# existence. Some known platforms actually don't have it. This thread:
# http://mail.python.org/pipermail/python-dev/2003-August/037845.html
# has the original discussion.
if have_readline:
try:
_rl.clear_history
except AttributeError:
def clear_history(): pass
_rl.clear_history = clear_history