##// END OF EJS Templates
add dirty trick for readline import on OSX...
MinRK -
Show More
@@ -1,112 +1,122 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 = -1
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 != -1:
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:
86 if have_readline:
55 # Previously this used commands.getstatusoutput, which uses os.popen.
87 # Official Python docs state that 'libedit' is in the docstring for libedit readline:
56 # Switching to subprocess.Popen, and exponential falloff for EINTR
88 uses_libedit = 'libedit' in _rl.__doc__
57 # seems to make this better behaved in environments such as PyQt and gdb
89 # Note that many non-System Pythons also do not use proper readline,
58 dt = 1e-3
90 # but do not report libedit at all, nor are they linked dynamically against libedit.
59 while dt < 1:
91 # known culprits of this include: EPD, Fink
60 try:
92 # There is not much we can do to detect this, until we find a specific failure
61 p = Popen(['otool', '-L', _rl.__file__], stdout=PIPE, stderr=PIPE)
93 # case, rather than relying on the readline module to self-identify as broken.
62 except OSError:
94 if uses_libedit and sys.platform == 'darwin':
63 try:
95 _rl.parse_and_bind("bind ^I rl_complete")
64 # otool not available (no XCode), use lsof instead.
96 warnings.warn('\n'.join(['', "*"*78,
65 # This *could* have a false positive
97 "libedit detected - readline will not be well behaved, including but not limited to:",
66 # if another package that uses libedit explicitly
98 " * crashes on tab completion",
67 # has been imported prior to this test.
99 " * incorrect history navigation",
68 p = Popen(['lsof', '-p', str(os.getpid())], stdout=PIPE, stderr=PIPE)
100 " * corrupting long-lines",
69 except OSError:
101 " * failure to wrap or indent lines properly",
70 # This is highly unlikely, but let's be sure
102 "It is highly recommended that you install readline, which is easy_installable:",
71 # we don't crash IPython just because we can't find lsof
103 " easy_install readline",
72 p = out = err = None
104 "Note that `pip install readline` generally DOES NOT WORK, because",
73 warnings.warn("libedit detection failed")
105 "it installs to site-packages, which come *after* lib-dynload in sys.path,",
74 break
106 "where readline is located. It must be `easy_install readline`, or to a custom",
75
107 "location on your PYTHONPATH (even --user comes after lib-dyload).",
76 out,err = p.communicate()
108 "*"*78]),
77
109 RuntimeWarning)
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
88
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
100
110
101 # the clear_history() function was only introduced in Python 2.4 and is
111 # 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
112 # 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:
113 # existence. Some known platforms actually don't have it. This thread:
104 # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
114 # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
105 # has the original discussion.
115 # has the original discussion.
106
116
107 if have_readline:
117 if have_readline:
108 try:
118 try:
109 _rl.clear_history
119 _rl.clear_history
110 except AttributeError:
120 except AttributeError:
111 def clear_history(): pass
121 def clear_history(): pass
112 _rl.clear_history = clear_history
122 _rl.clear_history = clear_history
General Comments 0
You need to be logged in to leave comments. Login now