##// END OF EJS Templates
fallback on lsof if otool not found in libedit detection...
MinRK -
Show More
@@ -1,95 +1,112 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 re
13 import re
13 import sys
14 import sys
14 import time
15 import time
15 import warnings
16 import warnings
16
17
17 from subprocess import Popen, PIPE
18 from subprocess import Popen, PIPE
18
19
19 try:
20 try:
20 from readline import *
21 from readline import *
21 import readline as _rl
22 import readline as _rl
22 have_readline = True
23 have_readline = True
23 except ImportError:
24 except ImportError:
24 try:
25 try:
25 from pyreadline import *
26 from pyreadline import *
26 import pyreadline as _rl
27 import pyreadline as _rl
27 have_readline = True
28 have_readline = True
28 except ImportError:
29 except ImportError:
29 have_readline = False
30 have_readline = False
30
31
31 if have_readline and hasattr(_rl, 'rlmain'):
32 if have_readline and hasattr(_rl, 'rlmain'):
32 # patch add_history to allow for strings in pyreadline <= 1.5:
33 # patch add_history to allow for strings in pyreadline <= 1.5:
33 # fix copied from pyreadline 1.6
34 # fix copied from pyreadline 1.6
34 import pyreadline
35 import pyreadline
35 if pyreadline.release.version <= '1.5':
36 if pyreadline.release.version <= '1.5':
36 def add_history(line):
37 def add_history(line):
37 """add a line to the history buffer."""
38 """add a line to the history buffer."""
38 from pyreadline import lineobj
39 from pyreadline import lineobj
39 if not isinstance(line, lineobj.TextLine):
40 if not isinstance(line, lineobj.TextLine):
40 line = lineobj.TextLine(line)
41 line = lineobj.TextLine(line)
41 return _rl.add_history(line)
42 return _rl.add_history(line)
42
43
43 if sys.platform == 'win32' and have_readline:
44 if sys.platform == 'win32' and have_readline:
44 try:
45 try:
45 _outputfile=_rl.GetOutputFile()
46 _outputfile=_rl.GetOutputFile()
46 except AttributeError:
47 except AttributeError:
47 print "Failed GetOutputFile"
48 print "Failed GetOutputFile"
48 have_readline = False
49 have_readline = False
49
50
50 # Test to see if libedit is being used instead of GNU readline.
51 # Test to see if libedit is being used instead of GNU readline.
51 # Thanks to Boyd Waters for the original patch.
52 # Thanks to Boyd Waters for the original patch.
52 uses_libedit = False
53 uses_libedit = False
53 if sys.platform == 'darwin' and have_readline:
54 if sys.platform == 'darwin' and have_readline:
54 # Previously this used commands.getstatusoutput, which uses os.popen.
55 # Previously this used commands.getstatusoutput, which uses os.popen.
55 # Switching to subprocess.Popen, and exponential falloff for EINTR
56 # Switching to subprocess.Popen, and exponential falloff for EINTR
56 # seems to make this better behaved in environments such as PyQt and gdb
57 # seems to make this better behaved in environments such as PyQt and gdb
57 dt = 1e-3
58 dt = 1e-3
58 while dt < 1:
59 while dt < 1:
59 p = Popen(['otool', '-L', _rl.__file__], stdout=PIPE, stderr=PIPE)
60 try:
60 otool,err = p.communicate()
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()
61
77
62 if p.returncode == 4:
78 if p.returncode == 4:
63 # EINTR
79 # EINTR
64 time.sleep(dt)
80 time.sleep(dt)
65 dt *= 2
81 dt *= 2
66 continue
82 continue
67 elif p.returncode:
83 elif p is None or p.returncode:
68 warnings.warn("libedit detection failed: %s"%err)
84 warnings.warn("libedit detection failed: %s"%err)
69 break
85 break
70 else:
86 else:
71 break
87 break
72
88
73 if p.returncode == 0 and re.search(r'/libedit[\.\d+]*\.dylib\s', otool):
89 if p is not None and p.returncode == 0 and re.search(r'/libedit[\.\d+]*\.dylib\s', out):
74 # we are bound to libedit - new in Leopard
90 # we are bound to libedit - new in Leopard
75 _rl.parse_and_bind("bind ^I rl_complete")
91 _rl.parse_and_bind("bind ^I rl_complete")
76 warnings.warn("Leopard libedit detected - readline will not be well behaved "
92 warnings.warn("Leopard libedit detected - readline will not be well behaved "
77 "including some crashes on tab completion, and incorrect history navigation. "
93 "including some crashes on tab completion, and incorrect history navigation. "
78 "It is highly recommended that you install readline, "
94 "It is highly recommended that you install readline, "
79 "which is easy_installable with: 'easy_install readline'",
95 "which is easy_installable with: 'easy_install readline'",
80 RuntimeWarning)
96 RuntimeWarning)
81 uses_libedit = True
97 uses_libedit = True
82
98 # cleanup names
99 del dt,p,out,err
83
100
84 # the clear_history() function was only introduced in Python 2.4 and is
101 # the clear_history() function was only introduced in Python 2.4 and is
85 # actually optional in the readline API, so we must explicitly check for its
102 # actually optional in the readline API, so we must explicitly check for its
86 # existence. Some known platforms actually don't have it. This thread:
103 # existence. Some known platforms actually don't have it. This thread:
87 # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
104 # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
88 # has the original discussion.
105 # has the original discussion.
89
106
90 if have_readline:
107 if have_readline:
91 try:
108 try:
92 _rl.clear_history
109 _rl.clear_history
93 except AttributeError:
110 except AttributeError:
94 def clear_history(): pass
111 def clear_history(): pass
95 _rl.clear_history = clear_history
112 _rl.clear_history = clear_history
General Comments 0
You need to be logged in to leave comments. Login now