def _process_source( source: str, command: str, magic_substitutions: List[MagicHandler], *, skip_bad_cells: bool, ) -> str: """Temporarily replace ipython magics - don't process if can't.""" try: ast.parse(source) except SyntaxError: pass else: # Source has no IPython magic, return it directly return source body = TransformerManager().transform_cell(source) if len(body.splitlines()) != len(source.splitlines()): handler = MagicHandler(source, command, magic_type=None) magic_substitutions.append(handler) return handler.replacement try: tree = ast.parse(body) except SyntaxError: if skip_bad_cells: handler = MagicHandler(source, command, magic_type=None) magic_substitutions.append(handler) return handler.replacement return source system_assigns_finder = SystemAssignsFinder() system_assigns_finder.visit(tree) visitor = Visitor(system_assigns_finder.system_assigns) visitor.visit(tree) new_src = [] for i, line in enumerate(body.splitlines(), start=1): if i in visitor.magics: col_offset, src, magic_type = visitor.magics[i][0] if src is None or len(visitor.magics[i]) > 1: # unusual case - skip cell completely for now handler = MagicHandler(source, command, magic_type=magic_type) magic_substitutions.append(handler) return handler.replacement handler = MagicHandler( src, command, magic_type=magic_type, ) magic_substitutions.append(handler) line = line[:col_offset] + handler.replacement new_src.append(line) return "\n" * (len(source) - len(source.lstrip("\n"))) + "\n".join(new_src)
def _process_source(source: str) -> str: """Temporarily replace ipython magics - don't process if can't.""" try: ast.parse(source) except SyntaxError: pass else: # Source has no IPython magic, return it directly return source body = TransformerManager().transform_cell(source) try: tree = ast.parse(body) except SyntaxError: return source visitor = Visitor() visitor.visit(tree) new_src = [] for i, line in enumerate(body.splitlines(), start=1): if i in visitor.magics: col_offset, src, magic_type = visitor.magics[i][0] if (src is None or line[:col_offset].strip() or len(visitor.magics[i]) > 1): # unusual case - skip cell completely for now handler = NewMagicHandler(source, command, magic_type=magic_type) magic_substitutions.append(handler) return handler.replacement handler = NewMagicHandler( src, command, magic_type=magic_type, ) magic_substitutions.append(handler) line = line[:col_offset] + handler.replacement new_src.append(line) leading_newlines = len(source) - len(source.lstrip("\n")) return "\n" * leading_newlines + "\n".join(new_src)
def default(self, line): """ Default way of running pdb statment. The only difference with Pdb.default is that if line contains multiple statments, the code will be compiled with 'exec'. It will not print the result but will run without failing. """ execute_events = self.pdb_execute_events if line[:1] == '!': line = line[1:] elif self.pdb_use_exclamation_mark: self.print_exclamation_warning() self.error("Unknown command '" + line.split()[0] + "'") return # Disallow the use of %debug magic in the debugger if line.startswith("%debug"): self.error("Please don't use '%debug' in the debugger.\n" "For a recursive debugger, use the pdb 'debug'" " command instead") return locals = self.curframe_locals globals = self.curframe.f_globals if self.pdb_use_exclamation_mark: # Find pdb commands executed without ! cmd, arg, line = self.parseline(line) if cmd: cmd_in_namespace = (cmd in globals or cmd in locals or cmd in builtins.__dict__) # Special case for quit and exit if cmd in ("quit", "exit"): if cmd in globals and isinstance(globals[cmd], ZMQExitAutocall): # Use the pdb call cmd_in_namespace = False cmd_func = getattr(self, 'do_' + cmd, None) is_pdb_cmd = cmd_func is not None # Look for assignment is_assignment = False try: for node in ast.walk(ast.parse(line)): if isinstance(node, ast.Assign): is_assignment = True break except SyntaxError: pass if is_pdb_cmd: if not cmd_in_namespace and not is_assignment: # This is a pdb command without the '!' prefix. self.lastcmd = line return cmd_func(arg) else: # The pdb command is masked by something self.print_exclamation_warning() try: line = TransformerManager().transform_cell(line) save_stdout = sys.stdout save_stdin = sys.stdin save_displayhook = sys.displayhook try: sys.stdin = self.stdin sys.stdout = self.stdout sys.displayhook = self.displayhook if execute_events: get_ipython().events.trigger('pre_execute') if locals is not globals: # Mitigates a behaviour of CPython that makes it difficult # to work with exec and the local namespace # See: # - https://bugs.python.org/issue41918 # - https://bugs.python.org/issue46153 # - https://bugs.python.org/issue21161 # - spyder-ide/spyder#13909 # - spyder-ide/spyder-kernels#345 # # The idea here is that the best way to emulate being in a # function is to actually execute the code in a function. # A function called `_spyderpdb_code` is created and # called. It will first load the locals, execute the code, # and then update the locals. # # One limitation of this approach is that locals() is only # a copy of the curframe locals. This means that closures # for example are early binding instead of late binding. # Check if line is an expression to print print_ret = False try: code = ast.parse(line + '\n', '<stdin>', 'single') if len(code.body) == 1: print_ret = isinstance(code.body[0], ast.Expr) except SyntaxError: pass # Create a function and load the locals globals["_spyderpdb_locals"] = locals # Save builtins locals in case it is shadowed globals["_spyderpdb_builtins_locals"] = builtins.locals indent = " " code = ["def _spyderpdb_code():"] # Load locals if they have a valid name # In comprehensions, locals could contain ".0" for example code += [ indent + "{k} = _spyderpdb_locals['{k}']".format(k=k) for k in locals if isidentifier(k) ] # Run the code if print_ret: code += [indent + 'print(' + line.strip() + ")"] else: code += [indent + l for l in line.splitlines()] # Update the locals code += [ indent + "_spyderpdb_locals.update(" "_spyderpdb_builtins_locals())" ] # Run the function code += ["_spyderpdb_code()"] code = compile('\n'.join(code) + '\n', '<stdin>', 'exec') try: exec(code, globals) finally: globals.pop("_spyderpdb_locals", None) globals.pop("_spyderpdb_code", None) globals.pop("_spyderpdb_builtins_locals", None) else: try: code = compile(line + '\n', '<stdin>', 'single') except SyntaxError: # Support multiline statments code = compile(line + '\n', '<stdin>', 'exec') exec(code, globals) finally: if execute_events: get_ipython().events.trigger('post_execute') sys.stdout = save_stdout sys.stdin = save_stdin sys.displayhook = save_displayhook except BaseException: if PY2: t, v = sys.exc_info()[:2] if type(t) == type(''): exc_type_name = t else: exc_type_name = t.__name__ print >> self.stdout, '***', exc_type_name + ':', v else: exc_info = sys.exc_info()[:2] self.error( traceback.format_exception_only(*exc_info)[-1].strip())