Improved handling for when you paste "continue", "break", or "return" control flow statements into IPython

Not sure if this is the right place, but I have an idea for a feature that I think would improve IPython / Jupyter.

Use Case:

Often when I copy paste code from a .py file into an IPython terminal it is code that exists in a loop. E.g.

            loop_body_setup(data)
            if condition(data, idx):
                continue
            loop_body_main_case(data)

but if I paste that into IPython, it fails to parse because it isn’t valid Python, and it gives a SyntaxError.

This also happens when the continue is replaced by other control flow statements like break or return _.

But, it’s pretty close to valid Python, and if we have the variables “idx” and “data” in our IPython namespace, and we want to debug what happens in the body, we have to modify the code before we paste it into IPython. That’s kinda annoying. I’ve also found it encourages me to write roundabout code like

        for idx in range(10):
            loop_body_setup(data)
            if condition(data, idx):
                ...
            else:
                loop_body_main_case(data)

to avoid syntax errors. But this code smells, and I think:

        for idx in range(10):
            loop_body_setup(data)
            if condition(data, idx):
                continue
            loop_body_main_case(data)

is just better. But to use nicer code like this in IPython I need to piece-wise copy/paste it. Or, recently I’ve been replacing the continue with a raise Exception, which forshadows the proposed solution.

Proposal

Notice that for each control flow statement the body of the loop stops, so what if IPython is sneaky. What if when the user pastes in code like that and it catches a SyntaxError, then it replaces the control flow statement with raise Exception('original control flow statement').

That will let the user modify the current IPython state just as a loop or function body would. If it hits the control flow statement, an error is raised and IPython’s current cell execution stops. The user can also notified of which control flow statement was hit by passing that information to the inserted Exception.

(As a side-note, this could be built into the Python language and its implementations, but it seems like IPython would be a good place to test its mettle.)

Thoughts?

just no, because it would implicate ipython could run broken python code.

You definitely don’t want iPython to be able to run invalid code.

But I don’t understand what’s wrong with this code:

for idx in range(10):
       loop_body_setup(data)
       if condition(data, idx):
           continue
       loop_body_main_case(data)

It will run just fine.

@defjaf: yeah he wants to run the code without the for loop declared.

@erotemic:
i still try to avoid continue, break and finally in loops altogether because it keeps things flexible.

loop_body_setup(data)
if not condition(data, idx):
    loop_body_main_case(data)

and not capturing return out of function declaration as a syntax error could bring serious problems with it.

IPython already runs “broken” Python code.

Paste:

>>> print('hello world') 

into IPython, versus run it in a .py file. Or give everything leading indentation, same thing. There is already precedent for IPython munging its inputs.

I think I’ve been deluding myself into thinking that using continue or break is somehow undesirable just because I can’t use that code outside of a loop body. The problem is really the ergonomics of it, and IPython could improve that.

I suspect you could write a %%magic or even a jupyter extension that could do something like this for you.

1 Like

didn’t know that ipython masks out the default prompt chars, interesting.
imo it shouldn’t run that, but it is not as severe as changing things up.

and i totally agree with defjaf: an ipython magic command is a good idea to implement this.

1 Like

Would such a magic be able to be run once, and then modify the behavior on receiving a pasted block of text? If so then an extension seems like the right place for this.

The main thing is I want to copy/paste without any other overhead to keep the workflow as smooth as possible.

I’m surprised at the negative response, I would have thought other people would be copy/pasting into IPython and recognize this use-case as a potential improvement.

If you want something like that you can use input transformations that you’d define at the top of your IPython session or running .ipynb file.
I have a basic example here of using input transformations to detect text being entered and then alters it behind-the-scenes and makes the output as if the altered version was the input code.
Obviously, yours would be more complex, but I think it is the direction you want to go.

2 Likes