##// 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 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """ Imports and provides the 'correct' version of readline for the platform.
2 """ Imports and provides the 'correct' version of readline for the platform.
3
3
4 Readline is used throughout IPython as::
4 Readline is used throughout IPython as::
5
5
6 import IPython.utils.rlineimpl as readline
6 import IPython.utils.rlineimpl as readline
7
7
8 In addition to normal readline stuff, this module provides have_readline
8 In addition to normal readline stuff, this module provides have_readline
9 boolean and _outputfile variable used in IPython.utils.
9 boolean and _outputfile variable used in IPython.utils.
10 """
10 """
11
11
12 import os
12 import os
13 import re
13 import re
14 import sys
14 import sys
15 import time
15 import time
16 import warnings
16 import warnings
17
17
18 from subprocess import Popen, PIPE
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 try:
32 try:
21 from readline import *
33 from readline import *
22 import readline as _rl
34 import readline as _rl
23 have_readline = True
35 have_readline = True
24 except ImportError:
36 except ImportError:
25 try:
37 try:
26 from pyreadline import *
38 from pyreadline import *
27 import pyreadline as _rl
39 import pyreadline as _rl
28 have_readline = True
40 have_readline = True
29 except ImportError:
41 except ImportError:
30 have_readline = False
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 if have_readline and hasattr(_rl, 'rlmain'):
64 if have_readline and hasattr(_rl, 'rlmain'):
33 # patch add_history to allow for strings in pyreadline <= 1.5:
65 # patch add_history to allow for strings in pyreadline <= 1.5:
34 # fix copied from pyreadline 1.6
66 # fix copied from pyreadline 1.6
35 import pyreadline
67 import pyreadline
36 if pyreadline.release.version <= '1.5':
68 if pyreadline.release.version <= '1.5':
37 def add_history(line):
69 def add_history(line):
38 """add a line to the history buffer."""
70 """add a line to the history buffer."""
39 from pyreadline import lineobj
71 from pyreadline import lineobj
40 if not isinstance(line, lineobj.TextLine):
72 if not isinstance(line, lineobj.TextLine):
41 line = lineobj.TextLine(line)
73 line = lineobj.TextLine(line)
42 return _rl.add_history(line)
74 return _rl.add_history(line)
43
75
44 if sys.platform == 'win32' and have_readline:
76 if sys.platform == 'win32' and have_readline:
45 try:
77 try:
46 _outputfile=_rl.GetOutputFile()
78 _outputfile=_rl.GetOutputFile()
47 except AttributeError:
79 except AttributeError:
48 warnings.warn("Failed GetOutputFile")
80 warnings.warn("Failed GetOutputFile")
49 have_readline = False
81 have_readline = False
50
82
51 # Test to see if libedit is being used instead of GNU readline.
83 # Test to see if libedit is being used instead of GNU readline.
52 # Thanks to Boyd Waters for the original patch.
84 # Thanks to Boyd Waters for the original patch.
53 uses_libedit = False
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:
87 if have_readline:
79 # EINTR
88 # Official Python docs state that 'libedit' is in the docstring for libedit readline:
80 time.sleep(dt)
89 uses_libedit = 'libedit' in _rl.__doc__
81 dt *= 2
90 # Note that many non-System Pythons also do not use proper readline,
82 continue
91 # but do not report libedit at all, nor are they linked dynamically against libedit.
83 elif p is None or p.returncode:
92 # known culprits of this include: EPD, Fink
84 warnings.warn("libedit detection failed: %s"%err)
93 # There is not much we can do to detect this, until we find a specific failure
85 break
94 # case, rather than relying on the readline module to self-identify as broken.
86 else:
87 break
88
95
89 if p is not None and p.returncode == 0 and re.search(br'/libedit[\.\d+]*\.dylib\s', out):
96 if uses_libedit and sys.platform == 'darwin':
90 # we are bound to libedit - new in Leopard
97 _rl.parse_and_bind("bind ^I rl_complete")
91 _rl.parse_and_bind("bind ^I rl_complete")
98 warnings.warn('\n'.join(['', "*"*78,
92 warnings.warn("Leopard libedit detected - readline will not be well behaved "
99 "libedit detected - readline will not be well behaved, including but not limited to:",
93 "including some crashes on tab completion, and incorrect history navigation. "
100 " * crashes on tab completion",
94 "It is highly recommended that you install readline, "
101 " * incorrect history navigation",
95 "which is easy_installable with: 'easy_install readline'",
102 " * corrupting long-lines",
96 RuntimeWarning)
103 " * failure to wrap or indent lines properly",
97 uses_libedit = True
104 "It is highly recommended that you install readline, which is easy_installable:",
98 # cleanup names
105 " easy_install readline",
99 del dt,p,out,err
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 # the clear_history() function was only introduced in Python 2.4 and is
113 # the clear_history() function was only introduced in Python 2.4 and is
102 # actually optional in the readline API, so we must explicitly check for its
114 # actually optional in the readline API, so we must explicitly check for its
103 # existence. Some known platforms actually don't have it. This thread:
115 # existence. Some known platforms actually don't have it. This thread:
104 # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
116 # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
105 # has the original discussion.
117 # has the original discussion.
106
118
107 if have_readline:
119 if have_readline:
108 try:
120 try:
109 _rl.clear_history
121 _rl.clear_history
110 except AttributeError:
122 except AttributeError:
111 def clear_history(): pass
123 def clear_history(): pass
112 _rl.clear_history = clear_history
124 _rl.clear_history = clear_history
General Comments 0
You need to be logged in to leave comments. Login now