##// END OF EJS Templates
Merge pull request #937 from minrk/readline...
Fernando Perez -
r5211:90b01394 merge
parent child Browse files
Show More
@@ -1,112 +1,124 b''
1 1 # -*- coding: utf-8 -*-
2 2 """ Imports and provides the 'correct' version of readline for the platform.
3 3
4 4 Readline is used throughout IPython as::
5 5
6 6 import IPython.utils.rlineimpl as readline
7 7
8 8 In addition to normal readline stuff, this module provides have_readline
9 9 boolean and _outputfile variable used in IPython.utils.
10 10 """
11 11
12 12 import os
13 13 import re
14 14 import sys
15 15 import time
16 16 import warnings
17 17
18 18 from subprocess import Popen, PIPE
19 19
20 if sys.platform == 'darwin':
21 # dirty trick, to skip the system readline, because pip-installed readline
22 # will never be found on OSX, since lib-dynload always comes ahead of site-packages
23 from distutils import sysconfig
24 lib_dynload = sysconfig.get_config_var('DESTSHARED')
25 del sysconfig
26 try:
27 dynload_idx = sys.path.index(lib_dynload)
28 except ValueError:
29 dynload_idx = None
30 else:
31 sys.path.pop(dynload_idx)
20 32 try:
21 33 from readline import *
22 34 import readline as _rl
23 35 have_readline = True
24 36 except ImportError:
25 37 try:
26 38 from pyreadline import *
27 39 import pyreadline as _rl
28 40 have_readline = True
29 41 except ImportError:
30 42 have_readline = False
31 43
44 if sys.platform == 'darwin':
45 # dirty trick, part II:
46 if dynload_idx is not None:
47 # restore path
48 sys.path.insert(dynload_idx, lib_dynload)
49 if not have_readline:
50 # *only* have system readline, try import again
51 try:
52 from readline import *
53 import readline as _rl
54 have_readline = True
55 except ImportError:
56 have_readline = False
57 else:
58 # if we want to warn about EPD / Fink having bad readline
59 # we would do it here
60 pass
61 # cleanup dirty trick vars
62 del dynload_idx, lib_dynload
63
32 64 if have_readline and hasattr(_rl, 'rlmain'):
33 65 # patch add_history to allow for strings in pyreadline <= 1.5:
34 66 # fix copied from pyreadline 1.6
35 67 import pyreadline
36 68 if pyreadline.release.version <= '1.5':
37 69 def add_history(line):
38 70 """add a line to the history buffer."""
39 71 from pyreadline import lineobj
40 72 if not isinstance(line, lineobj.TextLine):
41 73 line = lineobj.TextLine(line)
42 74 return _rl.add_history(line)
43 75
44 76 if sys.platform == 'win32' and have_readline:
45 77 try:
46 78 _outputfile=_rl.GetOutputFile()
47 79 except AttributeError:
48 80 warnings.warn("Failed GetOutputFile")
49 81 have_readline = False
50 82
51 83 # Test to see if libedit is being used instead of GNU readline.
52 84 # Thanks to Boyd Waters for the original patch.
53 85 uses_libedit = False
54 if sys.platform == 'darwin' and have_readline:
55 # Previously this used commands.getstatusoutput, which uses os.popen.
56 # Switching to subprocess.Popen, and exponential falloff for EINTR
57 # seems to make this better behaved in environments such as PyQt and gdb
58 dt = 1e-3
59 while dt < 1:
60 try:
61 p = Popen(['otool', '-L', _rl.__file__], stdout=PIPE, stderr=PIPE)
62 except OSError:
63 try:
64 # otool not available (no XCode), use lsof instead.
65 # This *could* have a false positive
66 # if another package that uses libedit explicitly
67 # has been imported prior to this test.
68 p = Popen(['lsof', '-p', str(os.getpid())], stdout=PIPE, stderr=PIPE)
69 except OSError:
70 # This is highly unlikely, but let's be sure
71 # we don't crash IPython just because we can't find lsof
72 p = out = err = None
73 warnings.warn("libedit detection failed")
74 break
75
76 out,err = p.communicate()
77 86
78 if p.returncode == 4:
79 # EINTR
80 time.sleep(dt)
81 dt *= 2
82 continue
83 elif p is None or p.returncode:
84 warnings.warn("libedit detection failed: %s"%err)
85 break
86 else:
87 break
87 if have_readline:
88 # Official Python docs state that 'libedit' is in the docstring for libedit readline:
89 uses_libedit = 'libedit' in _rl.__doc__
90 # Note that many non-System Pythons also do not use proper readline,
91 # but do not report libedit at all, nor are they linked dynamically against libedit.
92 # known culprits of this include: EPD, Fink
93 # There is not much we can do to detect this, until we find a specific failure
94 # case, rather than relying on the readline module to self-identify as broken.
88 95
89 if p is not None and p.returncode == 0 and re.search(br'/libedit[\.\d+]*\.dylib\s', out):
90 # we are bound to libedit - new in Leopard
91 _rl.parse_and_bind("bind ^I rl_complete")
92 warnings.warn("Leopard libedit detected - readline will not be well behaved "
93 "including some crashes on tab completion, and incorrect history navigation. "
94 "It is highly recommended that you install readline, "
95 "which is easy_installable with: 'easy_install readline'",
96 RuntimeWarning)
97 uses_libedit = True
98 # cleanup names
99 del dt,p,out,err
96 if uses_libedit and sys.platform == 'darwin':
97 _rl.parse_and_bind("bind ^I rl_complete")
98 warnings.warn('\n'.join(['', "*"*78,
99 "libedit detected - readline will not be well behaved, including but not limited to:",
100 " * crashes on tab completion",
101 " * incorrect history navigation",
102 " * corrupting long-lines",
103 " * failure to wrap or indent lines properly",
104 "It is highly recommended that you install readline, which is easy_installable:",
105 " easy_install readline",
106 "Note that `pip install readline` generally DOES NOT WORK, because",
107 "it installs to site-packages, which come *after* lib-dynload in sys.path,",
108 "where readline is located. It must be `easy_install readline`, or to a custom",
109 "location on your PYTHONPATH (even --user comes after lib-dyload).",
110 "*"*78]),
111 RuntimeWarning)
100 112
101 113 # the clear_history() function was only introduced in Python 2.4 and is
102 114 # actually optional in the readline API, so we must explicitly check for its
103 115 # existence. Some known platforms actually don't have it. This thread:
104 116 # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
105 117 # has the original discussion.
106 118
107 119 if have_readline:
108 120 try:
109 121 _rl.clear_history
110 122 except AttributeError:
111 123 def clear_history(): pass
112 124 _rl.clear_history = clear_history
General Comments 0
You need to be logged in to leave comments. Login now