예제 #1
0
def exec_code(code, filename, ns_globals, ns_locals=None):
    """Execute code and display any exception."""
    if PY2:
        filename = encode(filename)
        code = encode(code)

    ipython_shell = get_ipython()
    is_ipython = os.path.splitext(filename)[1] == '.ipy'
    try:
        if is_ipython:
            # transform code
            tm = TransformerManager()
            if not PY2:
                # Avoid removing lines
                tm.cleanup_transforms = []
            code = tm.transform_cell(code)
        exec(compile(code, filename, 'exec'), ns_globals, ns_locals)
    except SystemExit as status:
        # ignore exit(0)
        if status.code:
            ipython_shell.showtraceback(exception_only=True)
    except BaseException as error:
        if (isinstance(error, bdb.BdbQuit) and ipython_shell.kernel._pdb_obj):
            # Ignore BdbQuit if we are debugging, as it is expected.
            ipython_shell.kernel._pdb_obj = None
        else:
            # We ignore the call to exec
            ipython_shell.showtraceback(tb_offset=1)
예제 #2
0
def transform_cell(code):
    """Transform ipython code to python code."""
    tm = TransformerManager()
    number_empty_lines = count_leading_empty_lines(code)
    code = tm.transform_cell(code)
    if PY2:
        return code
    return '\n' * number_empty_lines + code
예제 #3
0
 def _is_pdb_complete(self, source):
     """
     Check if the pdb input is ready to be executed.
     """
     if source and source[0] == '!':
         source = source[1:]
     tm = TransformerManager()
     complete, indent = tm.check_complete(source)
     if indent is not None:
         indent = indent * ' '
     return complete != 'incomplete', indent
예제 #4
0
def transform_cell(code, indent_only=False):
    """Transform IPython code to Python code."""
    number_empty_lines = count_leading_empty_lines(code)
    if indent_only:
        if not code.endswith('\n'):
            code += '\n'  # Ensure the cell has a trailing newline
        lines = code.splitlines(keepends=True)
        lines = leading_indent(leading_empty_lines(lines))
        code = ''.join(lines)
    else:
        tm = TransformerManager()
        code = tm.transform_cell(code)
    return '\n' * number_empty_lines + code
예제 #5
0
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)
예제 #6
0
    def get_ipython_magic_type(
            ipython_magic: str) -> Optional[IPythonMagicType]:
        """Return the type of ipython magic.

        This function assumes the input parameter to be a ipython magic. It is
        recommended to call this method after checking `is_ipython_magic`.

        Parameters
        ----------
        ipython_magic : str
            Ipython magic statement

        Returns
        -------
        Optional[IPythonMagicType]
            Type of the IPython magic
        """
        python_code = TransformerManager().transform_cell(ipython_magic)
        magic_type: Optional[IPythonMagicType] = None
        for magic, prefixes in MagicHandler._MAGIC_PREFIXES.items():
            if any(prefix in python_code for prefix in prefixes):
                magic_type = magic
                break
        else:
            magic_type = IPythonMagicType.NO_MAGIC

        return magic_type
예제 #7
0
def ipython2python(code):
    """Transform IPython syntax to pure Python syntax

    Parameters
    ----------
    code : str
        IPython code, to be transformed to pure Python
    """
    try:
        from IPython.core.inputtransformer2 import TransformerManager
    except ImportError:
        warnings.warn(
            "IPython is needed to transform IPython syntax to pure Python."
            " Install ipython if you need this functionality."
        )
        return code
    else:
        isp = TransformerManager()
        return isp.transform_cell(code)
예제 #8
0
def find_imports(path):
    from IPython.core.inputtransformer2 import TransformerManager

    tm = TransformerManager()
    collector = ImportCollector()
    for nb_file in pathlib.Path(path).glob("**/*.ipynb"):
        with nb_file.open("r") as f:
            nb = nbformat.read(f, as_version=4)
        for cell in nb.cells:
            if cell.cell_type == "code":
                source = tm.transform_cell(cell.source)
                try:
                    node = ast.parse(source)
                except SyntaxError:
                    # invalid cell
                    # e.g. cell with magics
                    pass
                else:
                    collector.visit(node)

    for py_file in pathlib.Path(path).glob("**/*.py"):
        with py_file.open("r") as f:
            source = f.read()
            try:
                node = ast.parse(source)
            except SyntaxError:
                # invalid cell
                # e.g. cell with magics
                pass
            else:
                collector.visit(node)

    print("All counts")
    pprint(collector.imports)
    print("Top-level packages")
    for mod, count in sorted(
            collector.imports.items(),
            key=lambda x: (x[1], len(x[0]), x[0]),
            reverse=True,
    ):
        if "." not in mod:
            print(f"{mod:20}: {count:3}")
예제 #9
0
파일: spyderpdb.py 프로젝트: leogott/spyder
    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:]
        # 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
        try:
            line = TransformerManager().transform_cell(line)
            try:
                code = compile(line + '\n', '<stdin>', 'single')
            except SyntaxError:
                # support multiline statments
                code = compile(line + '\n', '<stdin>', 'exec')
            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')
                exec(code, globals, locals)
                if execute_events:
                     get_ipython().events.trigger('post_execute')
            finally:
                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())
예제 #10
0
 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)
예제 #11
0
def mask_cell(src: str) -> Tuple[str, List[Replacement]]:
    """Mask IPython magics so content becomes parseable Python code.

    For example,

        %matplotlib inline
        'foo'

    becomes

        "25716f358c32750e"
        'foo'

    The replacements are returned, along with the transformed code.
    """
    replacements: List[Replacement] = []
    try:
        ast.parse(src)
    except SyntaxError:
        # Might have IPython magics, will process below.
        pass
    else:
        # Syntax is fine, nothing to mask, early return.
        return src, replacements

    from IPython.core.inputtransformer2 import TransformerManager

    transformer_manager = TransformerManager()
    transformed = transformer_manager.transform_cell(src)
    transformed, cell_magic_replacements = replace_cell_magics(transformed)
    replacements += cell_magic_replacements
    transformed = transformer_manager.transform_cell(transformed)
    transformed, magic_replacements = replace_magics(transformed)
    if len(transformed.splitlines()) != len(src.splitlines()):
        # Multi-line magic, not supported.
        raise NothingChanged
    replacements += magic_replacements
    return transformed, replacements
예제 #12
0
 def _is_pdb_complete(self, source):
     """
     Check if the pdb input is ready to be executed.
     """
     if source and source[0] == '!':
         source = source[1:]
     if LooseVersion(ipy_version) < LooseVersion('7.0.0'):
         tm = IPythonInputSplitter()
     else:
         tm = TransformerManager()
     complete, indent = tm.check_complete(source)
     if indent is not None:
         indent = indent * ' '
     return complete != 'incomplete', indent
예제 #13
0
def _should_ignore_code_cell(
    source: Sequence[str], process_cells: Sequence[str]
) -> bool:
    """
    Return True if the current cell should be ignored from processing.

    Parameters
    ----------
    source
        Source from the notebook cell
    process_cells
        Extra cells which nbqa should process.

    Returns
    -------
    bool
        True if the cell should ignored else False
    """
    if not "".join(source):
        return True

    try:
        ast.parse("".join(source))
    except SyntaxError:
        # Deal with this below
        pass
    else:
        # No need to ignore
        return False

    cell_magic_finder = CellMagicFinder()
    body = TransformerManager().transform_cell("".join(source))
    try:
        tree = ast.parse(body)
    except SyntaxError:
        # Don't ignore, let tool deal with syntax error
        return False
    cell_magic_finder.visit(tree)

    if cell_magic_finder.header is None:
        # If there's no cell magic, don't ignore.
        return False
    magic_name = remove_prefix(cell_magic_finder.header.split()[0], "%%")
    return magic_name not in MAGIC and magic_name not in {
        i.strip() for i in process_cells
    }
예제 #14
0
def transform_cell(code, indent_only=False):
    """Transform ipython code to python code."""
    number_empty_lines = count_leading_empty_lines(code)
    if indent_only:
        # Not implemented for PY2
        if LooseVersion(ipy_version) < LooseVersion('7.0.0'):
            return code
        if not code.endswith('\n'):
            code += '\n'  # Ensure the cell has a trailing newline
        lines = code.splitlines(keepends=True)
        lines = leading_indent(leading_empty_lines(lines))
        code = ''.join(lines)
    else:
        if LooseVersion(ipy_version) < LooseVersion('7.0.0'):
            tm = IPythonInputSplitter()
            return tm.transform_cell(code)
        else:
            tm = TransformerManager()
            code = tm.transform_cell(code)
    return '\n' * number_empty_lines + code
예제 #15
0
def _transform_magic_commands(cell, hidden_variables):
    def __cell_magic(lines):
        # https://github.com/ipython/ipython/blob/1879ed27bb0ec3be5fee499ac177ad14a9ef7cfd/IPython/core/inputtransformer2.py#L91
        if not lines or not lines[0].startswith("%%"):
            return lines
        if re.match(r"%%\w+\?", lines[0]):
            # This case will be handled by help_end
            return lines
        magic_name, _, first_line = lines[0][2:-1].partition(" ")
        body = "".join(lines[1:])
        hidden_variables.append("".join(lines))
        return [__BF_SIGNATURE__.format(len(hidden_variables) - 1)]

    class __MagicAssign(MagicAssign):
        def transform(self, lines):
            # https://github.com/ipython/ipython/blob/1879ed27bb0ec3be5fee499ac177ad14a9ef7cfd/IPython/core/inputtransformer2.py#L223
            """Transform a magic assignment found by the ``find()`` classmethod."""
            start_line, start_col = self.start_line, self.start_col
            lhs = lines[start_line][:start_col]
            end_line = find_end_of_continued_line(lines, start_line)
            rhs = assemble_continued_line(lines, (start_line, start_col),
                                          end_line)
            assert rhs.startswith("%"), rhs
            magic_name, _, args = rhs[1:].partition(" ")

            lines_before = lines[:start_line]
            hidden_variables.append(rhs)
            call = __BF_SIGNATURE__.format(len(hidden_variables) - 1)
            new_line = lhs + call + "\n"
            lines_after = lines[end_line + 1:]

            return lines_before + [new_line] + lines_after

    class __SystemAssign(SystemAssign):
        def transform(self, lines):
            # https://github.com/ipython/ipython/blob/1879ed27bb0ec3be5fee499ac177ad14a9ef7cfd/IPython/core/inputtransformer2.py#L262
            """Transform a system assignment found by the ``find()`` classmethod."""
            start_line, start_col = self.start_line, self.start_col

            lhs = lines[start_line][:start_col]
            end_line = find_end_of_continued_line(lines, start_line)
            rhs = assemble_continued_line(lines, (start_line, start_col),
                                          end_line)
            assert rhs.startswith("!"), rhs
            cmd = rhs[1:]

            lines_before = lines[:start_line]
            hidden_variables.append(rhs)
            call = __BF_SIGNATURE__.format(len(hidden_variables) - 1)
            new_line = lhs + call + "\n"
            lines_after = lines[end_line + 1:]

            return lines_before + [new_line] + lines_after

    class __EscapedCommand(EscapedCommand):
        def transform(self, lines):
            # https://github.com/ipython/ipython/blob/1879ed27bb0ec3be5fee499ac177ad14a9ef7cfd/IPython/core/inputtransformer2.py#L382
            """Transform an escaped line found by the ``find()`` classmethod."""
            start_line, start_col = self.start_line, self.start_col

            indent = lines[start_line][:start_col]
            end_line = find_end_of_continued_line(lines, start_line)
            line = assemble_continued_line(lines, (start_line, start_col),
                                           end_line)

            if len(line) > 1 and line[:2] in ESCAPE_DOUBLES:
                escape, content = line[:2], line[2:]
            else:
                escape, content = line[:1], line[1:]

            if escape in tr:
                hidden_variables.append(line)
                call = __BF_SIGNATURE__.format(len(hidden_variables) - 1)
            else:
                call = ""

            lines_before = lines[:start_line]
            new_line = indent + call + "\n"
            lines_after = lines[end_line + 1:]

            return lines_before + [new_line] + lines_after

    class __HelpEnd(HelpEnd):
        def transform(self, lines):
            # https://github.com/ipython/ipython/blob/1879ed27bb0ec3be5fee499ac177ad14a9ef7cfd/IPython/core/inputtransformer2.py#L439
            """Transform a help command found by the ``find()`` classmethod."""
            piece = "".join(lines[self.start_line:self.q_line + 1])
            indent, content = piece[:self.start_col], piece[self.start_col:]
            lines_before = lines[:self.start_line]
            lines_after = lines[self.q_line + 1:]

            m = _help_end_re.search(content)
            if not m:
                raise SyntaxError(content)
            assert m is not None, content
            target = m.group(1)
            esc = m.group(3)

            # If we're mid-command, put it back on the next prompt for the user.
            next_input = None
            if (not lines_before) and (
                    not lines_after) and content.strip() != m.group(0):
                next_input = content.rstrip("?\n")

            hidden_variables.append(content)
            call = __BF_SIGNATURE__.format(len(hidden_variables) - 1)
            new_line = indent + call + "\n"

            return lines_before + [new_line] + lines_after

    transformer_manager = TransformerManager()
    transformer_manager.line_transforms = [__cell_magic]
    transformer_manager.token_transformers = [
        __MagicAssign,
        __SystemAssign,
        __EscapedCommand,
        __HelpEnd,
    ]
    return transformer_manager.transform_cell(cell)
예제 #16
0
def _replace_magics(
    source: Sequence[str],
    magic_substitutions: List[MagicHandler],
    command: str,
    *,
    skip_bad_cells: bool,
) -> str:
    """
    Replace IPython line magics with valid python code.

    Parameters
    ----------
    source
        Source from notebook cell.
    magic_substitutions
        List to store all the ipython magics substitutions

    Returns
    -------
    str
        Line from cell, with line magics replaced with python code
    """
    try:
        ast.parse("".join(source))
    except SyntaxError:
        pass
    else:
        # Source has no IPython magic, return it directly
        return "".join(source)

    cell_magic_finder = CellMagicFinder()
    body = TransformerManager().transform_cell("".join(source))
    try:
        tree = ast.parse(body)
    except SyntaxError:
        if skip_bad_cells:
            handler = MagicHandler("".join(source), command, magic_type=None)
            magic_substitutions.append(handler)
            return handler.replacement
        return "".join(source)
    cell_magic_finder.visit(tree)

    # if first line is cell magic, process it separately
    if cell_magic_finder.header is not None:
        assert cell_magic_finder.body is not None
        header = _process_source(
            cell_magic_finder.header,
            command,
            magic_substitutions,
            skip_bad_cells=skip_bad_cells,
        )
        cell = _process_source(
            cell_magic_finder.body,
            command,
            magic_substitutions,
            skip_bad_cells=skip_bad_cells,
        )
        return "\n".join([header, cell])

    return _process_source(
        "".join(source), command, magic_substitutions, skip_bad_cells=skip_bad_cells
    )
예제 #17
0
"""

import sys
import warnings
import ast

import nbformat


# try to fight the advertising/deprecation warnings and get an
# ipython2python function without confusing messages appearing
# all over the place
try:
    from IPython.core.inputtransformer2 import TransformerManager
    ipython2python = TransformerManager().transform_cell
except:
    # this is the import I wanted to use, but it generates
    # deprecation wanrings when all the latest packages are
    # installed (as of 12 June 2019).
    from nbconvert.filters.strings import ipython2python

from . import holoviews_support
from . import builtins_support

# TODO: still nede to investigate the following line magics (and what
# does ipython convert do to them?):
#
#   ? cd
#   ? dirs
#    macro
예제 #18
0
    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

        # This is necessary to allow running comprehensions with the
        # frame locals. It also fallbacks to the right globals if the
        # user wants to work with them instead.
        # See spyder-ide/spyder#13909.
        if not 'globals()' in line:
            ns = self.curframe.f_globals.copy()
            ns.update(locals)
        else:
            ns = 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 ns or cmd in builtins.__dict__)
                # Special case for quit and exit
                if cmd in ("quit", "exit"):
                    if cmd in ns and isinstance(ns[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
                is_assignment = arg and arg[0] == "="
                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)
            try:
                code = compile(line + '\n', '<stdin>', 'single')
            except SyntaxError:
                # support multiline statments
                code = compile(line + '\n', '<stdin>', 'exec')
            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')
                exec(code, ns, locals)
                if execute_events:
                    get_ipython().events.trigger('post_execute')
            finally:
                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())
예제 #19
0
def ipython_cell_transform(source):
    out = TransformerManager().transform_cell(source)
    return source, out
예제 #20
0
    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)
            try:
                code = compile(line + '\n', '<stdin>', 'single')
            except SyntaxError:
                # support multiline statments
                code = compile(line + '\n', '<stdin>', 'exec')
            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')

                # Mitigates a CPython bug (https://bugs.python.org/issue41918)
                # that prevents running comprehensions with the frame locals
                # in Pdb.
                # See https://bugs.python.org/issue21161 and
                # spyder-ide/spyder#13909.
                if uses_comprehension(line):
                    # There are three potential problems with this approach:
                    # 1. If the code access a globals variable that is
                    #    masked by a locals variable, it will get the locals
                    #    one.
                    # 2. Any edit to that variable will be lost.
                    # 3. The globals will appear to contain all the locals
                    #    variables.
                    # 4. Any new locals variable will be saved to globals
                    #    instead
                    fake_globals = globals.copy()
                    fake_globals.update(locals)
                    locals_keys = locals.keys()
                    # Don't pass locals, solves spyder-ide/spyder#16790
                    exec(code, fake_globals)
                    # Avoid mixing locals and globals
                    for key in locals_keys:
                        locals[key] = fake_globals.pop(key, None)
                    globals.update(fake_globals)
                else:
                    exec(code, globals, locals)

                if execute_events:
                    get_ipython().events.trigger('post_execute')
            finally:
                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())
예제 #21
0
    def init_line_transforms(self):
        """
        Set up transforms (like the preparser).

        TESTS:

        Check that :trac:`31951` is fixed::

             sage: from IPython import get_ipython
             sage: ip = get_ipython()
             sage: ip.input_transformer_manager.check_complete('''  # indirect doctest
             ....: for i in [1 .. 2]:
             ....:     a = 2''')
             ('incomplete', 2)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo(L)
             ....:     K.<a> = L''')
             ('invalid', None)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo(L):
             ....:     K.<a> = L''')
             ('incomplete', 4)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo(L):
             ....:     K.<a> = L''')
             ('incomplete', 4)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo(R):
             ....:     a = R.0''')
             ('incomplete', 4)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo(a):
             ....:     b = 2a''')
             ('invalid', None)
             sage: implicit_multiplication(True)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo(a):
             ....:     b = 2a''')
             ('incomplete', 4)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo():
             ....:     f(x) = x^2''')
             ('incomplete', 4)
             sage: ip.input_transformer_manager.check_complete('''
             ....: def foo():
             ....:     2.factor()''')
             ('incomplete', 4)
        """
        from IPython.core.inputtransformer2 import TransformerManager
        from .interpreter import SagePromptTransformer, SagePreparseTransformer

        self.shell.input_transformer_manager.cleanup_transforms.insert(
            1, SagePromptTransformer)
        self.shell.input_transformers_post.append(SagePreparseTransformer)

        # Create an input transformer that does Sage's special syntax in the first step.
        # We append Sage's preparse to the cleanup step, so that ``check_complete`` recognizes
        # Sage's special syntax.
        # Behaviour is somewhat inconsistent, but the syntax is recognized as desired.
        M = TransformerManager()
        M.token_transformers = self.shell.input_transformer_manager.token_transformers
        M.cleanup_transforms.insert(1, SagePromptTransformer)
        M.cleanup_transforms.append(SagePreparseTransformer)
        self.shell._check_complete_transformer = M
        self.shell.input_transformer_manager.check_complete = M.check_complete
예제 #22
0
 def is_complete(self, source):
     tm = TransformerManager()
     check_complete = tm.check_complete(source)
     responses.append(check_complete)
예제 #23
0
    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())
예제 #24
0
    def default(self, line):
        """
        Default way of running pdb statment.
        """
        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')

                code_ast = ast.parse(line)

                if line.rstrip()[-1] == ";":
                    # Supress output with ;
                    capture_last_expression = False
                else:
                    code_ast, capture_last_expression = capture_last_Expr(
                        code_ast, "_spyderpdb_out")

                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.

                    # Create a function
                    indent = "    "
                    code = ["def _spyderpdb_code():"]

                    # Load the locals
                    globals["_spyderpdb_builtins_locals"] = builtins.locals

                    # Save builtins locals in case it is shadowed
                    globals["_spyderpdb_locals"] = locals

                    # 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 k.isidentifier()]


                    # Update the locals
                    code += [indent + "_spyderpdb_locals.update("
                             "_spyderpdb_builtins_locals())"]

                    # Run the function
                    code += ["_spyderpdb_code()"]

                    # Cleanup
                    code += [
                        "del _spyderpdb_code",
                        "del _spyderpdb_locals",
                        "del _spyderpdb_builtins_locals"
                    ]

                    # Parse the function
                    fun_ast = ast.parse('\n'.join(code) + '\n')

                    # Inject code_ast in the function before the locals update
                    fun_ast.body[0].body = (
                        fun_ast.body[0].body[:-1]  # The locals
                        + code_ast.body  # Code to run
                        + fun_ast.body[0].body[-1:]  # Locals update
                    )
                    code_ast = fun_ast

                exec(compile(code_ast, "<stdin>", "exec"), globals)

                if capture_last_expression:
                    out = globals.pop("_spyderpdb_out", None)
                    if out is not None:
                        sys.stdout.flush()
                        sys.stderr.flush()
                        frontend_request(blocking=False).show_pdb_output(
                            repr(out))

            finally:
                if execute_events:
                     get_ipython().events.trigger('post_execute')
                sys.stdout = save_stdout
                sys.stdin = save_stdin
                sys.displayhook = save_displayhook
        except BaseException:
            exc_info = sys.exc_info()[:2]
            self.error(
                traceback.format_exception_only(*exc_info)[-1].strip())