##// END OF EJS Templates
Remove unused imports that where Python2.4-incompatible.
Gael Varoquaux -
Show More
@@ -1,362 +1,360 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
3 """
3 """
4 frontendbase provides an interface and base class for GUI frontends for
4 frontendbase provides an interface and base class for GUI frontends for
5 IPython.kernel/IPython.kernel.core.
5 IPython.kernel/IPython.kernel.core.
6
6
7 Frontend implementations will likely want to subclass FrontEndBase.
7 Frontend implementations will likely want to subclass FrontEndBase.
8
8
9 Author: Barry Wark
9 Author: Barry Wark
10 """
10 """
11 __docformat__ = "restructuredtext en"
11 __docformat__ = "restructuredtext en"
12
12
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19
19
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import string
23 import string
24 import uuid
24 import uuid
25 import _ast
25 import _ast
26
26
27 from IPython.frontend.zopeinterface import (
27 from IPython.frontend.zopeinterface import (
28 Interface,
28 Interface,
29 Attribute,
29 Attribute,
30 implements,
31 classProvides
32 )
30 )
33 from IPython.kernel.core.history import FrontEndHistory
31 from IPython.kernel.core.history import FrontEndHistory
34 from IPython.kernel.core.util import Bunch
32 from IPython.kernel.core.util import Bunch
35
33
36 ##############################################################################
34 ##############################################################################
37 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
35 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
38 # not
36 # not
39
37
40 rc = Bunch()
38 rc = Bunch()
41 rc.prompt_in1 = r'In [$number]: '
39 rc.prompt_in1 = r'In [$number]: '
42 rc.prompt_in2 = r'...'
40 rc.prompt_in2 = r'...'
43 rc.prompt_out = r'Out [$number]: '
41 rc.prompt_out = r'Out [$number]: '
44
42
45 ##############################################################################
43 ##############################################################################
46 # Interface definitions
44 # Interface definitions
47 ##############################################################################
45 ##############################################################################
48
46
49 class IFrontEndFactory(Interface):
47 class IFrontEndFactory(Interface):
50 """Factory interface for frontends."""
48 """Factory interface for frontends."""
51
49
52 def __call__(engine=None, history=None):
50 def __call__(engine=None, history=None):
53 """
51 """
54 Parameters:
52 Parameters:
55 interpreter : IPython.kernel.engineservice.IEngineCore
53 interpreter : IPython.kernel.engineservice.IEngineCore
56 """
54 """
57
55
58 pass
56 pass
59
57
60
58
61 class IFrontEnd(Interface):
59 class IFrontEnd(Interface):
62 """Interface for frontends. All methods return t.i.d.Deferred"""
60 """Interface for frontends. All methods return t.i.d.Deferred"""
63
61
64 Attribute("input_prompt_template", "string.Template instance\
62 Attribute("input_prompt_template", "string.Template instance\
65 substituteable with execute result.")
63 substituteable with execute result.")
66 Attribute("output_prompt_template", "string.Template instance\
64 Attribute("output_prompt_template", "string.Template instance\
67 substituteable with execute result.")
65 substituteable with execute result.")
68 Attribute("continuation_prompt_template", "string.Template instance\
66 Attribute("continuation_prompt_template", "string.Template instance\
69 substituteable with execute result.")
67 substituteable with execute result.")
70
68
71 def update_cell_prompt(result, blockID=None):
69 def update_cell_prompt(result, blockID=None):
72 """Subclass may override to update the input prompt for a block.
70 """Subclass may override to update the input prompt for a block.
73
71
74 In asynchronous frontends, this method will be called as a
72 In asynchronous frontends, this method will be called as a
75 twisted.internet.defer.Deferred's callback/errback.
73 twisted.internet.defer.Deferred's callback/errback.
76 Implementations should thus return result when finished.
74 Implementations should thus return result when finished.
77
75
78 Result is a result dict in case of success, and a
76 Result is a result dict in case of success, and a
79 twisted.python.util.failure.Failure in case of an error
77 twisted.python.util.failure.Failure in case of an error
80 """
78 """
81
79
82 pass
80 pass
83
81
84 def render_result(result):
82 def render_result(result):
85 """Render the result of an execute call. Implementors may choose the
83 """Render the result of an execute call. Implementors may choose the
86 method of rendering.
84 method of rendering.
87 For example, a notebook-style frontend might render a Chaco plot
85 For example, a notebook-style frontend might render a Chaco plot
88 inline.
86 inline.
89
87
90 Parameters:
88 Parameters:
91 result : dict (result of IEngineBase.execute )
89 result : dict (result of IEngineBase.execute )
92 blockID = result['blockID']
90 blockID = result['blockID']
93
91
94 Result:
92 Result:
95 Output of frontend rendering
93 Output of frontend rendering
96 """
94 """
97
95
98 pass
96 pass
99
97
100 def render_error(failure):
98 def render_error(failure):
101 """Subclasses must override to render the failure.
99 """Subclasses must override to render the failure.
102
100
103 In asynchronous frontend, since this method will be called as a
101 In asynchronous frontend, since this method will be called as a
104 twisted.internet.defer.Deferred's callback. Implementations
102 twisted.internet.defer.Deferred's callback. Implementations
105 should thus return result when finished.
103 should thus return result when finished.
106
104
107 blockID = failure.blockID
105 blockID = failure.blockID
108 """
106 """
109
107
110 pass
108 pass
111
109
112 def input_prompt(number=''):
110 def input_prompt(number=''):
113 """Returns the input prompt by subsituting into
111 """Returns the input prompt by subsituting into
114 self.input_prompt_template
112 self.input_prompt_template
115 """
113 """
116 pass
114 pass
117
115
118 def output_prompt(number=''):
116 def output_prompt(number=''):
119 """Returns the output prompt by subsituting into
117 """Returns the output prompt by subsituting into
120 self.output_prompt_template
118 self.output_prompt_template
121 """
119 """
122
120
123 pass
121 pass
124
122
125 def continuation_prompt():
123 def continuation_prompt():
126 """Returns the continuation prompt by subsituting into
124 """Returns the continuation prompt by subsituting into
127 self.continuation_prompt_template
125 self.continuation_prompt_template
128 """
126 """
129
127
130 pass
128 pass
131
129
132 def is_complete(block):
130 def is_complete(block):
133 """Returns True if block is complete, False otherwise."""
131 """Returns True if block is complete, False otherwise."""
134
132
135 pass
133 pass
136
134
137 def compile_ast(block):
135 def compile_ast(block):
138 """Compiles block to an _ast.AST"""
136 """Compiles block to an _ast.AST"""
139
137
140 pass
138 pass
141
139
142 def get_history_previous(current_block):
140 def get_history_previous(current_block):
143 """Returns the block previous in the history. Saves currentBlock if
141 """Returns the block previous in the history. Saves currentBlock if
144 the history_cursor is currently at the end of the input history"""
142 the history_cursor is currently at the end of the input history"""
145 pass
143 pass
146
144
147 def get_history_next():
145 def get_history_next():
148 """Returns the next block in the history."""
146 """Returns the next block in the history."""
149
147
150 pass
148 pass
151
149
152 def complete(self, line):
150 def complete(self, line):
153 """Returns the list of possible completions, and the completed
151 """Returns the list of possible completions, and the completed
154 line.
152 line.
155
153
156 The input argument is the full line to be completed. This method
154 The input argument is the full line to be completed. This method
157 returns both the line completed as much as possible, and the list
155 returns both the line completed as much as possible, and the list
158 of further possible completions (full words).
156 of further possible completions (full words).
159 """
157 """
160 pass
158 pass
161
159
162
160
163 ##############################################################################
161 ##############################################################################
164 # Base class for all the frontends.
162 # Base class for all the frontends.
165 ##############################################################################
163 ##############################################################################
166
164
167 class FrontEndBase(object):
165 class FrontEndBase(object):
168 """
166 """
169 FrontEndBase manages the state tasks for a CLI frontend:
167 FrontEndBase manages the state tasks for a CLI frontend:
170 - Input and output history management
168 - Input and output history management
171 - Input/continuation and output prompt generation
169 - Input/continuation and output prompt generation
172
170
173 Some issues (due to possibly unavailable engine):
171 Some issues (due to possibly unavailable engine):
174 - How do we get the current cell number for the engine?
172 - How do we get the current cell number for the engine?
175 - How do we handle completions?
173 - How do we handle completions?
176 """
174 """
177
175
178 history_cursor = 0
176 history_cursor = 0
179
177
180 input_prompt_template = string.Template(rc.prompt_in1)
178 input_prompt_template = string.Template(rc.prompt_in1)
181 output_prompt_template = string.Template(rc.prompt_out)
179 output_prompt_template = string.Template(rc.prompt_out)
182 continuation_prompt_template = string.Template(rc.prompt_in2)
180 continuation_prompt_template = string.Template(rc.prompt_in2)
183
181
184 def __init__(self, shell=None, history=None):
182 def __init__(self, shell=None, history=None):
185 self.shell = shell
183 self.shell = shell
186 if history is None:
184 if history is None:
187 self.history = FrontEndHistory(input_cache=[''])
185 self.history = FrontEndHistory(input_cache=[''])
188 else:
186 else:
189 self.history = history
187 self.history = history
190
188
191
189
192 def input_prompt(self, number=''):
190 def input_prompt(self, number=''):
193 """Returns the current input prompt
191 """Returns the current input prompt
194
192
195 It would be great to use ipython1.core.prompts.Prompt1 here
193 It would be great to use ipython1.core.prompts.Prompt1 here
196 """
194 """
197 return self.input_prompt_template.safe_substitute({'number':number})
195 return self.input_prompt_template.safe_substitute({'number':number})
198
196
199
197
200 def continuation_prompt(self):
198 def continuation_prompt(self):
201 """Returns the current continuation prompt"""
199 """Returns the current continuation prompt"""
202
200
203 return self.continuation_prompt_template.safe_substitute()
201 return self.continuation_prompt_template.safe_substitute()
204
202
205 def output_prompt(self, number=''):
203 def output_prompt(self, number=''):
206 """Returns the output prompt for result"""
204 """Returns the output prompt for result"""
207
205
208 return self.output_prompt_template.safe_substitute({'number':number})
206 return self.output_prompt_template.safe_substitute({'number':number})
209
207
210
208
211 def is_complete(self, block):
209 def is_complete(self, block):
212 """Determine if block is complete.
210 """Determine if block is complete.
213
211
214 Parameters
212 Parameters
215 block : string
213 block : string
216
214
217 Result
215 Result
218 True if block can be sent to the engine without compile errors.
216 True if block can be sent to the engine without compile errors.
219 False otherwise.
217 False otherwise.
220 """
218 """
221
219
222 try:
220 try:
223 ast = self.compile_ast(block)
221 ast = self.compile_ast(block)
224 except:
222 except:
225 return False
223 return False
226
224
227 lines = block.split('\n')
225 lines = block.split('\n')
228 return (len(lines)==1 or str(lines[-1])=='')
226 return (len(lines)==1 or str(lines[-1])=='')
229
227
230
228
231 def compile_ast(self, block):
229 def compile_ast(self, block):
232 """Compile block to an AST
230 """Compile block to an AST
233
231
234 Parameters:
232 Parameters:
235 block : str
233 block : str
236
234
237 Result:
235 Result:
238 AST
236 AST
239
237
240 Throws:
238 Throws:
241 Exception if block cannot be compiled
239 Exception if block cannot be compiled
242 """
240 """
243
241
244 return compile(block, "<string>", "exec", _ast.PyCF_ONLY_AST)
242 return compile(block, "<string>", "exec", _ast.PyCF_ONLY_AST)
245
243
246
244
247 def execute(self, block, blockID=None):
245 def execute(self, block, blockID=None):
248 """Execute the block and return the result.
246 """Execute the block and return the result.
249
247
250 Parameters:
248 Parameters:
251 block : {str, AST}
249 block : {str, AST}
252 blockID : any
250 blockID : any
253 Caller may provide an ID to identify this block.
251 Caller may provide an ID to identify this block.
254 result['blockID'] := blockID
252 result['blockID'] := blockID
255
253
256 Result:
254 Result:
257 Deferred result of self.interpreter.execute
255 Deferred result of self.interpreter.execute
258 """
256 """
259
257
260 if(not self.is_complete(block)):
258 if(not self.is_complete(block)):
261 raise Exception("Block is not compilable")
259 raise Exception("Block is not compilable")
262
260
263 if(blockID == None):
261 if(blockID == None):
264 blockID = uuid.uuid4() #random UUID
262 blockID = uuid.uuid4() #random UUID
265
263
266 try:
264 try:
267 result = self.shell.execute(block)
265 result = self.shell.execute(block)
268 except Exception,e:
266 except Exception,e:
269 e = self._add_block_id_for_failure(e, blockID=blockID)
267 e = self._add_block_id_for_failure(e, blockID=blockID)
270 e = self.update_cell_prompt(e, blockID=blockID)
268 e = self.update_cell_prompt(e, blockID=blockID)
271 e = self.render_error(e)
269 e = self.render_error(e)
272 else:
270 else:
273 result = self._add_block_id_for_result(result, blockID=blockID)
271 result = self._add_block_id_for_result(result, blockID=blockID)
274 result = self.update_cell_prompt(result, blockID=blockID)
272 result = self.update_cell_prompt(result, blockID=blockID)
275 result = self.render_result(result)
273 result = self.render_result(result)
276
274
277 return result
275 return result
278
276
279
277
280 def _add_block_id_for_result(self, result, blockID):
278 def _add_block_id_for_result(self, result, blockID):
281 """Add the blockID to result or failure. Unfortunatley, we have to
279 """Add the blockID to result or failure. Unfortunatley, we have to
282 treat failures differently than result dicts.
280 treat failures differently than result dicts.
283 """
281 """
284
282
285 result['blockID'] = blockID
283 result['blockID'] = blockID
286
284
287 return result
285 return result
288
286
289 def _add_block_id_for_failure(self, failure, blockID):
287 def _add_block_id_for_failure(self, failure, blockID):
290 """_add_block_id_for_failure"""
288 """_add_block_id_for_failure"""
291 failure.blockID = blockID
289 failure.blockID = blockID
292 return failure
290 return failure
293
291
294
292
295 def _add_history(self, result, block=None):
293 def _add_history(self, result, block=None):
296 """Add block to the history"""
294 """Add block to the history"""
297
295
298 assert(block != None)
296 assert(block != None)
299 self.history.add_items([block])
297 self.history.add_items([block])
300 self.history_cursor += 1
298 self.history_cursor += 1
301
299
302 return result
300 return result
303
301
304
302
305 def get_history_previous(self, current_block):
303 def get_history_previous(self, current_block):
306 """ Returns previous history string and decrement history cursor.
304 """ Returns previous history string and decrement history cursor.
307 """
305 """
308 command = self.history.get_history_item(self.history_cursor - 1)
306 command = self.history.get_history_item(self.history_cursor - 1)
309
307
310 if command is not None:
308 if command is not None:
311 if(self.history_cursor+1 == len(self.history.input_cache)):
309 if(self.history_cursor+1 == len(self.history.input_cache)):
312 self.history.input_cache[self.history_cursor] = current_block
310 self.history.input_cache[self.history_cursor] = current_block
313 self.history_cursor -= 1
311 self.history_cursor -= 1
314 return command
312 return command
315
313
316
314
317 def get_history_next(self):
315 def get_history_next(self):
318 """ Returns next history string and increment history cursor.
316 """ Returns next history string and increment history cursor.
319 """
317 """
320 command = self.history.get_history_item(self.history_cursor+1)
318 command = self.history.get_history_item(self.history_cursor+1)
321
319
322 if command is not None:
320 if command is not None:
323 self.history_cursor += 1
321 self.history_cursor += 1
324 return command
322 return command
325
323
326 ###
324 ###
327 # Subclasses probably want to override these methods...
325 # Subclasses probably want to override these methods...
328 ###
326 ###
329
327
330 def update_cell_prompt(self, result, blockID=None):
328 def update_cell_prompt(self, result, blockID=None):
331 """Subclass may override to update the input prompt for a block.
329 """Subclass may override to update the input prompt for a block.
332
330
333 This method only really makes sens in asyncrhonous frontend.
331 This method only really makes sens in asyncrhonous frontend.
334 Since this method will be called as a
332 Since this method will be called as a
335 twisted.internet.defer.Deferred's callback, implementations should
333 twisted.internet.defer.Deferred's callback, implementations should
336 return result when finished.
334 return result when finished.
337 """
335 """
338
336
339 raise NotImplementedError
337 raise NotImplementedError
340
338
341
339
342 def render_result(self, result):
340 def render_result(self, result):
343 """Subclasses must override to render result.
341 """Subclasses must override to render result.
344
342
345 In asynchronous frontends, this method will be called as a
343 In asynchronous frontends, this method will be called as a
346 twisted.internet.defer.Deferred's callback. Implementations
344 twisted.internet.defer.Deferred's callback. Implementations
347 should thus return result when finished.
345 should thus return result when finished.
348 """
346 """
349
347
350 raise NotImplementedError
348 raise NotImplementedError
351
349
352
350
353 def render_error(self, failure):
351 def render_error(self, failure):
354 """Subclasses must override to render the failure.
352 """Subclasses must override to render the failure.
355
353
356 In asynchronous frontends, this method will be called as a
354 In asynchronous frontends, this method will be called as a
357 twisted.internet.defer.Deferred's callback. Implementations
355 twisted.internet.defer.Deferred's callback. Implementations
358 should thus return result when finished.
356 should thus return result when finished.
359 """
357 """
360
358
361 raise NotImplementedError
359 raise NotImplementedError
362
360
@@ -1,34 +1,27 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
3 """
3 """
4 zope.interface mock. If zope is installed, this module provides a zope
4 zope.interface mock. If zope is installed, this module provides a zope
5 interface classes, if not it provides mocks for them.
5 interface classes, if not it provides mocks for them.
6
6
7 Classes provided:
7 Classes provided:
8 Interface, Attribute, implements, classProvides
8 Interface, Attribute, implements, classProvides
9 """
9 """
10 __docformat__ = "restructuredtext en"
10 __docformat__ = "restructuredtext en"
11
11
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13 # Copyright (C) 2008 The IPython Development Team
13 # Copyright (C) 2008 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18
18
19 #-------------------------------------------------------------------------------
20 # Imports
21 #-------------------------------------------------------------------------------
22 import string
23 import uuid
24 import _ast
25
26 try:
19 try:
27 from zope.interface import Interface, Attribute, implements, classProvides
20 from zope.interface import Interface, Attribute, implements, classProvides
28 except ImportError:
21 except ImportError:
29 #zope.interface is not available
22 #zope.interface is not available
30 Interface = object
23 Interface = object
31 def Attribute(name, doc): pass
24 def Attribute(name, doc): pass
32 def implements(interface): pass
25 def implements(interface): pass
33 def classProvides(interface): pass
26 def classProvides(interface): pass
34
27
General Comments 0
You need to be logged in to leave comments. Login now