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