[IPython-dev] Splitting inputs, cell inputs in an IPython client

Dino Viehland dinov at microsoft.com
Wed Jul 17 23:13:36 EDT 2013


We've recently noticed an issue when hosting IPython in PTVS - we split the 
inputs differently, which means when you have an input with multiple 
statements that build up a plot, we end up outputting the individual portions 
of the plot rather than one final plot at the end.

I've looked at how IPython is splitting the inputs and noticed a couple of things.  
First there's this doc string in the InputSplitter code:

        Return whether a block of interactive input can accept more input.
 
        This method is meant to be used by line-oriented frontends, who need to
        guess whether a block is complete or not based solely on prior and
        current input lines.  The InputSplitter considers it has a complete
        interactive block and will not accept more input only when either a
        SyntaxError is raised, or *all* of the following are true:
 
        1. The input compiles to a complete statement.
        
        2. The indentation level is flush-left (because if we are indented,
           like inside a function definition or for loop, we need to keep
           reading new input).
          
        3. There is one extra line consisting only of whitespace.
 
        Because of condition #3, this method should be used only by
        *line-oriented* frontends, since it means that intermediate blank lines
        are not allowed in function definitions (or any other indented block).
 
        If the current input produces a syntax error, this method immediately
        returns False but does *not* raise the syntax error exception, as
        typically clients will want to send invalid syntax to an execution
        backend which might convert the invalid syntax into valid Python via
        one of the dynamic IPython mechanisms.

Then there's this comment (*'s added for emphasis):
        # If we already have complete input and we're flush left, the answer
        # depends.  In line mode, if there hasn't been any indentation,
        # that's it. If we've come back from some indentation, we need
        # the blank final line to finish.
        # In cell mode, we need to check how many blocks the input so far
        # compiles into, because if there's already more than one full
        # independent block of input, then the client has entered full
        # 'cell' mode and is feeding lines that each is complete.  In this
        # case we should then keep accepting. The Qt terminal-like console
        # does precisely this, *to provide the convenience of terminal-like
        # input of single expressions, but allowing the user (with a
        # separate keystroke) to switch to 'cell' mode and type multiple
        # expressions in one shot*.

So my question is then - what do you think the best way to map this into 
our REPL running in VS is?  We already have logic for detecting if a statement 
is complete.  It's similar, but we never allow multiple complete statements in 
a row ('cell' mode I guess).  

We could go about supporting this a couple of different ways.  #1 is to simply 
model this behavior within PTVS.  We already have a parser, we're already 
looking for complete statements, we just need to tweak our behavior around 
rules #2 and #3.  
 
Or, option 2 we could send the text across the wire to IPython, and ask if IPython 
thinks that the input is complete.  That would allow IPython to be in charge, and if 
you evolve this behavior, or there's some way for users to provide their own line 
splitter, then we'd get the latest and greatest behavior.

Orthogonal to either of those choices is if we should expose a button somewhere 
which lets you quickly switch between 'line' and 'cell' mode, or if we should just
default to cell mode in our REPL when running in IPython mode.  And w/ approach
#2 we'd need to send the mode change over somehow too.
 
Do you guys have any thoughts on what you think we should do here?  I think #1 is 
probably actually easier to implement for us and result in a better user experience.  For 
example if the remote IPython process has become unresponsive or crashed the user 
will have a slow response time because we're querying for the complete input on the 
UI thread.  But option 2 might evolve nicer if this parsing ever changes.


Thoughts?





More information about the IPython-dev mailing list