##// END OF EJS Templates
Modified OutputTrap to accept a file-like object and use it instead of...
Gael Varoquaux -
Show More
@@ -1,157 +1,158 b''
1 """
1 """
2 Frontend class that uses IPython0 to prefilter the inputs.
2 Frontend class that uses IPython0 to prefilter the inputs.
3
3
4 Using the IPython0 mechanism gives us access to the magics.
4 Using the IPython0 mechanism gives us access to the magics.
5 """
5 """
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 #-------------------------------------------------------------------------------
15 #-------------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18 import sys
18 import sys
19
19
20 from linefrontendbase import LineFrontEndBase, common_prefix
20 from linefrontendbase import LineFrontEndBase, common_prefix
21
21
22 from IPython.ipmaker import make_IPython
22 from IPython.ipmaker import make_IPython
23 from IPython.ipapi import IPApi
23 from IPython.ipapi import IPApi
24 from IPython.kernel.core.sync_output_trap import SyncOutputTrap
24 from IPython.kernel.core.file_like import FileLike
25 from IPython.kernel.core.output_trap import OutputTrap
25
26
26 from IPython.genutils import Term
27 from IPython.genutils import Term
27 import pydoc
28 import pydoc
28
29
29 #-------------------------------------------------------------------------------
30 #-------------------------------------------------------------------------------
30 # Utility functions (temporary, should be moved out of here)
31 # Utility functions (temporary, should be moved out of here)
31 #-------------------------------------------------------------------------------
32 #-------------------------------------------------------------------------------
32 import os
33 import os
33 def xterm_system(command):
34 def xterm_system(command):
34 """ Run a command in a separate console window.
35 """ Run a command in a separate console window.
35 """
36 """
36 os.system("""
37 os.system(("""xterm -title "%s" -e \'/bin/sh -c "%s ; """
37 xterm -title "%s" -e \'/bin/sh -c "%s ;
38 """echo; echo press enter to close ; """
38 printf \\"\\\\n\\";
39 # """echo \\"\x1b]0;%s (finished -- press enter to close)\x07\\" ;
39 printf \\"press a key to close\\" ;
40 """read foo;"\' """) % (command, command) )
40 printf \\"\x1b]0;%s (finished -- press a key to close)\x07\\" ;
41 read foo;"\'
42 """ % (command, command, command) )
43
41
44 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
45 # Frontend class using ipython0 to do the prefiltering.
43 # Frontend class using ipython0 to do the prefiltering.
46 #-------------------------------------------------------------------------------
44 #-------------------------------------------------------------------------------
47 class PrefilterFrontEnd(LineFrontEndBase):
45 class PrefilterFrontEnd(LineFrontEndBase):
48
46
49 def __init__(self, *args, **kwargs):
47 def __init__(self, *args, **kwargs):
50 LineFrontEndBase.__init__(self, *args, **kwargs)
48 LineFrontEndBase.__init__(self, *args, **kwargs)
51 # Instanciate an IPython0 interpreter to be able to use the
49 # Instanciate an IPython0 interpreter to be able to use the
52 # prefiltering.
50 # prefiltering.
53 self.ipython0 = make_IPython()
51 self.ipython0 = make_IPython()
54 # Set the pager:
52 # Set the pager:
55 self.ipython0.set_hook('show_in_pager',
53 self.ipython0.set_hook('show_in_pager',
56 lambda s, string: self.write("\n"+string))
54 lambda s, string: self.write("\n"+string))
57 self.ipython0.write = self.write
55 self.ipython0.write = self.write
58 self._ip = _ip = IPApi(self.ipython0)
56 self._ip = _ip = IPApi(self.ipython0)
59 # XXX: Hack: mix the two namespaces
57 # XXX: Hack: mix the two namespaces
60 self.shell.user_ns = self.ipython0.user_ns
58 self.shell.user_ns = self.ipython0.user_ns
61 self.shell.user_global_ns = self.ipython0.user_global_ns
59 self.shell.user_global_ns = self.ipython0.user_global_ns
62 # Make sure the raw system call doesn't get called, as we don't
60 # Make sure the raw system call doesn't get called, as we don't
63 # have a stdin accessible.
61 # have a stdin accessible.
64 self._ip.system = xterm_system
62 self._ip.system = xterm_system
65 # Redefine a serie of magics to avoid os.system:
63 # Redefine a serie of magics to avoid os.system:
66 # FIXME: I am redefining way too much magics.
64 # FIXME: I am redefining way too much magics.
67 for alias_name, (_, alias_value) in \
65 for alias_name, (_, alias_value) in \
68 _ip.IP.shell.alias_table.iteritems():
66 _ip.IP.shell.alias_table.iteritems():
69 magic = lambda s : _ip.magic('sx %s %s' % (alias_value, s))
67 magic = lambda s : _ip.magic('sx %s %s' % (alias_value, s))
70 setattr(_ip.IP, 'magic_%s' % alias_name, magic)
68 setattr(_ip.IP, 'magic_%s' % alias_name, magic)
71 # FIXME: I should create a real file-like object dedicated to this
69 # FIXME: I should create a real file-like object dedicated to this
72 # terminal
70 # terminal
73 self.shell.output_trap = SyncOutputTrap(write_out=self.write,
71 self.shell.output_trap = OutputTrap(
74 write_err=self.write)
72 out=FileLike(write_callback=self.write),
73 err=FileLike(write_callback=self.write),
74 )
75 # Capture and release the outputs, to make sure all the
75 # Capture and release the outputs, to make sure all the
76 # shadow variables are set
76 # shadow variables are set
77 self.capture_output()
77 self.capture_output()
78 self.release_output()
78 self.release_output()
79
79
80
80
81 def prefilter_input(self, input_string):
81 def prefilter_input(self, input_string):
82 """ Using IPython0 to prefilter the commands.
82 """ Using IPython0 to prefilter the commands.
83 """
83 """
84 input_string = LineFrontEndBase.prefilter_input(self, input_string)
84 input_string = LineFrontEndBase.prefilter_input(self, input_string)
85 filtered_lines = []
85 filtered_lines = []
86 # The IPython0 prefilters sometime produce output. We need to
86 # The IPython0 prefilters sometime produce output. We need to
87 # capture it.
87 # capture it.
88 self.capture_output()
88 self.capture_output()
89 self.last_result = dict(number=self.prompt_number)
89 self.last_result = dict(number=self.prompt_number)
90 try:
90 try:
91 for line in input_string.split('\n'):
91 for line in input_string.split('\n'):
92 filtered_lines.append(self.ipython0.prefilter(line, False))
92 filtered_lines.append(self.ipython0.prefilter(line, False))
93 except:
93 except:
94 # XXX: probably not the right thing to do.
94 # XXX: probably not the right thing to do.
95 self.ipython0.showsyntaxerror()
95 self.ipython0.showsyntaxerror()
96 self.after_execute()
96 self.after_execute()
97 finally:
97 finally:
98 self.release_output()
98 self.release_output()
99
99
100 filtered_string = '\n'.join(filtered_lines)
100 filtered_string = '\n'.join(filtered_lines)
101 return filtered_string
101 return filtered_string
102
102
103
103
104 def show_traceback(self):
104 def show_traceback(self):
105 self.capture_output()
105 self.capture_output()
106 self.ipython0.showtraceback()
106 self.ipython0.showtraceback()
107 self.release_output()
107 self.release_output()
108
108
109
109
110 def execute(self, python_string, raw_string=None):
110 def execute(self, python_string, raw_string=None):
111 self.capture_output()
111 self.capture_output()
112 LineFrontEndBase.execute(self, python_string,
112 LineFrontEndBase.execute(self, python_string,
113 raw_string=raw_string)
113 raw_string=raw_string)
114 self.release_output()
114 self.release_output()
115
115
116
116
117 def capture_output(self):
117 def capture_output(self):
118 """ Capture all the output mechanisms we can think of.
118 """ Capture all the output mechanisms we can think of.
119 """
119 """
120 self.__old_cout_write = Term.cout.write
120 self.__old_cout_write = Term.cout.write
121 self.__old_err_write = Term.cerr.write
121 self.__old_err_write = Term.cerr.write
122 Term.cout.write = self.write
122 Term.cout.write = self.write
123 Term.cerr.write = self.write
123 Term.cerr.write = self.write
124 self.__old_stdout = sys.stdout
124 self.__old_stdout = sys.stdout
125 self.__old_stderr= sys.stderr
125 self.__old_stderr= sys.stderr
126 sys.stdout = Term.cout
126 sys.stdout = Term.cout
127 sys.stderr = Term.cerr
127 sys.stderr = Term.cerr
128 self.__old_help_output = pydoc.help.output
128 self.__old_help_output = pydoc.help.output
129 pydoc.help.output = self.shell.output_trap.out
129 pydoc.help.output = self.shell.output_trap.out
130
130
131
131
132 def release_output(self):
132 def release_output(self):
133 """ Release all the different captures we have made.
133 """ Release all the different captures we have made.
134 """
134 """
135 Term.cout.write = self.__old_cout_write
135 Term.cout.write = self.__old_cout_write
136 Term.cerr.write = self.__old_err_write
136 Term.cerr.write = self.__old_err_write
137 sys.stdout = self.__old_stdout
137 sys.stdout = self.__old_stdout
138 sys.stderr = self.__old_stderr
138 sys.stderr = self.__old_stderr
139 pydoc.help.output = self.__old_help_output
139 pydoc.help.output = self.__old_help_output
140
140
141
141
142 def complete(self, line):
142 def complete(self, line):
143 word = line.split('\n')[-1].split(' ')[-1]
143 word = line.split('\n')[-1].split(' ')[-1]
144 completions = self.ipython0.complete(word)
144 completions = self.ipython0.complete(word)
145 # FIXME: The proper sort should be done in the complete method.
145 key = lambda x: x.replace('_', '')
146 key = lambda x: x.replace('_', '')
146 completions.sort(key=key)
147 completions.sort(key=key)
147 if completions:
148 if completions:
148 prefix = common_prefix(completions)
149 prefix = common_prefix(completions)
149 line = line[:-len(word)] + prefix
150 line = line[:-len(word)] + prefix
150 return line, completions
151 return line, completions
151
152
152
153
153 def do_exit(self):
154 def do_exit(self):
154 """ Exit the shell, cleanup and save the history.
155 """ Exit the shell, cleanup and save the history.
155 """
156 """
156 self.ipython0.atexit_operations()
157 self.ipython0.atexit_operations()
157
158
@@ -1,67 +1,49 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """ Redirects stdout/stderr to given write methods."""
3 """ File like object that redirects its write calls to a given callback."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
15 # Imports
16 #-------------------------------------------------------------------------------
17
18 import sys
14 import sys
19 from IPython.kernel.core.output_trap import OutputTrap
20
15
21 class FileLike(object):
16 class FileLike(object):
22 """ FileLike object that redirects all write to a callback.
17 """ FileLike object that redirects all write to a callback.
23
18
24 Only the write-related methods are implemented, as well as those
19 Only the write-related methods are implemented, as well as those
25 required to read a StringIO.
20 required to read a StringIO.
26 """
21 """
27 closed = False
22 closed = False
28
23
29 def __init__(self, write):
24 def __init__(self, write_callback):
30 self.write = write
25 self.write = write_callback
31
26
32 def flush(self):
27 def flush(self):
33 pass
28 pass
34
29
35 def close(self):
30 def close(self):
36 pass
31 pass
37
32
38 def writelines(self, lines):
33 def writelines(self, lines):
39 for line in lines:
34 for line in lines:
40 self.write(line)
35 self.write(line)
41
36
42 def isatty(self):
37 def isatty(self):
43 return False
38 return False
44
39
45 def getvalue(self):
40 def getvalue(self):
46 return ''
41 return ''
47
42
43 def reset(self):
44 pass
48
45
49 class SyncOutputTrap(OutputTrap):
46 def truncate(self):
50 """ Object which redirect text sent to stdout and stderr to write
51 callbacks.
52 """
53
54 def __init__(self, write_out, write_err):
55 # Store callbacks
56 self.out = FileLike(write_out)
57 self.err = FileLike(write_err)
58
59 # Boolean to check if the stdout/stderr hook is set.
60 self.out_set = False
61 self.err_set = False
62
63 def clear(self):
64 """ Clear out the buffers.
65 """
66 pass
47 pass
67
48
49
@@ -1,99 +1,105 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """ Trap stdout/stderr."""
3 """ Trap stdout/stderr."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 import sys
18 import sys
19 from cStringIO import StringIO
19 from cStringIO import StringIO
20
20
21
21
22 class OutputTrap(object):
22 class OutputTrap(object):
23 """ Object which can trap text sent to stdout and stderr.
23 """ Object which can trap text sent to stdout and stderr.
24 """
24 """
25
25
26 def __init__(self):
26 def __init__(self, out=None, err=None):
27 # Filelike objects to store stdout/stderr text.
27 # Filelike objects to store stdout/stderr text.
28 self.out = StringIO()
28 if out is None:
29 self.err = StringIO()
29 self.out = StringIO()
30 else:
31 self.out = out
32 if err is None:
33 self.err = StringIO()
34 else:
35 self.err = err
30
36
31 # Boolean to check if the stdout/stderr hook is set.
37 # Boolean to check if the stdout/stderr hook is set.
32 self.out_set = False
38 self.out_set = False
33 self.err_set = False
39 self.err_set = False
34
40
35 @property
41 @property
36 def out_text(self):
42 def out_text(self):
37 """ Return the text currently in the stdout buffer.
43 """ Return the text currently in the stdout buffer.
38 """
44 """
39 return self.out.getvalue()
45 return self.out.getvalue()
40
46
41 @property
47 @property
42 def err_text(self):
48 def err_text(self):
43 """ Return the text currently in the stderr buffer.
49 """ Return the text currently in the stderr buffer.
44 """
50 """
45 return self.err.getvalue()
51 return self.err.getvalue()
46
52
47 def set(self):
53 def set(self):
48 """ Set the hooks.
54 """ Set the hooks.
49 """
55 """
50
56
51 if sys.stdout is not self.out:
57 if sys.stdout is not self.out:
52 self._out_save = sys.stdout
58 self._out_save = sys.stdout
53 sys.stdout = self.out
59 sys.stdout = self.out
54 self.out_set = True
60 self.out_set = True
55
61
56 if sys.stderr is not self.err:
62 if sys.stderr is not self.err:
57 self._err_save = sys.stderr
63 self._err_save = sys.stderr
58 sys.stderr = self.err
64 sys.stderr = self.err
59 self.err_set = True
65 self.err_set = True
60
66
61 def unset(self):
67 def unset(self):
62 """ Remove the hooks.
68 """ Remove the hooks.
63 """
69 """
64
70
65 sys.stdout = self._out_save
71 sys.stdout = self._out_save
66 self.out_set = False
72 self.out_set = False
67
73
68 sys.stderr = self._err_save
74 sys.stderr = self._err_save
69 self.err_set = False
75 self.err_set = False
70
76
71 def clear(self):
77 def clear(self):
72 """ Clear out the buffers.
78 """ Clear out the buffers.
73 """
79 """
74
80
75 self.out.close()
81 self.out.reset()
76 self.out = StringIO()
82 self.out.truncate()
77
83
78 self.err.close()
84 self.err.reset()
79 self.err = StringIO()
85 self.err.truncate()
80
86
81 def add_to_message(self, message):
87 def add_to_message(self, message):
82 """ Add the text from stdout and stderr to the message from the
88 """ Add the text from stdout and stderr to the message from the
83 interpreter to its listeners.
89 interpreter to its listeners.
84
90
85 Parameters
91 Parameters
86 ----------
92 ----------
87 message : dict
93 message : dict
88 """
94 """
89
95
90 out_text = self.out_text
96 out_text = self.out_text
91 if out_text:
97 if out_text:
92 message['stdout'] = out_text
98 message['stdout'] = out_text
93
99
94 err_text = self.err_text
100 err_text = self.err_text
95 if err_text:
101 if err_text:
96 message['stderr'] = err_text
102 message['stderr'] = err_text
97
103
98
104
99
105
General Comments 0
You need to be logged in to leave comments. Login now