Show More
@@ -40,6 +40,7 b' from IPython.kernel.engineservice import EngineService, ThreadedEngineService' | |||||
40 | from IPython.frontend.frontendbase import FrontEndBase |
|
40 | from IPython.frontend.frontendbase import FrontEndBase | |
41 |
|
41 | |||
42 | from twisted.internet.threads import blockingCallFromThread |
|
42 | from twisted.internet.threads import blockingCallFromThread | |
|
43 | from twisted.python.failure import Failure | |||
43 |
|
44 | |||
44 | #------------------------------------------------------------------------------- |
|
45 | #------------------------------------------------------------------------------- | |
45 | # Classes to implement the Cocoa frontend |
|
46 | # Classes to implement the Cocoa frontend | |
@@ -305,8 +306,13 b' class IPythonCocoaController(NSObject, FrontEndBase):' | |||||
305 | return block[-1] |
|
306 | return block[-1] | |
306 |
|
307 | |||
307 | def update_cell_prompt(self, result): |
|
308 | def update_cell_prompt(self, result): | |
308 | blockID = result['blockID'] |
|
309 | if(isinstance(result, Failure)): | |
309 | self.insert_text(self.inputPrompt(result=result), |
|
310 | blockID = result.blockID | |
|
311 | else: | |||
|
312 | blockID = result['blockID'] | |||
|
313 | ||||
|
314 | ||||
|
315 | self.insert_text(self.input_prompt(result=result), | |||
310 | textRange=NSMakeRange(self.blockRanges[blockID].location,0), |
|
316 | textRange=NSMakeRange(self.blockRanges[blockID].location,0), | |
311 | scrollToVisible=False |
|
317 | scrollToVisible=False | |
312 | ) |
|
318 | ) | |
@@ -321,7 +327,7 b' class IPythonCocoaController(NSObject, FrontEndBase):' | |||||
321 |
|
327 | |||
322 | #print inputRange,self.currentBlockRange() |
|
328 | #print inputRange,self.currentBlockRange() | |
323 | self.insert_text('\n' + |
|
329 | self.insert_text('\n' + | |
324 |
self.output |
|
330 | self.output_prompt(result) + | |
325 | result.get('display',{}).get('pprint','') + |
|
331 | result.get('display',{}).get('pprint','') + | |
326 | '\n\n', |
|
332 | '\n\n', | |
327 | textRange=NSMakeRange(inputRange.location+inputRange.length, 0)) |
|
333 | textRange=NSMakeRange(inputRange.location+inputRange.length, 0)) |
@@ -89,16 +89,16 b' class IFrontEnd(zi.Interface):' | |||||
89 | pass |
|
89 | pass | |
90 |
|
90 | |||
91 |
|
91 | |||
92 |
def input |
|
92 | def input_prompt(result={}): | |
93 | """Returns the input prompt by subsituting into self.input_prompt_template""" |
|
93 | """Returns the input prompt by subsituting into self.input_prompt_template""" | |
94 | pass |
|
94 | pass | |
95 |
|
95 | |||
96 |
def output |
|
96 | def output_prompt(result): | |
97 | """Returns the output prompt by subsituting into self.output_prompt_template""" |
|
97 | """Returns the output prompt by subsituting into self.output_prompt_template""" | |
98 |
|
98 | |||
99 | pass |
|
99 | pass | |
100 |
|
100 | |||
101 |
def continuation |
|
101 | def continuation_prompt(): | |
102 | """Returns the continuation prompt by subsituting into self.continuation_prompt_template""" |
|
102 | """Returns the continuation prompt by subsituting into self.continuation_prompt_template""" | |
103 |
|
103 | |||
104 | pass |
|
104 | pass | |
@@ -157,7 +157,7 b' class FrontEndBase(object):' | |||||
157 | self.history = history |
|
157 | self.history = history | |
158 |
|
158 | |||
159 |
|
159 | |||
160 |
def input |
|
160 | def input_prompt(self, result={}): | |
161 | """Returns the current input prompt |
|
161 | """Returns the current input prompt | |
162 |
|
162 | |||
163 | It would be great to use ipython1.core.prompts.Prompt1 here |
|
163 | It would be great to use ipython1.core.prompts.Prompt1 here | |
@@ -168,12 +168,12 b' class FrontEndBase(object):' | |||||
168 | return self.input_prompt_template.safe_substitute(result) |
|
168 | return self.input_prompt_template.safe_substitute(result) | |
169 |
|
169 | |||
170 |
|
170 | |||
171 |
def continuation |
|
171 | def continuation_prompt(self): | |
172 | """Returns the current continuation prompt""" |
|
172 | """Returns the current continuation prompt""" | |
173 |
|
173 | |||
174 | return self.continuation_prompt_template.safe_substitute() |
|
174 | return self.continuation_prompt_template.safe_substitute() | |
175 |
|
175 | |||
176 |
def output |
|
176 | def output_prompt(self, result): | |
177 | """Returns the output prompt for result""" |
|
177 | """Returns the output prompt for result""" | |
178 |
|
178 | |||
179 | return self.output_prompt_template.safe_substitute(result) |
|
179 | return self.output_prompt_template.safe_substitute(result) | |
@@ -234,18 +234,23 b' class FrontEndBase(object):' | |||||
234 | blockID = uuid.uuid4() #random UUID |
|
234 | blockID = uuid.uuid4() #random UUID | |
235 |
|
235 | |||
236 | d = self.engine.execute(block) |
|
236 | d = self.engine.execute(block) | |
237 | d.addCallback(self._add_block_id, blockID) |
|
|||
238 | d.addCallback(self._add_history, block=block) |
|
237 | d.addCallback(self._add_history, block=block) | |
239 | d.addCallback(self.update_cell_prompt) |
|
238 | d.addBoth(self._add_block_id, blockID) | |
|
239 | d.addBoth(self.update_cell_prompt) | |||
240 | d.addCallbacks(self.render_result, errback=self.render_error) |
|
240 | d.addCallbacks(self.render_result, errback=self.render_error) | |
241 |
|
241 | |||
242 | return d |
|
242 | return d | |
243 |
|
243 | |||
244 |
|
244 | |||
245 | def _add_block_id(self, result, blockID): |
|
245 | def _add_block_id(self, result, blockID): | |
246 | """Add the blockID to result""" |
|
246 | """Add the blockID to result or failure. Unfortunatley, we have to treat failures | |
|
247 | differently than result dicts | |||
|
248 | """ | |||
247 |
|
249 | |||
248 | result['blockID'] = blockID |
|
250 | if(isinstance(result, Failure)): | |
|
251 | result.blockID = blockID | |||
|
252 | else: | |||
|
253 | result['blockID'] = blockID | |||
249 |
|
254 | |||
250 | return result |
|
255 | return result | |
251 |
|
256 | |||
@@ -287,7 +292,17 b' class FrontEndBase(object):' | |||||
287 | def update_cell_prompt(self, result): |
|
292 | def update_cell_prompt(self, result): | |
288 | """Subclass may override to update the input prompt for a block. |
|
293 | """Subclass may override to update the input prompt for a block. | |
289 | Since this method will be called as a twisted.internet.defer.Deferred's callback, |
|
294 | Since this method will be called as a twisted.internet.defer.Deferred's callback, | |
290 |
implementations should return result when finished. |
|
295 | implementations should return result when finished. | |
|
296 | ||||
|
297 | NP: result is a failure if the execute returned a failre. To get the blockID, you should | |||
|
298 | do something like:: | |||
|
299 | if(isinstance(result, twisted.python.failure.Failure)): | |||
|
300 | blockID = result.blockID | |||
|
301 | else: | |||
|
302 | blockID = result['blockID'] | |||
|
303 | ||||
|
304 | ||||
|
305 | """ | |||
291 |
|
306 | |||
292 | return result |
|
307 | return result | |
293 |
|
308 |
@@ -50,18 +50,18 b' class TestFrontendBase(unittest.TestCase):' | |||||
50 | self.fb = FrontEndCallbackChecker(engine=EngineService()) |
|
50 | self.fb = FrontEndCallbackChecker(engine=EngineService()) | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | def test_implementsIFrontEnd(self): |
|
53 | def test_implements_IFrontEnd(self): | |
54 | assert(frontendbase.IFrontEnd.implementedBy(frontendbase.FrontEndBase)) |
|
54 | assert(frontendbase.IFrontEnd.implementedBy(frontendbase.FrontEndBase)) | |
55 |
|
55 | |||
56 |
|
56 | |||
57 |
def test_is_complete |
|
57 | def test_is_complete_returns_False_for_incomplete_block(self): | |
58 | """""" |
|
58 | """""" | |
59 |
|
59 | |||
60 | block = """def test(a):""" |
|
60 | block = """def test(a):""" | |
61 |
|
61 | |||
62 | assert(self.fb.is_complete(block) == False) |
|
62 | assert(self.fb.is_complete(block) == False) | |
63 |
|
63 | |||
64 |
def test_is_complete |
|
64 | def test_is_complete_returns_True_for_complete_block(self): | |
65 | """""" |
|
65 | """""" | |
66 |
|
66 | |||
67 | block = """def test(a): pass""" |
|
67 | block = """def test(a): pass""" | |
@@ -73,18 +73,28 b' class TestFrontendBase(unittest.TestCase):' | |||||
73 | assert(self.fb.is_complete(block)) |
|
73 | assert(self.fb.is_complete(block)) | |
74 |
|
74 | |||
75 |
|
75 | |||
76 |
def test_blockID |
|
76 | def test_blockID_added_to_result(self): | |
77 | block = """3+3""" |
|
77 | block = """3+3""" | |
78 |
|
78 | |||
79 | d = self.fb.execute(block, blockID='TEST_ID') |
|
79 | d = self.fb.execute(block, blockID='TEST_ID') | |
80 |
|
80 | |||
81 | d.addCallback(self.checkBlockID, expected='TEST_ID') |
|
81 | d.addCallback(self.checkBlockID, expected='TEST_ID') | |
82 |
|
82 | |||
|
83 | def test_blockID_added_to_failure(self): | |||
|
84 | block = "raise Exception()" | |||
|
85 | ||||
|
86 | d = self.fb.execute(block,blockID='TEST_ID') | |||
|
87 | d.addErrback(self.checkFailureID, expected='TEST_ID') | |||
|
88 | ||||
83 | def checkBlockID(self, result, expected=""): |
|
89 | def checkBlockID(self, result, expected=""): | |
84 | assert(result['blockID'] == expected) |
|
90 | assert(result['blockID'] == expected) | |
85 |
|
91 | |||
86 |
|
92 | |||
87 | def test_callbacksAddedToExecuteRequest(self): |
|
93 | def checkFailureID(self, failure, expected=""): | |
|
94 | assert(failure.blockID == expected) | |||
|
95 | ||||
|
96 | ||||
|
97 | def test_callbacks_added_to_execute(self): | |||
88 | """test that |
|
98 | """test that | |
89 | update_cell_prompt |
|
99 | update_cell_prompt | |
90 | render_result |
|
100 | render_result | |
@@ -101,7 +111,7 b' class TestFrontendBase(unittest.TestCase):' | |||||
101 | assert(self.fb.renderResultCalled) |
|
111 | assert(self.fb.renderResultCalled) | |
102 |
|
112 | |||
103 |
|
113 | |||
104 |
def test_error |
|
114 | def test_error_callback_added_to_execute(self): | |
105 | """test that render_error called on execution error""" |
|
115 | """test that render_error called on execution error""" | |
106 |
|
116 | |||
107 | d = self.fb.execute("raise Exception()") |
|
117 | d = self.fb.execute("raise Exception()") |
General Comments 0
You need to be logged in to leave comments.
Login now