diff --git a/IPython/core/compilerop.py b/IPython/core/compilerop.py index 3dc083c..19b5596 100644 --- a/IPython/core/compilerop.py +++ b/IPython/core/compilerop.py @@ -90,13 +90,31 @@ class CachingCompiler(codeop.Compile): # stdlib that call it outside our control go through our codepath # (otherwise we'd lose our tracebacks). linecache.checkcache = check_linecache_ipython + + + def _fix_module_ds(self, module): + """ + Starting in python 3.7 the AST for mule have changed, and if + the first expressions encountered is a string it is attached to the + `docstring` attribute of the `Module` ast node. + + This breaks IPython, as if this string is the only expression, IPython + will not return it as the result of the current cell. + """ + from ast import Str, Expr, Module, fix_missing_locations + docstring = getattr(module, 'docstring', None) + if not docstring: + return module + new_body=[Expr(Str(docstring, lineno=1, col_offset=0), lineno=1, col_offset=0)] + new_body.extend(module.body) + return fix_missing_locations(Module(new_body)) def ast_parse(self, source, filename='', symbol='exec'): """Parse code to an AST with the current compiler flags active. Arguments are exactly the same as ast.parse (in the standard library), and are passed to the built-in compile function.""" - return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1) + return self._fix_module_ds(compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)) def reset_compiler_flags(self): """Reset compiler flags to default state.""" diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index ff450ce..4593c6b 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -2865,7 +2865,6 @@ class InteractiveShell(SingletonConfigurable): """ if not nodelist: return - if interactivity == 'last_expr_or_assign': if isinstance(nodelist[-1], _assign_nodes): asg = nodelist[-1] @@ -2895,7 +2894,6 @@ class InteractiveShell(SingletonConfigurable): to_run_exec, to_run_interactive = [], nodelist else: raise ValueError("Interactivity was %r" % interactivity) - try: for i, node in enumerate(to_run_exec): mod = ast.Module([node])