diff --git a/IPython/frontend/cocoa/cocoa_frontend.py b/IPython/frontend/cocoa/cocoa_frontend.py index b366905..a713a2e 100644 --- a/IPython/frontend/cocoa/cocoa_frontend.py +++ b/IPython/frontend/cocoa/cocoa_frontend.py @@ -40,7 +40,7 @@ from pprint import saferepr import IPython from IPython.kernel.engineservice import ThreadedEngineService -from IPython.frontend.frontendbase import FrontEndBase +from IPython.frontend.frontendbase import AsynchronousFrontEndBase from twisted.internet.threads import blockingCallFromThread from twisted.python.failure import Failure @@ -96,14 +96,14 @@ class AutoreleasePoolWrappedThreadedEngineService(ThreadedEngineService): return d -class IPythonCocoaController(NSObject, FrontEndBase): +class IPythonCocoaController(NSObject, AsynchronousFrontEndBase): userNS = objc.ivar() #mirror of engine.user_ns (key=>str(value)) waitingForEngine = objc.ivar().bool() textView = objc.IBOutlet() def init(self): self = super(IPythonCocoaController, self).init() - FrontEndBase.__init__(self, + AsynchronousFrontEndBase.__init__(self, engine=AutoreleasePoolWrappedThreadedEngineService()) if(self != None): self._common_init() diff --git a/IPython/frontend/frontendbase.py b/IPython/frontend/frontendbase.py index 9a3b10e..87e7ac2 100644 --- a/IPython/frontend/frontendbase.py +++ b/IPython/frontend/frontendbase.py @@ -159,9 +159,6 @@ class FrontEndBase(object): - How do we handle completions? """ - zi.implements(IFrontEnd) - zi.classProvides(IFrontEndFactory) - history_cursor = 0 current_indent_level = 0 @@ -248,23 +245,7 @@ class FrontEndBase(object): Deferred result of self.interpreter.execute """ - if(not self.is_complete(block)): - return Failure(Exception("Block is not compilable")) - - if(blockID == None): - blockID = uuid.uuid4() #random UUID - - d = self.engine.execute(block) - d.addCallback(self._add_history, block=block) - d.addCallbacks(self._add_block_id_for_result, - errback=self._add_block_id_for_failure, - callbackArgs=(blockID,), - errbackArgs=(blockID,)) - d.addBoth(self.update_cell_prompt, blockID=blockID) - d.addCallbacks(self.render_result, - errback=self.render_error) - - return d + pass def _add_block_id_for_result(self, result, blockID): @@ -347,3 +328,44 @@ class FrontEndBase(object): +class AsynchronousFrontEndBase(FrontEndBase): + """ + Overrides FrontEndBase to wrap execute in a deferred result. + All callbacks are made as callbacks on the deferred result. + """ + + zi.implements(IFrontEnd) + zi.classProvides(IFrontEndFactory) + + def execute(self, block, blockID=None): + """Execute the block and return the deferred result. + + Parameters: + block : {str, AST} + blockID : any + Caller may provide an ID to identify this block. + result['blockID'] := blockID + + Result: + Deferred result of self.interpreter.execute + """ + + if(not self.is_complete(block)): + return Failure(Exception("Block is not compilable")) + + if(blockID == None): + blockID = uuid.uuid4() #random UUID + + d = self.engine.execute(block) + d.addCallback(self._add_history, block=block) + d.addCallbacks(self._add_block_id_for_result, + errback=self._add_block_id_for_failure, + callbackArgs=(blockID,), + errbackArgs=(blockID,)) + d.addBoth(self.update_cell_prompt, blockID=blockID) + d.addCallbacks(self.render_result, + errback=self.render_error) + + return d + + diff --git a/IPython/frontend/tests/test_frontendbase.py b/IPython/frontend/tests/test_frontendbase.py index ff68b6c..1498036 100644 --- a/IPython/frontend/tests/test_frontendbase.py +++ b/IPython/frontend/tests/test_frontendbase.py @@ -19,7 +19,7 @@ import unittest from IPython.frontend import frontendbase from IPython.kernel.engineservice import EngineService -class FrontEndCallbackChecker(frontendbase.FrontEndBase): +class FrontEndCallbackChecker(frontendbase.AsynchronousFrontEndBase): """FrontEndBase subclass for checking callbacks""" def __init__(self, engine=None, history=None): super(FrontEndCallbackChecker, self).__init__(engine=engine, @@ -44,7 +44,7 @@ class FrontEndCallbackChecker(frontendbase.FrontEndBase): -class TestFrontendBase(unittest.TestCase): +class TestAsynchronousFrontendBase(unittest.TestCase): def setUp(self): """Setup the EngineService and FrontEndBase""" @@ -53,7 +53,7 @@ class TestFrontendBase(unittest.TestCase): def test_implements_IFrontEnd(self): assert(frontendbase.IFrontEnd.implementedBy( - frontendbase.FrontEndBase)) + frontendbase.AsynchronousFrontEndBase)) def test_is_complete_returns_False_for_incomplete_block(self):