##// END OF EJS Templates
Better traceback support.
Gael Varoquaux -
Show More
@@ -0,0 +1,41 b''
1 # encoding: utf-8
2
3 """Object to manage sys.excepthook().
4
5 Synchronous version: prints errors when called.
6 """
7
8 __docformat__ = "restructuredtext en"
9
10 #-------------------------------------------------------------------------------
11 # Copyright (C) 2008 The IPython Development Team
12 #
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
15 #-------------------------------------------------------------------------------
16
17 #-------------------------------------------------------------------------------
18 # Imports
19 #-------------------------------------------------------------------------------
20 from traceback_trap import TracebackTrap
21 from IPython.ultraTB import ColorTB
22
23 class SyncTracebackTrap(TracebackTrap):
24
25 def __init__(self, sync_formatter=None, formatters=None):
26 TracebackTrap.__init__(self, formatters=formatters)
27 if sync_formatter is None:
28 sync_formatter = ColorTB(color_scheme='LightBG')
29 self.sync_formatter = sync_formatter
30
31
32 def hook(self, *args):
33 """ This method actually implements the hook.
34 """
35 self.args = args
36
37 print self.sync_formatters(*self.args)
38
39
40
41
@@ -1,48 +1,55 b''
1 1 # encoding: utf-8
2 2 """
3 3 Object for encapsulating process execution by using callbacks for stdout,
4 4 stderr and stdin.
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 from subprocess import Popen, PIPE
19 19 from threading import Thread
20
20 from time import sleep
21 21
22 22 class PipedProcess(Thread):
23 23
24 24 def __init__(self, command_string, out_callback,
25 25 end_callback=None,):
26 26 self.command_string = command_string
27 27 self.out_callback = out_callback
28 28 self.end_callback = end_callback
29 29 Thread.__init__(self)
30 30
31 31
32 32 def run(self):
33 33 """ Start the process and hook up the callbacks.
34 34 """
35 35 process = Popen((self.command_string + ' 2>&1', ), shell=True,
36 36 universal_newlines=True,
37 37 stdout=PIPE, stdin=PIPE)
38 38 self.process = process
39 39 while True:
40 40 out_char = process.stdout.read(1)
41 if out_char == '' and process.poll() is not None:
42 break
43 self.out_callback(out_char)
41 if out_char == '':
42 if process.poll() is not None:
43 # The process has finished
44 break
45 else:
46 # The process is not giving any interesting
47 # output. No use polling it immediatly.
48 sleep(0.1)
49 else:
50 self.out_callback(out_char)
44 51
45 52 if self.end_callback is not None:
46 53 self.end_callback()
47 54
48 55
@@ -1,163 +1,162 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 24 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
25 25
26 26 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
27 27
28 from IPython.ultraTB import ColorTB
29 28 from IPython.genutils import Term
30 29 import pydoc
31 30
32 31 def mk_system_call(system_call_function, command):
33 32 """ given a os.system replacement, and a leading string command,
34 33 returns a function that will execute the command with the given
35 34 argument string.
36 35 """
37 36 def my_system_call(args):
38 37 system_call_function("%s %s" % (command, args))
39 38 return my_system_call
40 39
41 40 #-------------------------------------------------------------------------------
42 41 # Frontend class using ipython0 to do the prefiltering.
43 42 #-------------------------------------------------------------------------------
44 43 class PrefilterFrontEnd(LineFrontEndBase):
45 44
46 45 def __init__(self, *args, **kwargs):
47 46 LineFrontEndBase.__init__(self, *args, **kwargs)
48 47 # Instanciate an IPython0 interpreter to be able to use the
49 48 # prefiltering.
50 49 self.ipython0 = make_IPython()
51 50 # Set the pager:
52 51 self.ipython0.set_hook('show_in_pager',
53 52 lambda s, string: self.write("\n"+string))
54 53 self.ipython0.write = self.write
55 54 self._ip = _ip = IPApi(self.ipython0)
56 55 # XXX: Hack: mix the two namespaces
57 56 self.shell.user_ns = self.ipython0.user_ns
58 57 self.shell.user_global_ns = self.ipython0.user_global_ns
59 58 # Make sure the raw system call doesn't get called, as we don't
60 59 # have a stdin accessible.
61 60 self._ip.system = self.system_call
62 61 # XXX: Muck around with magics so that they work better
63 62 # in our environment
64 63 self.ipython0.magic_ls = mk_system_call(self.system_call,
65 64 'ls -CF')
66 65 self.shell.output_trap = RedirectorOutputTrap(
67 66 out_callback=self.write,
68 67 err_callback=self.write,
69 68 )
70 69 self.shell.traceback_trap = SyncTracebackTrap(
71 formatters=[ColorTB(color_scheme='LightBG'), ]
70 formatters=self.shell.traceback_trap.formatters
72 71 )
73 72 # Capture and release the outputs, to make sure all the
74 73 # shadow variables are set
75 74 self.capture_output()
76 75 self.release_output()
77 76
78 77
79 78 def prefilter_input(self, input_string):
80 79 """ Using IPython0 to prefilter the commands.
81 80 """
82 81 input_string = LineFrontEndBase.prefilter_input(self, input_string)
83 82 filtered_lines = []
84 83 # The IPython0 prefilters sometime produce output. We need to
85 84 # capture it.
86 85 self.capture_output()
87 86 self.last_result = dict(number=self.prompt_number)
88 87 try:
89 88 for line in input_string.split('\n'):
90 89 filtered_lines.append(self.ipython0.prefilter(line, False))
91 90 except:
92 91 # XXX: probably not the right thing to do.
93 92 self.ipython0.showsyntaxerror()
94 93 self.after_execute()
95 94 finally:
96 95 self.release_output()
97 96
98 97 filtered_string = '\n'.join(filtered_lines)
99 98 return filtered_string
100 99
101 100
102 101 def show_traceback(self):
103 102 self.capture_output()
104 103 self.ipython0.showtraceback()
105 104 self.release_output()
106 105
107 106
108 107 def execute(self, python_string, raw_string=None):
109 108 self.capture_output()
110 109 LineFrontEndBase.execute(self, python_string,
111 110 raw_string=raw_string)
112 111 self.release_output()
113 112
114 113
115 114 def system_call(self, command):
116 115 """ Allows for frontend to define their own system call, to be
117 116 able capture output and redirect input.
118 117 """
119 118 return os.system(command, args)
120 119
121 120
122 121 def capture_output(self):
123 122 """ Capture all the output mechanisms we can think of.
124 123 """
125 124 self.__old_cout_write = Term.cout.write
126 125 self.__old_err_write = Term.cerr.write
127 126 Term.cout.write = self.write
128 127 Term.cerr.write = self.write
129 128 self.__old_stdout = sys.stdout
130 129 self.__old_stderr= sys.stderr
131 130 sys.stdout = Term.cout
132 131 sys.stderr = Term.cerr
133 132 self.__old_help_output = pydoc.help.output
134 133 pydoc.help.output = self.shell.output_trap.out
135 134
136 135
137 136 def release_output(self):
138 137 """ Release all the different captures we have made.
139 138 """
140 139 Term.cout.write = self.__old_cout_write
141 140 Term.cerr.write = self.__old_err_write
142 141 sys.stdout = self.__old_stdout
143 142 sys.stderr = self.__old_stderr
144 143 pydoc.help.output = self.__old_help_output
145 144
146 145
147 146 def complete(self, line):
148 147 word = line.split('\n')[-1].split(' ')[-1]
149 148 completions = self.ipython0.complete(word)
150 149 # FIXME: The proper sort should be done in the complete method.
151 150 key = lambda x: x.replace('_', '')
152 151 completions.sort(key=key)
153 152 if completions:
154 153 prefix = common_prefix(completions)
155 154 line = line[:-len(word)] + prefix
156 155 return line, completions
157 156
158 157
159 158 def do_exit(self):
160 159 """ Exit the shell, cleanup and save the history.
161 160 """
162 161 self.ipython0.atexit_operations()
163 162
General Comments 0
You need to be logged in to leave comments. Login now