Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Multiline input push #372

Merged
merged 2 commits into from

2 participants

@takluyver
Owner

To see this bug, start a Qt console and enter something like this (just using the return key, not ctrl-return):

if True:
    a = 1
b = [1,

(at this point, you get a SyntaxError).

The trouble is codeop.CommandCompiler, the tool we use in inputsplitter to distinguish a syntax error from an incomplete cell. By default, it compiles in "single" mode, which doesn't work properly with multiple statements. This patch uses "exec" mode instead.

The documentation for codeop says that only "single" and "eval" are valid arguments, but a look at the code reveals that the argument is ultimately just passed to compile, and using "exec" works with everything I've tried throwing at it. I guess it was invalid in older versions, and the documentation hasn't been updated (the docs for codeop describe backwards compatibility with Python 2.1).

There is also a test (which fails without the patch).

@fperez
Owner

Looks good to me, go for it. Thanks!

@takluyver takluyver merged commit e55836e into ipython:master
@damianavila damianavila referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
2  IPython/core/inputsplitter.py
@@ -310,7 +310,7 @@ def push(self, lines):
self._update_indent(lines)
try:
- self.code = self._compile(source)
+ self.code = self._compile(source, symbol="exec")
# Invalid syntax can produce any of a number of different errors from
# inside the compiler, so we have to catch them all. Syntax errors
# immediately produce a 'ready' block, so the invalid Python can be
View
6 IPython/core/tests/test_inputsplitter.py
@@ -238,6 +238,12 @@ def test_push2(self):
for line in [' x=1', '# a comment', ' y=2']:
self.assertTrue(isp.push(line))
+ def test_push3(self):
+ isp = self.isp
+ isp.push('if True:')
+ isp.push(' a = 1')
+ self.assertFalse(isp.push('b = [1,'))
+
def test_replace_mode(self):
isp = self.isp
isp.input_mode = 'cell'
Something went wrong with that request. Please try again.