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