Example #1
0
    def runsource(self, source, filename="<input>", symbol="single"):
        try:
            code = self.compile(source, filename, symbol)
        except (OverflowError, SyntaxError, ValueError):
            code = ""
            pass

        if code is None:
            # This means it's incomplete
            return True

        try:
            tree = ast.parse(source)
            bindings = detect_macros(tree)

            for p, names in bindings:
                __import__(p)

            self.bindings.extend([(sys.modules[p], bindings) for (p, bindings) in bindings])

            tree = expand_entire_ast(tree, source, self.bindings)

            tree = ast.Interactive(tree.body)
            code = compile(tree, filename, symbol, self.compile.compiler.flags, 1)
        except (OverflowError, SyntaxError, ValueError):
            # Case 1
            self.showsyntaxerror(filename)
            # This means there's a syntax error
            return False

        self.runcode(code)
        # This means it was successfully compiled; `runcode` takes care of
        # any runtime failures
        return False
Example #2
0
    def runsource(self, source, filename="<input>", symbol="single"):
        try:
            code = self.compile(source, filename, symbol)
        except (OverflowError, SyntaxError, ValueError):
            code = ""
            pass

        if code is None:
            # This means it's incomplete
            return True

        try:
            tree = ast.parse(source)
            required_pkgs = detect_macros(tree)
            for p in required_pkgs:
                __import__(p)

            self.modules.update(sys.modules[p] for p in required_pkgs)
            tree = process_ast(tree, self.modules)

            tree = ast.Interactive(tree.body)
            code = compile(tree, filename, symbol, self.compile.compiler.flags,
                           1)
        except (OverflowError, SyntaxError, ValueError):
            # Case 1
            self.showsyntaxerror(filename)
            # This means there's a syntax error
            return False

        self.runcode(code)
        # This means it was successfully compiled; `runcode` takes care of
        # any runtime failures
        return False
Example #3
0
 def visit(self, tree):
     try:
         bindings = detect_macros(tree, '__main__')  # macro imports
         if bindings:
             self.ext.macro_bindings_changed = True
             for fullname, macro_bindings in bindings:
                 mod = importlib.import_module(fullname)
                 self.bindings[fullname] = (mod, macro_bindings)
         newtree = ModuleExpansionContext(
             tree, self.ext.src, self.bindings.values()).expand_macros()
         self.ext.src = _placeholder
         return newtree
     except Exception as err:
         # see IPython.core.interactiveshell.InteractiveShell.transform_ast()
         raise InputRejected(*err.args)
Example #4
0
    def runsource(self, source, filename="<input>", symbol="single"):
        # ? and ?? help syntax
        if source == "macros?":
            self._list_macros()
            return False  # complete input
        elif source.endswith("??"):
            return self.runsource(f'imacropy.sourcecode({source[:-2]})')
        elif source.endswith("?"):
            return self.runsource(f"imacropy.doc({source[:-1]})")

        try:
            code = self.compile(source, filename, symbol)
        except (OverflowError, SyntaxError, ValueError):
            code = ""
        if code is None:  # incomplete input
            return True

        try:
            tree = ast.parse(source)
            # Must reload modules before detect_macros, because detect_macros reads the macro registry
            # of each module from which macros are imported.
            _reload_macro_modules(tree, '__main__')
            # If detect_macros returns normally, it means each fullname (module) can be imported successfully.
            try:
                bindings = detect_macros(tree, '__main__')
            except AttributeError:  # module 'foo' has no attribute 'macros'
                pass
            else:
                if bindings:
                    self._stubs_dirty = True
                for fullname, macro_bindings in bindings:  # validate before committing
                    mod = importlib.import_module(
                        fullname
                    )  # already imported so just a sys.modules lookup
                    for origname, _ in macro_bindings:
                        try:
                            getattr(mod, origname)
                        except AttributeError:
                            raise ImportError(
                                f"cannot import name '{origname}'")
                for fullname, macro_bindings in bindings:
                    mod = importlib.import_module(fullname)
                    self._bindings[fullname] = (mod, macro_bindings)

            tree = ModuleExpansionContext(
                tree, source, self._bindings.values()).expand_macros()

            tree = ast.Interactive(tree.body)
            code = compile(tree, filename, symbol, self.compile.compiler.flags,
                           1)
        except (OverflowError, SyntaxError, ValueError):
            self.showsyntaxerror(filename)
            return False  # erroneous input
        except ModuleNotFoundError as err:  # during macro module lookup
            # In this case, the standard stack trace is long and points only to our code and the stdlib,
            # not the erroneous input that's the actual culprit. Better ignore it, and emulate showsyntaxerror.
            # TODO: support sys.excepthook.
            self.write(f"{err.__class__.__name__}: {str(err)}\n")
            return False  # erroneous input
        except ImportError as err:  # during macro lookup in a successfully imported module
            self.write(f"{err.__class__.__name__}: {str(err)}\n")
            return False  # erroneous input

        self.runcode(code)
        self._refresh_stubs()
        return False  # Successfully compiled. `runcode` takes care of any runtime failures.