##// END OF EJS Templates
Add a docstring to magics to fix the broken "%magic" magic.
gvaroquaux -
Show More
@@ -1,230 +1,232 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 This is a transitory class, used here to do the transition between
7 7 ipython0 and ipython1. This class is meant to be short-lived as more
8 8 functionnality is abstracted out of ipython0 in reusable functions and
9 9 is added on the interpreter. This class can be a used to guide this
10 10 refactoring.
11 11 """
12 12 __docformat__ = "restructuredtext en"
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Copyright (C) 2008 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-------------------------------------------------------------------------------
20 20
21 21 #-------------------------------------------------------------------------------
22 22 # Imports
23 23 #-------------------------------------------------------------------------------
24 24 import sys
25 25
26 26 from linefrontendbase import LineFrontEndBase, common_prefix
27 27 from frontendbase import FrontEndBase
28 28
29 29 from IPython.ipmaker import make_IPython
30 30 from IPython.ipapi import IPApi
31 31 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
32 32
33 33 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
34 34
35 35 from IPython.genutils import Term
36 36 import pydoc
37 37 import os
38 38 import sys
39 39
40 40
41 41 def mk_system_call(system_call_function, command):
42 42 """ given a os.system replacement, and a leading string command,
43 43 returns a function that will execute the command with the given
44 44 argument string.
45 45 """
46 46 def my_system_call(args):
47 47 system_call_function("%s %s" % (command, args))
48
49 my_system_call.__doc__ = "Calls %s" % command
48 50 return my_system_call
49 51
50 52 #-------------------------------------------------------------------------------
51 53 # Frontend class using ipython0 to do the prefiltering.
52 54 #-------------------------------------------------------------------------------
53 55 class PrefilterFrontEnd(LineFrontEndBase):
54 56 """ Class that uses ipython0 to do prefilter the input, do the
55 57 completion and the magics.
56 58
57 59 The core trick is to use an ipython0 instance to prefilter the
58 60 input, and share the namespace between the interpreter instance used
59 61 to execute the statements and the ipython0 used for code
60 62 completion...
61 63 """
62 64
63 65 debug = False
64 66
65 67 def __init__(self, ipython0=None, *args, **kwargs):
66 68 """ Parameters:
67 69 -----------
68 70
69 71 ipython0: an optional ipython0 instance to use for command
70 72 prefiltering and completion.
71 73 """
72 74 LineFrontEndBase.__init__(self, *args, **kwargs)
73 75 self.shell.output_trap = RedirectorOutputTrap(
74 76 out_callback=self.write,
75 77 err_callback=self.write,
76 78 )
77 79 self.shell.traceback_trap = SyncTracebackTrap(
78 80 formatters=self.shell.traceback_trap.formatters,
79 81 )
80 82
81 83 # Start the ipython0 instance:
82 84 self.save_output_hooks()
83 85 if ipython0 is None:
84 86 # Instanciate an IPython0 interpreter to be able to use the
85 87 # prefiltering.
86 88 # XXX: argv=[] is a bit bold.
87 89 ipython0 = make_IPython(argv=[],
88 90 user_ns=self.shell.user_ns,
89 91 user_global_ns=self.shell.user_global_ns)
90 92 self.ipython0 = ipython0
91 93 # Set the pager:
92 94 self.ipython0.set_hook('show_in_pager',
93 95 lambda s, string: self.write("\n" + string))
94 96 self.ipython0.write = self.write
95 97 self._ip = _ip = IPApi(self.ipython0)
96 98 # Make sure the raw system call doesn't get called, as we don't
97 99 # have a stdin accessible.
98 100 self._ip.system = self.system_call
99 101 # XXX: Muck around with magics so that they work better
100 102 # in our environment
101 103 self.ipython0.magic_ls = mk_system_call(self.system_call,
102 104 'ls -CF')
103 105 # And now clean up the mess created by ipython0
104 106 self.release_output()
105 107
106 108
107 109 if not 'banner' in kwargs and self.banner is None:
108 110 self.banner = self.ipython0.BANNER + """
109 111 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
110 112
111 113 self.start()
112 114
113 115 #--------------------------------------------------------------------------
114 116 # FrontEndBase interface
115 117 #--------------------------------------------------------------------------
116 118
117 119 def show_traceback(self):
118 120 """ Use ipython0 to capture the last traceback and display it.
119 121 """
120 122 self.capture_output()
121 123 self.ipython0.showtraceback(tb_offset=-1)
122 124 self.release_output()
123 125
124 126
125 127 def execute(self, python_string, raw_string=None):
126 128 if self.debug:
127 129 print 'Executing Python code:', repr(python_string)
128 130 self.capture_output()
129 131 LineFrontEndBase.execute(self, python_string,
130 132 raw_string=raw_string)
131 133 self.release_output()
132 134
133 135
134 136 def save_output_hooks(self):
135 137 """ Store all the output hooks we can think of, to be able to
136 138 restore them.
137 139
138 140 We need to do this early, as starting the ipython0 instance will
139 141 screw ouput hooks.
140 142 """
141 143 self.__old_cout_write = Term.cout.write
142 144 self.__old_cerr_write = Term.cerr.write
143 145 self.__old_stdout = sys.stdout
144 146 self.__old_stderr= sys.stderr
145 147 self.__old_help_output = pydoc.help.output
146 148 self.__old_display_hook = sys.displayhook
147 149
148 150
149 151 def capture_output(self):
150 152 """ Capture all the output mechanisms we can think of.
151 153 """
152 154 self.save_output_hooks()
153 155 Term.cout.write = self.write
154 156 Term.cerr.write = self.write
155 157 sys.stdout = Term.cout
156 158 sys.stderr = Term.cerr
157 159 pydoc.help.output = self.shell.output_trap.out
158 160
159 161
160 162 def release_output(self):
161 163 """ Release all the different captures we have made.
162 164 """
163 165 Term.cout.write = self.__old_cout_write
164 166 Term.cerr.write = self.__old_cerr_write
165 167 sys.stdout = self.__old_stdout
166 168 sys.stderr = self.__old_stderr
167 169 pydoc.help.output = self.__old_help_output
168 170 sys.displayhook = self.__old_display_hook
169 171
170 172
171 173 def complete(self, line):
172 174 # FIXME: This should be factored out in the linefrontendbase
173 175 # method.
174 176 word = line.split('\n')[-1].split(' ')[-1]
175 177 completions = self.ipython0.complete(word)
176 178 # FIXME: The proper sort should be done in the complete method.
177 179 key = lambda x: x.replace('_', '')
178 180 completions.sort(key=key)
179 181 if completions:
180 182 prefix = common_prefix(completions)
181 183 line = line[:-len(word)] + prefix
182 184 return line, completions
183 185
184 186
185 187 #--------------------------------------------------------------------------
186 188 # LineFrontEndBase interface
187 189 #--------------------------------------------------------------------------
188 190
189 191 def prefilter_input(self, input_string):
190 192 """ Using IPython0 to prefilter the commands to turn them
191 193 in executable statements that are valid Python strings.
192 194 """
193 195 input_string = LineFrontEndBase.prefilter_input(self, input_string)
194 196 filtered_lines = []
195 197 # The IPython0 prefilters sometime produce output. We need to
196 198 # capture it.
197 199 self.capture_output()
198 200 self.last_result = dict(number=self.prompt_number)
199 201 try:
200 202 for line in input_string.split('\n'):
201 203 filtered_lines.append(
202 204 self.ipython0.prefilter(line, False).rstrip())
203 205 except:
204 206 # XXX: probably not the right thing to do.
205 207 self.ipython0.showsyntaxerror()
206 208 self.after_execute()
207 209 finally:
208 210 self.release_output()
209 211
210 212 # Clean up the trailing whitespace, to avoid indentation errors
211 213 filtered_string = '\n'.join(filtered_lines)
212 214 return filtered_string
213 215
214 216
215 217 #--------------------------------------------------------------------------
216 218 # PrefilterFrontEnd interface
217 219 #--------------------------------------------------------------------------
218 220
219 221 def system_call(self, command_string):
220 222 """ Allows for frontend to define their own system call, to be
221 223 able capture output and redirect input.
222 224 """
223 225 return os.system(command_string)
224 226
225 227
226 228 def do_exit(self):
227 229 """ Exit the shell, cleanup and save the history.
228 230 """
229 231 self.ipython0.atexit_operations()
230 232
General Comments 0
You need to be logged in to leave comments. Login now