Show More
@@ -40,7 +40,7 b' from pprint import saferepr' | |||
|
40 | 40 | |
|
41 | 41 | import IPython |
|
42 | 42 | from IPython.kernel.engineservice import ThreadedEngineService |
|
43 | from IPython.frontend.frontendbase import FrontEndBase | |
|
43 | from IPython.frontend.frontendbase import AsynchronousFrontEndBase | |
|
44 | 44 | |
|
45 | 45 | from twisted.internet.threads import blockingCallFromThread |
|
46 | 46 | from twisted.python.failure import Failure |
@@ -96,14 +96,14 b' class AutoreleasePoolWrappedThreadedEngineService(ThreadedEngineService):' | |||
|
96 | 96 | return d |
|
97 | 97 | |
|
98 | 98 | |
|
99 | class IPythonCocoaController(NSObject, FrontEndBase): | |
|
99 | class IPythonCocoaController(NSObject, AsynchronousFrontEndBase): | |
|
100 | 100 | userNS = objc.ivar() #mirror of engine.user_ns (key=>str(value)) |
|
101 | 101 | waitingForEngine = objc.ivar().bool() |
|
102 | 102 | textView = objc.IBOutlet() |
|
103 | 103 | |
|
104 | 104 | def init(self): |
|
105 | 105 | self = super(IPythonCocoaController, self).init() |
|
106 | FrontEndBase.__init__(self, | |
|
106 | AsynchronousFrontEndBase.__init__(self, | |
|
107 | 107 | engine=AutoreleasePoolWrappedThreadedEngineService()) |
|
108 | 108 | if(self != None): |
|
109 | 109 | self._common_init() |
@@ -159,9 +159,6 b' class FrontEndBase(object):' | |||
|
159 | 159 | - How do we handle completions? |
|
160 | 160 | """ |
|
161 | 161 | |
|
162 | zi.implements(IFrontEnd) | |
|
163 | zi.classProvides(IFrontEndFactory) | |
|
164 | ||
|
165 | 162 | history_cursor = 0 |
|
166 | 163 | |
|
167 | 164 | current_indent_level = 0 |
@@ -248,23 +245,7 b' class FrontEndBase(object):' | |||
|
248 | 245 | Deferred result of self.interpreter.execute |
|
249 | 246 | """ |
|
250 | 247 | |
|
251 | if(not self.is_complete(block)): | |
|
252 | return Failure(Exception("Block is not compilable")) | |
|
253 | ||
|
254 | if(blockID == None): | |
|
255 | blockID = uuid.uuid4() #random UUID | |
|
256 | ||
|
257 | d = self.engine.execute(block) | |
|
258 | d.addCallback(self._add_history, block=block) | |
|
259 | d.addCallbacks(self._add_block_id_for_result, | |
|
260 | errback=self._add_block_id_for_failure, | |
|
261 | callbackArgs=(blockID,), | |
|
262 | errbackArgs=(blockID,)) | |
|
263 | d.addBoth(self.update_cell_prompt, blockID=blockID) | |
|
264 | d.addCallbacks(self.render_result, | |
|
265 | errback=self.render_error) | |
|
266 | ||
|
267 | return d | |
|
248 | pass | |
|
268 | 249 | |
|
269 | 250 | |
|
270 | 251 | def _add_block_id_for_result(self, result, blockID): |
@@ -347,3 +328,44 b' class FrontEndBase(object):' | |||
|
347 | 328 | |
|
348 | 329 | |
|
349 | 330 | |
|
331 | class AsynchronousFrontEndBase(FrontEndBase): | |
|
332 | """ | |
|
333 | Overrides FrontEndBase to wrap execute in a deferred result. | |
|
334 | All callbacks are made as callbacks on the deferred result. | |
|
335 | """ | |
|
336 | ||
|
337 | zi.implements(IFrontEnd) | |
|
338 | zi.classProvides(IFrontEndFactory) | |
|
339 | ||
|
340 | def execute(self, block, blockID=None): | |
|
341 | """Execute the block and return the deferred result. | |
|
342 | ||
|
343 | Parameters: | |
|
344 | block : {str, AST} | |
|
345 | blockID : any | |
|
346 | Caller may provide an ID to identify this block. | |
|
347 | result['blockID'] := blockID | |
|
348 | ||
|
349 | Result: | |
|
350 | Deferred result of self.interpreter.execute | |
|
351 | """ | |
|
352 | ||
|
353 | if(not self.is_complete(block)): | |
|
354 | return Failure(Exception("Block is not compilable")) | |
|
355 | ||
|
356 | if(blockID == None): | |
|
357 | blockID = uuid.uuid4() #random UUID | |
|
358 | ||
|
359 | d = self.engine.execute(block) | |
|
360 | d.addCallback(self._add_history, block=block) | |
|
361 | d.addCallbacks(self._add_block_id_for_result, | |
|
362 | errback=self._add_block_id_for_failure, | |
|
363 | callbackArgs=(blockID,), | |
|
364 | errbackArgs=(blockID,)) | |
|
365 | d.addBoth(self.update_cell_prompt, blockID=blockID) | |
|
366 | d.addCallbacks(self.render_result, | |
|
367 | errback=self.render_error) | |
|
368 | ||
|
369 | return d | |
|
370 | ||
|
371 |
@@ -19,7 +19,7 b' import unittest' | |||
|
19 | 19 | from IPython.frontend import frontendbase |
|
20 | 20 | from IPython.kernel.engineservice import EngineService |
|
21 | 21 | |
|
22 | class FrontEndCallbackChecker(frontendbase.FrontEndBase): | |
|
22 | class FrontEndCallbackChecker(frontendbase.AsynchronousFrontEndBase): | |
|
23 | 23 | """FrontEndBase subclass for checking callbacks""" |
|
24 | 24 | def __init__(self, engine=None, history=None): |
|
25 | 25 | super(FrontEndCallbackChecker, self).__init__(engine=engine, |
@@ -44,7 +44,7 b' class FrontEndCallbackChecker(frontendbase.FrontEndBase):' | |||
|
44 | 44 | |
|
45 | 45 | |
|
46 | 46 | |
|
47 | class TestFrontendBase(unittest.TestCase): | |
|
47 | class TestAsynchronousFrontendBase(unittest.TestCase): | |
|
48 | 48 | def setUp(self): |
|
49 | 49 | """Setup the EngineService and FrontEndBase""" |
|
50 | 50 | |
@@ -53,7 +53,7 b' class TestFrontendBase(unittest.TestCase):' | |||
|
53 | 53 | |
|
54 | 54 | def test_implements_IFrontEnd(self): |
|
55 | 55 | assert(frontendbase.IFrontEnd.implementedBy( |
|
56 |
|
|
|
56 | frontendbase.AsynchronousFrontEndBase)) | |
|
57 | 57 | |
|
58 | 58 | |
|
59 | 59 | def test_is_complete_returns_False_for_incomplete_block(self): |
General Comments 0
You need to be logged in to leave comments.
Login now