def __init__(self, engine=None, history=None): assert (engine == None or IEngineCore.providedBy(engine)) self.engine = IEngineCore(engine) if history is None: self.history = FrontEndHistory(input_cache=['']) else: self.history = history
def __init__(self, shell=None, history=None): self.shell = shell if history is None: self.history = FrontEndHistory(input_cache=['']) else: self.history = history
class FrontEndBase(object): """ FrontEndBase manages the state tasks for a CLI frontend: - Input and output history management - Input/continuation and output prompt generation Some issues (due to possibly unavailable engine): - How do we get the current cell number for the engine? - How do we handle completions? """ history_cursor = 0 input_prompt_template = string.Template(rc.prompt_in1) output_prompt_template = string.Template(rc.prompt_out) continuation_prompt_template = string.Template(rc.prompt_in2) def __init__(self, shell=None, history=None): self.shell = shell if history is None: self.history = FrontEndHistory(input_cache=['']) else: self.history = history def input_prompt(self, number=''): """Returns the current input prompt It would be great to use ipython1.core.prompts.Prompt1 here """ return self.input_prompt_template.safe_substitute({'number':number}) def continuation_prompt(self): """Returns the current continuation prompt""" return self.continuation_prompt_template.safe_substitute() def output_prompt(self, number=''): """Returns the output prompt for result""" return self.output_prompt_template.safe_substitute({'number':number}) def is_complete(self, block): """Determine if block is complete. Parameters block : string Result True if block can be sent to the engine without compile errors. False otherwise. """ try: is_complete = codeop.compile_command(block.rstrip() + '\n\n', "<string>", "exec") except: return False lines = block.split('\n') return ((is_complete is not None) and (len(lines)==1 or str(lines[-1])=='')) def execute(self, block, blockID=None): """Execute the block and return the 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)): raise Exception("Block is not compilable") if(blockID == None): blockID = uuid.uuid4() try: result = self.shell.execute(block) except Exception as e: e = self._add_block_id_for_failure(e, blockID=blockID) e = self.update_cell_prompt(e, blockID=blockID) e = self.render_error(e) else: result = self._add_block_id_for_result(result, blockID=blockID) result = self.update_cell_prompt(result, blockID=blockID) result = self.render_result(result) return result def _add_block_id_for_result(self, result, blockID): """Add the blockID to result or failure. Unfortunatley, we have to treat failures differently than result dicts. """ result['blockID'] = blockID return result def _add_block_id_for_failure(self, failure, blockID): """_add_block_id_for_failure""" failure.blockID = blockID return failure def _add_history(self, result, block=None): """Add block to the history""" assert(block != None) self.history.add_items([block]) self.history_cursor += 1 return result def get_history_previous(self, current_block): """ Returns previous history string and decrement history cursor. """ command = self.history.get_history_item(self.history_cursor - 1) if command is not None: if(self.history_cursor+1 == len(self.history.input_cache)): self.history.input_cache[self.history_cursor] = current_block self.history_cursor -= 1 return command def get_history_next(self): """ Returns next history string and increment history cursor. """ command = self.history.get_history_item(self.history_cursor+1) if command is not None: self.history_cursor += 1 return command ### # Subclasses probably want to override these methods... ### def update_cell_prompt(self, result, blockID=None): """Subclass may override to update the input prompt for a block. This method only really makes sens in asyncrhonous frontend. Since this method will be called as a twisted.internet.defer.Deferred's callback, implementations should return result when finished. """ raise NotImplementedError def render_result(self, result): """Subclasses must override to render result. In asynchronous frontends, this method will be called as a twisted.internet.defer.Deferred's callback. Implementations should thus return result when finished. """ raise NotImplementedError def render_error(self, failure): """Subclasses must override to render the failure. In asynchronous frontends, this method will be called as a twisted.internet.defer.Deferred's callback. Implementations should thus return result when finished. """ raise NotImplementedError
class FrontEndBase(object): """ FrontEndBase manages the state tasks for a CLI frontend: - Input and output history management - Input/continuation and output prompt generation Some issues (due to possibly unavailable engine): - How do we get the current cell number for the engine? - How do we handle completions? """ history_cursor = 0 input_prompt_template = string.Template(rc.prompt_in1) output_prompt_template = string.Template(rc.prompt_out) continuation_prompt_template = string.Template(rc.prompt_in2) def __init__(self, shell=None, history=None): self.shell = shell if history is None: self.history = FrontEndHistory(input_cache=['']) else: self.history = history def input_prompt(self, number=''): """Returns the current input prompt It would be great to use ipython1.core.prompts.Prompt1 here """ return self.input_prompt_template.safe_substitute({'number': number}) def continuation_prompt(self): """Returns the current continuation prompt""" return self.continuation_prompt_template.safe_substitute() def output_prompt(self, number=''): """Returns the output prompt for result""" return self.output_prompt_template.safe_substitute({'number': number}) def is_complete(self, block): """Determine if block is complete. Parameters block : string Result True if block can be sent to the engine without compile errors. False otherwise. """ try: is_complete = codeop.compile_command(block.rstrip() + '\n\n', "<string>", "exec") except: return False lines = block.split('\n') return ((is_complete is not None) and (len(lines) == 1 or str(lines[-1]) == '')) def execute(self, block, blockID=None): """Execute the block and return the 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)): raise Exception("Block is not compilable") if (blockID == None): blockID = uuid.uuid4() try: result = self.shell.execute(block) except Exception as e: e = self._add_block_id_for_failure(e, blockID=blockID) e = self.update_cell_prompt(e, blockID=blockID) e = self.render_error(e) else: result = self._add_block_id_for_result(result, blockID=blockID) result = self.update_cell_prompt(result, blockID=blockID) result = self.render_result(result) return result def _add_block_id_for_result(self, result, blockID): """Add the blockID to result or failure. Unfortunatley, we have to treat failures differently than result dicts. """ result['blockID'] = blockID return result def _add_block_id_for_failure(self, failure, blockID): """_add_block_id_for_failure""" failure.blockID = blockID return failure def _add_history(self, result, block=None): """Add block to the history""" assert (block != None) self.history.add_items([block]) self.history_cursor += 1 return result def get_history_previous(self, current_block): """ Returns previous history string and decrement history cursor. """ command = self.history.get_history_item(self.history_cursor - 1) if command is not None: if (self.history_cursor + 1 == len(self.history.input_cache)): self.history.input_cache[self.history_cursor] = current_block self.history_cursor -= 1 return command def get_history_next(self): """ Returns next history string and increment history cursor. """ command = self.history.get_history_item(self.history_cursor + 1) if command is not None: self.history_cursor += 1 return command ### # Subclasses probably want to override these methods... ### def update_cell_prompt(self, result, blockID=None): """Subclass may override to update the input prompt for a block. This method only really makes sens in asyncrhonous frontend. Since this method will be called as a twisted.internet.defer.Deferred's callback, implementations should return result when finished. """ raise NotImplementedError def render_result(self, result): """Subclasses must override to render result. In asynchronous frontends, this method will be called as a twisted.internet.defer.Deferred's callback. Implementations should thus return result when finished. """ raise NotImplementedError def render_error(self, failure): """Subclasses must override to render the failure. In asynchronous frontends, this method will be called as a twisted.internet.defer.Deferred's callback. Implementations should thus return result when finished. """ raise NotImplementedError