Permalink
Browse files

Prevent crash from invalid code such as a bare 'return'.

More generally, catch any exceptions from code that may have parsed
into an AST tree but doesn't actually compile.

Closes gh-704.
  • Loading branch information...
fperez committed Aug 16, 2011
1 parent 1d09217 commit 1a64b37c5f6224b927c4b51db951c1874c7f0a82
Showing with 26 additions and 14 deletions.
  1. +26 −14 IPython/core/interactiveshell.py
@@ -2263,7 +2263,7 @@ def run_cell(self, raw_cell, store_history=True):
cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
except AliasError as e:
error(e)
- prefilter_failed=True
+ prefilter_failed = True
except Exception:
# don't allow prefilter errors to crash IPython
self.showtraceback()
@@ -2294,7 +2294,7 @@ def run_cell(self, raw_cell, store_history=True):
return None
self.run_ast_nodes(code_ast.body, cell_name,
- interactivity="last_expr")
+ interactivity="last_expr")
# Execute any registered post-execution functions.
for func, status in self._post_execute.iteritems():
@@ -2351,18 +2351,30 @@ def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr'):
raise ValueError("Interactivity was %r" % interactivity)
exec_count = self.execution_count
-
- for i, node in enumerate(to_run_exec):
- mod = ast.Module([node])
- code = self.compile(mod, cell_name, "exec")
- if self.run_code(code):
- return True
-
- for i, node in enumerate(to_run_interactive):
- mod = ast.Interactive([node])
- code = self.compile(mod, cell_name, "single")
- if self.run_code(code):
- return True
+
+ try:
+ for i, node in enumerate(to_run_exec):
+ mod = ast.Module([node])
+ code = self.compile(mod, cell_name, "exec")
+ if self.run_code(code):
+ return True
+
+ for i, node in enumerate(to_run_interactive):
+ mod = ast.Interactive([node])
+ code = self.compile(mod, cell_name, "single")
+ if self.run_code(code):
+ return True
+ except:
+ # It's possible to have exceptions raised here, typically by
+ # compilation of odd code (such as a naked 'return' outside a
+ # function) that did parse but isn't valid. Typically the exception
+ # is a SyntaxError, but it's safest just to catch anything and show
+ # the user a traceback.
+
+ # We do only one try/except outside the loop to minimize the impact
+ # on runtime, and also because if any node in the node list is
+ # broken, we should stop execution completely.
+ self.showtraceback()
return False

0 comments on commit 1a64b37

Please sign in to comment.