Example #1
0
 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
Example #2
0
 def __init__(self, shell=None, history=None):
     self.shell = shell
     if history is None:
         self.history = FrontEndHistory(input_cache=[''])
     else:
         self.history = history
Example #3
0
 def __init__(self, shell=None, history=None):
     self.shell = shell
     if history is None:
             self.history = FrontEndHistory(input_cache=[''])
     else:
         self.history = history
Example #4
0
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
Example #5
0
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