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