New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
push cell magic to the head of the transformer line #3606
Conversation
physical line transformers are run before "assemble_logical_lines", whereas logical line transformers are after: https://github.com/ipython/ipython/blob/master/IPython/core/inputsplitter.py#L633 assemble_logical_lines just joins lines according to explicit line continuations: https://github.com/ipython/ipython/blob/master/IPython/core/inputtransformer.py#L173 |
Thanks for the clarification. That is precisely the line that cell magic needed to cross, so it seems that I have done this right. |
I guess you might be breaking something like:
|
That's true. If there is a sensible way to only allow the continuation on the first line, that would be desirable. Otherwise, I think not touching the cell contents is much more important than allowing the first line to be wrapped. |
I agree that not touching cell magic contents is extremely important - it On Wed, Jul 10, 2013 at 9:07 PM, Min RK notifications@github.com wrote:
Brian E. Granger |
By the way, +1 from me as well for not touching the cell contents at all. I suppose the cell transformer itself could respect \ line continuations on the settings line. |
Can you make sure that something like this doesn't trigger the cell magic?
|
Yes, it will fall foul of the case @jasongrout mentions. There are two differences between physical and logical line transformations:
(The prompts are removed by physical line transformers, but magic transformation is done by a logical line transformer, so it doesn't see %foo. a is set to I put cell magics in logical transformations, because I think explicit line continuations are common to many languages. If we move them to physical transformations, we'll need to tweak the transformer so it only acts if the I might also put it after the prompt cleaners, so we can do something like this:
|
Is there logic to know what line in the cell you are in? Because starting a cell magic mid-cell also shouldn't work |
The transformer gets a series of lines pushed to it followed by a
|
@takluyver another peek at this one? I put it behind the prompt transformers, and it shouldn't fire unless it starts on the first line. |
It seems like quite a bit of extra complexity just to get an error message when you try to start a cell magic that's not at the beginning of a cell, but I can't see a better way to do it at the moment. There should be a test for that case, though. Other than that, I think it looks good. |
self.input_transformer_manager.push(raw_cell) | ||
cell = self.input_transformer_manager.source_reset() | ||
except UsageError: | ||
self.showtraceback() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Showing a traceback is probably unnecessary clutter for users who don't want to learn about IPython's internals. Maybe we should just print an error message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I call showtraceback because that's where we handle the shortening of UsageError (no traceback, just ERROR: message
).
If you have a better idea for how to show an error and abort, I would love to hear it. This did seem a bit wonky as I wrote it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I thought it was handled in ip.magic(). Maybe we should have a separate showusageerror() method.
Also, check what happens with that UsageError in the terminal, because the lines are fed to the InputSplitter as they're entered, before we get to run_cell, so the error will appear somewhere else. |
in terminal, I get this: In [1]: %paste
def foo():
print 'hi'
%%cellmagic
in_a_cell()
## -- End pasted text --
UsageError: Cannot call cell magics (%%cellmagic) mid-cell |
I added |
I mean, what if you actually type something in and try to start a cell magic at a |
Ah, no - it gets |
The UsageError is starting to look like a bad choice - should I just go back to letting it raise a SyntaxError? |
I undid the UsageError stuff, it was starting to get messy. Now you just get a regular SyntaxError: In [2]: def foo():
...: pass
...: %%cellmagic
File "<ipython-input-2-675fda08d994>", line 3
%%cellmagic
^
SyntaxError: invalid syntax |
Yes, I think that the simpler option is better here. |
I'm not 100% sure this is the right fix (ping @takluyver for review), since it is unclear what the physical/logical distinction is, but this does allow the cell magic transform to preempt all other transforms. closes ipython#3604
some highlighters get confused :(
for showing UsageError, rather than explicitly calling `showtraceback()` to render an exception that wants no traceback.
regular SyntaxError is raised
I agree, good to merge then? |
I might still add a test that a cell magic isn't transformed mid cell. Other than that, it looks good to me. |
mid-cell cell magic test added |
And Travis is happy, so in it goes. |
push cell magic to the head of the transformer line
push cell magic to the head of the transformer line
I'm not 100% sure this is the right fix (ping @takluyver for review), since it is unclear to me what the physical/logical distinction is.
but this does allow the cell magic transform to preempt all other transforms.
Possible alternative: put cell magic at the end of the physical line, which would enable a single use case: copy/paste of cell magic to the terminal with prompts.
closes #3604