Beispiel #1
0
    def __call__(self, source, filename="<input>", symbol="single"):

        if source == 'pass':
            # We need to return a no-op to signal that no more input is needed.
            return (compile(source, filename, symbol), ) * 2

        hash_digest = hashlib.sha1(source.encode("utf-8").strip()).hexdigest()
        name = '{}-{}'.format(filename.strip('<>'), hash_digest)

        try:
            hy_ast = hy_parse(source, filename=name)
        except Exception:
            # Capture a traceback without the compiler/REPL frames.
            sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info()
            self._update_exc_info()
            raise

        self._cache(source, name)

        try:
            hy_ast = hy_parse(source, filename=filename)
            root_ast = ast.Interactive if symbol == 'single' else ast.Module

            # Our compiler doesn't correspond to a real, fixed source file, so
            # we need to [re]set these.
            self.hy_compiler.filename = filename
            self.hy_compiler.source = source
            exec_ast, eval_ast = hy_compile(hy_ast,
                                            self.module,
                                            root=root_ast,
                                            get_expr=True,
                                            compiler=self.hy_compiler,
                                            filename=filename,
                                            source=source,
                                            import_stdlib=False)

            if self.ast_callback:
                self.ast_callback(exec_ast, eval_ast)

            exec_code = super(HyCompile, self).__call__(exec_ast, name, symbol)
            eval_code = super(HyCompile, self).__call__(eval_ast, name, 'eval')

        except HyLanguageError:
            # Hy will raise exceptions during compile-time that Python would
            # raise during run-time (e.g. import errors for `require`).  In
            # order to work gracefully with the Python world, we convert such
            # Hy errors to code that purposefully reraises those exceptions in
            # the places where Python code expects them.
            sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info()
            self._update_exc_info()
            exec_code = super(HyCompile, self).__call__(
                'import hy._compat; hy._compat.reraise('
                '_hy_last_type, _hy_last_value, _hy_last_traceback)', name,
                symbol)
            eval_code = super(HyCompile, self).__call__('None', name, 'eval')

        return exec_code, eval_code
Beispiel #2
0
    def __call__(self, source, filename="<input>", symbol="single"):

        if source == 'pass':
            # We need to return a no-op to signal that no more input is needed.
            return (compile(source, filename, symbol),) * 2

        hash_digest = hashlib.sha1(source.encode("utf-8").strip()).hexdigest()
        name = '{}-{}'.format(filename.strip('<>'), hash_digest)

        try:
            hy_ast = hy_parse(source, filename=name)
        except Exception:
            # Capture a traceback without the compiler/REPL frames.
            sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info()
            self._update_exc_info()
            raise

        self._cache(source, name)

        try:
            hy_ast = hy_parse(source, filename=filename)
            root_ast = ast.Interactive if symbol == 'single' else ast.Module

            # Our compiler doesn't correspond to a real, fixed source file, so
            # we need to [re]set these.
            self.hy_compiler.filename = filename
            self.hy_compiler.source = source
            exec_ast, eval_ast = hy_compile(hy_ast, self.module, root=root_ast,
                                            get_expr=True,
                                            compiler=self.hy_compiler,
                                            filename=filename, source=source)

            if self.ast_callback:
                self.ast_callback(exec_ast, eval_ast)

            exec_code = super(HyCompile, self).__call__(exec_ast, name, symbol)
            eval_code = super(HyCompile, self).__call__(eval_ast, name, 'eval')

        except HyLanguageError:
            # Hy will raise exceptions during compile-time that Python would
            # raise during run-time (e.g. import errors for `require`).  In
            # order to work gracefully with the Python world, we convert such
            # Hy errors to code that purposefully reraises those exceptions in
            # the places where Python code expects them.
            sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info()
            self._update_exc_info()
            exec_code = super(HyCompile, self).__call__(
                'import hy._compat; hy._compat.reraise('
                '_hy_last_type, _hy_last_value, _hy_last_traceback)',
                name, symbol)
            eval_code = super(HyCompile, self).__call__('None', name, 'eval')

        return exec_code, eval_code
Beispiel #3
0
    def runsource(self, source, filename='<input>', symbol='single'):
        global SIMPLE_TRACEBACKS

        def error_handler(e, use_simple_traceback=False):
            self.locals[mangle("*e")] = e
            if use_simple_traceback:
                print(e, file=sys.stderr)
            else:
                self.showtraceback()

        try:
            try:
                do = hy_parse(source)
            except PrematureEndOfInput:
                return True
        except LexException as e:
            if e.source is None:
                e.source = source
                e.filename = filename
            error_handler(e, use_simple_traceback=True)
            return False

        try:

            def ast_callback(main_ast, expr_ast):
                if self.spy:
                    # Mush the two AST chunks into a single module for
                    # conversion into Python.
                    new_ast = ast.Module(main_ast.body +
                                         [ast.Expr(expr_ast.body)])
                    print(astor.to_source(new_ast))

            value = hy_eval(do,
                            self.locals,
                            ast_callback=ast_callback,
                            compiler=self.hy_compiler)
        except HyTypeError as e:
            if e.source is None:
                e.source = source
                e.filename = filename
            error_handler(e, use_simple_traceback=SIMPLE_TRACEBACKS)
            return False
        except Exception as e:
            error_handler(e)
            return False

        if value is not None:
            # Shift exisitng REPL results
            next_result = value
            for sym in self._repl_results_symbols:
                self.locals[sym], next_result = next_result, self.locals[sym]

            # Print the value.
            try:
                output = self.output_fn(value)
            except Exception as e:
                error_handler(e)
                return False
            print(output)
        return False
Beispiel #4
0
    def do_execute_direct(self, code):
        '''
        Execute the code, and return result.
        '''
        self.result = None
        #### try to parse it:
        try:
            filename = "In [%s]" % self.execution_count
            hy_ast = hy_parse(code, filename=filename)
            exec_ast, eval_ast = hy_compile(hy_ast, self.module,
                                            root=ast.Interactive,
                                            get_expr=True,
                                            compiler=self.hy_compiler,
                                            filename=filename, source=code)
            exec_code = compile(exec_ast, filename, 'single')
            eval_code = compile(eval_ast, filename, 'eval')
            eval(exec_code, self.locals)
            self.result = eval(eval_code, self.locals)

        except Exception as e:
            self.Error(traceback.format_exc())
            self.kernel_resp.update({
                "status": "error",
                'ename' : e.__class__.__name__,   # Exception name, as a string
                'evalue' : e.__class__.__name__,  # Exception value, as a string
                'traceback' : [], # traceback frames as strings
            })
            return None
        return self.result
Beispiel #5
0
    def _hy_source_to_code(self, data, path, _optimize=-1):
        if _could_be_hy_src(path):
            source = data.decode("utf-8")
            hy_tree = hy_parse(source, filename=path)
            with loader_module_obj(self) as module:
                data = hy_compile(hy_tree, module)

        return _py_source_to_code(self, data, path, _optimize=_optimize)
Beispiel #6
0
def _hy_source_to_code(self, data, path, _optimize=-1):
    if _could_be_hy_src(path):
        source = data.decode("utf-8")
        hy_tree = hy_parse(source, filename=path)
        with loader_module_obj(self) as module:
            data = hy_compile(hy_tree, module)

    return _py_source_to_code(self, data, path, _optimize=_optimize)
Beispiel #7
0
def cant_compile(expr):
    with pytest.raises(HyError) as excinfo:
        hy_compile(hy_parse(expr), __name__)
    # Anything that can't be compiled should raise a user friendly
    # error, otherwise it's a compiler bug.
    assert issubclass(excinfo.type, HyLanguageError)
    assert excinfo.value.msg
    return excinfo.value
Beispiel #8
0
def hy2py_main():
    options = dict(prog="hy2py",
                   usage="%(prog)s [options] [FILE]",
                   formatter_class=argparse.RawDescriptionHelpFormatter)
    parser = argparse.ArgumentParser(**options)
    parser.add_argument("FILE",
                        type=str,
                        nargs='?',
                        help="Input Hy code (use STDIN if \"-\" or "
                        "not provided)")
    parser.add_argument("--with-source",
                        "-s",
                        action="store_true",
                        help="Show the parsed source structure")
    parser.add_argument("--with-ast",
                        "-a",
                        action="store_true",
                        help="Show the generated AST")
    parser.add_argument("--without-python",
                        "-np",
                        action="store_true",
                        help=("Do not show the Python code generated "
                              "from the AST"))

    options = parser.parse_args(sys.argv[1:])

    if options.FILE is None or options.FILE == '-':
        sys.path.insert(0, "")
        filename = '<stdin>'
        source = sys.stdin.read()
    else:
        filename = options.FILE
        set_path(filename)
        with io.open(options.FILE, 'r', encoding='utf-8') as source_file:
            source = source_file.read()

    with filtered_hy_exceptions():
        hst = hy_parse(source, filename=filename)

    if options.with_source:
        _print_for_windows(hst)
        print()
        print()

    with filtered_hy_exceptions():
        _ast = hy_compile(hst, '__main__', filename=filename, source=source)

    if options.with_ast:
        _print_for_windows(ast.dump(_ast))
        print()
        print()

    if not options.without_python:
        _print_for_windows(ast.unparse(_ast))

    parser.exit(0)
Beispiel #9
0
def cant_compile(expr):
    with pytest.raises(HyError) as excinfo:
        hy_compile(hy_parse(expr), __name__)

    if issubclass(excinfo.type, HyLanguageError):
        assert excinfo.value.msg
        return excinfo.value
    elif issubclass(excinfo.type, HyCompileError):
        # Anything that can't be compiled should raise a user friendly
        # error, otherwise it's a compiler bug.
        return excinfo.value
Beispiel #10
0
def run_command(source, filename=None):
    __main__ = importlib.import_module('__main__')
    require("hy.cmdline", __main__, assignments="ALL")
    try:
        tree = hy_parse(source, filename=filename)
    except HyLanguageError:
        hy_exc_handler(*sys.exc_info())
        return 1

    with filtered_hy_exceptions():
        hy_eval(tree, None, __main__, filename=filename, source=source)
    return 0
Beispiel #11
0
def run_command(source, filename=None):
    __main__ = importlib.import_module('__main__')
    require("hy.cmdline", __main__, assignments="ALL")
    try:
        tree = hy_parse(source, filename=filename)
    except HyLanguageError:
        hy_exc_handler(*sys.exc_info())
        return 1

    with filtered_hy_exceptions():
        hy_eval(tree, None, __main__, filename=filename, source=source)
    return 0
Beispiel #12
0
    def _hy_source_to_code(self, data, path, _optimize=-1):
        if _could_be_hy_src(path):
            source = data.decode("utf-8")
            try:
                hy_tree = hy_parse(source)
                with loader_module_obj(self) as module:
                    data = hy_compile(hy_tree, module)
            except (HyTypeError, LexException) as e:
                if e.source is None:
                    e.source = source
                    e.filename = path
                raise

        return _py_source_to_code(self, data, path, _optimize=_optimize)
Beispiel #13
0
def cant_compile(expr):
    try:
        hy_compile(hy_parse(expr), "__main__")
        assert False
    except HyTypeError as e:
        # Anything that can't be compiled should raise a user friendly
        # error, otherwise it's a compiler bug.
        assert isinstance(e.expression, HyObject)
        assert e.message
        return e
    except HyCompileError as e:
        # Anything that can't be compiled should raise a user friendly
        # error, otherwise it's a compiler bug.
        assert isinstance(e.exception, HyTypeError)
        assert e.traceback
        return e
Beispiel #14
0
 def generate(self, code, lang='py', mode='main'):
     self.mod_name = mode
     if mode not in ['main', 'block']:
         self.namespace = mode
         self.variables |= {mode: {'type': types.types['module'](mode)}}
     if lang == 'py':
         tree = ast.parse(code).body
     elif lang == 'hy':
         if not is_hy_supported:
             raise Exception(
                 "requires hy library\n"
                 "\trun 'python -m pip install kithon[add-langs]' to fix")
         tree = hy_parse(code)[1:]
     elif lang == 'coco':
         if not is_coconut_supported:
             raise Exception(
                 "requires coconut library\n"
                 "\trun 'python -m pip install kithon[add-langs]' to fix")
         setup(target='sys')
         tree = ast.parse(parse(code, 'block')).body
     for block in map(self.visit, tree):
         if not block:
             continue
         self.strings.extend(block.render().split('\n'))
     if mode != 'block':
         code = self.templates['main']['tmp'].render(_body=self.strings,
                                                     body='\n'.join(
                                                         self.strings),
                                                     env=self)
         if mode == 'main':
             self.variables = {
                 '__main__': {
                     'type': types.types['module']('__main__')
                 }
             }
             self.temp_var_counts = defaultdict(int)
     else:
         code = '\n'.join(self.strings)
     self.nl = 0
     self.namespace = '__main__'
     self.strings = []
     self.used = set([])
     return code
Beispiel #15
0
        def byte_compile_hy(self, fullname=None):
            fullname = self._fix_name(fullname)
            if fullname is None:
                fullname = self.fullname

            hy_source = self.get_source(fullname)
            hy_tree = hy_parse(hy_source, filename=self.filename)

            with loader_module_obj(self) as module:
                hy_ast = hy_compile(hy_tree, module)

            code = compile(hy_ast, self.filename, 'exec', hy_ast_compile_flags)

            if not sys.dont_write_bytecode:
                try:
                    hyc_compile(code, module=fullname)
                except IOError:
                    pass
            return code
Beispiel #16
0
        def byte_compile_hy(self, fullname=None):
            fullname = self._fix_name(fullname)
            if fullname is None:
                fullname = self.fullname

            hy_source = self.get_source(fullname)
            hy_tree = hy_parse(hy_source, filename=self.filename)

            with loader_module_obj(self) as module:
                hy_ast = hy_compile(hy_tree, module)

            code = compile(hy_ast, self.filename, 'exec',
                           hy_ast_compile_flags)

            if not sys.dont_write_bytecode:
                try:
                    hyc_compile(code, module=fullname)
                except IOError:
                    pass
            return code
Beispiel #17
0
def test_import_error_reporting():
    "Make sure that (import) reports errors correctly."

    with pytest.raises(HyLanguageError):
        hy_compile(hy_parse("(import \"sys\")"), __name__)
Beispiel #18
0
def test_stringer():
    _ast = hy_compile(hy_parse("(defn square [x] (* x x))"), __name__)

    assert type(_ast.body[0]) == ast.FunctionDef
Beispiel #19
0
def can_eval(expr):
    return hy_eval(hy_parse(expr))
Beispiel #20
0
def can_compile(expr):
    return hy_compile(hy_parse(expr), __name__)
Beispiel #21
0
def can_compile(expr):
    return hy_compile(hy_parse(expr), "__main__")
Beispiel #22
0
def can_compile(expr):
    return hy_compile(hy_parse(expr), __name__)
Beispiel #23
0
def test_stringer():
    _ast = hy_compile(hy_parse("(defn square [x] (* x x))"), __name__)

    assert type(_ast.body[0]) == ast.FunctionDef
Beispiel #24
0
    def __init__(self,
                 spy=False,
                 output_fn=None,
                 locals=None,
                 filename="<stdin>"):

        # Create a proper module for this REPL so that we can obtain it easily
        # (e.g. using `importlib.import_module`).
        # We let `InteractiveConsole` initialize `self.locals` when it's
        # `None`.
        super(HyREPL, self).__init__(locals=locals, filename=filename)

        module_name = self.locals.get('__name__', '__console__')
        # Make sure our newly created module is properly introduced to
        # `sys.modules`, and consistently use its namespace as `self.locals`
        # from here on.
        self.module = sys.modules.setdefault(module_name,
                                             types.ModuleType(module_name))
        self.module.__dict__.update(self.locals)
        self.locals = self.module.__dict__

        if os.environ.get("HYSTARTUP"):
            try:
                loader = HyLoader("__hystartup__", os.environ.get("HYSTARTUP"))
                spec = importlib.util.spec_from_loader(loader.name, loader)
                mod = importlib.util.module_from_spec(spec)
                sys.modules.setdefault(mod.__name__, mod)
                loader.exec_module(mod)
                imports = mod.__dict__.get('__all__', [
                    name for name in mod.__dict__ if not name.startswith("_")
                ])
                imports = {name: mod.__dict__[name] for name in imports}
                spy = spy or imports.get("repl_spy")
                output_fn = output_fn or imports.get("repl_output_fn")

                # Load imports and defs
                self.locals.update(imports)

                # load module macros
                require(mod, self.module, assignments='ALL')
            except Exception as e:
                print(e)
        # Load cmdline-specific macros.
        require('hy.cmdline', self.module, assignments='ALL')

        self.hy_compiler = HyASTCompiler(self.module)

        self.cmdline_cache = {}
        self.compile = HyCommandCompiler(self.module,
                                         self.locals,
                                         ast_callback=self.ast_callback,
                                         hy_compiler=self.hy_compiler,
                                         cmdline_cache=self.cmdline_cache)

        self.spy = spy
        self.last_value = None
        self.print_last_value = True

        if output_fn is None:
            self.output_fn = hy.repr
        elif callable(output_fn):
            self.output_fn = output_fn
        elif "." in output_fn:
            parts = [mangle(x) for x in output_fn.split(".")]
            module, f = '.'.join(parts[:-1]), parts[-1]
            self.output_fn = getattr(importlib.import_module(module), f)
        else:
            self.output_fn = getattr(builtins, mangle(output_fn))

        # Pre-mangle symbols for repl recent results: *1, *2, *3
        self._repl_results_symbols = [
            mangle("*{}".format(i + 1)) for i in range(3)
        ]
        self.locals.update({sym: None for sym in self._repl_results_symbols})

        # Allow access to the running REPL instance
        self.locals['_hy_repl'] = self

        # Compile an empty statement to load the standard prelude
        exec_ast = hy_compile(hy_parse(''),
                              self.module,
                              compiler=self.hy_compiler,
                              import_stdlib=True)
        if self.ast_callback:
            self.ast_callback(exec_ast, None)
Beispiel #25
0
    def hyc_compile(file_or_code, cfile=None, dfile=None, doraise=False,
                    module=None):
        """Write a Hy file, or code object, to pyc.

        This is a patched version of Python 2.7's `py_compile.compile`.

        Also, it tries its best to write the bytecode file atomically.

        Parameters
        ----------
        file_or_code : str or instance of `types.CodeType`
            A filename for a Hy or Python source file or its corresponding code
            object.
        cfile : str, optional
            The filename to use for the bytecode file.  If `None`, use the
            standard bytecode filename determined by `cache_from_source`.
        dfile : str, optional
            The filename to use for compile-time errors.
        doraise : bool, default False
            If `True` raise compilation exceptions; otherwise, ignore them.
        module : str or types.ModuleType, optional
            The module, or module name, in which the Hy tree is expanded.
            Default is the caller's module.

        Returns
        -------
        out : str
            The resulting bytecode file name.  Python 3.x returns this, but
            Python 2.7 doesn't; this function does for convenience.
        """

        if isinstance(file_or_code, types.CodeType):
            codeobject = file_or_code
            filename = codeobject.co_filename
        else:
            filename = file_or_code

            with open(filename, 'rb') as f:
                source_str = f.read().decode('utf-8')

            try:
                flags = None
                if _could_be_hy_src(filename):
                    hy_tree = hy_parse(source_str)

                    if module is None:
                        module = inspect.getmodule(inspect.stack()[1][0])
                    elif not inspect.ismodule(module):
                        module = importlib.import_module(module)

                    source = hy_compile(hy_tree, module)
                    flags = hy_ast_compile_flags

                codeobject = compile(source, dfile or filename, 'exec', flags)
            except Exception as err:
                if isinstance(err, (HyTypeError, LexException)) and err.source is None:
                    err.source = source_str
                    err.filename = filename

                py_exc = py_compile.PyCompileError(err.__class__, err,
                                                   dfile or filename)
                if doraise:
                    raise py_exc
                else:
                    traceback.print_exc()
                    return

        timestamp = long(os.stat(filename).st_mtime)

        if cfile is None:
            cfile = cache_from_source(filename)

        f = tempfile.NamedTemporaryFile('wb', dir=os.path.split(cfile)[0],
                                        delete=False)
        try:
            f.write('\0\0\0\0')
            f.write(struct.pack('<I', timestamp))
            f.write(marshal.dumps(codeobject))
            f.flush()
            f.seek(0, 0)
            f.write(imp.get_magic())

            # Make sure it's written to disk.
            f.flush()
            os.fsync(f.fileno())
            f.close()

            # Rename won't replace an existing dest on Windows.
            if os.name == 'nt' and os.path.isfile(cfile):
                os.unlink(cfile)

            os.rename(f.name, cfile)
        except OSError:
            try:
                os.unlink(f.name)
            except OSError:
                pass

        return cfile
Beispiel #26
0
def test_import_error_reporting():
    "Make sure that (import) reports errors correctly."

    with pytest.raises(HyLanguageError):
        hy_compile(hy_parse("(import \"sys\")"), __name__)
Beispiel #27
0
def can_compile(expr, import_stdlib=False):
    return hy_compile(hy_parse(expr), __name__, import_stdlib=import_stdlib)
Beispiel #28
0
def hy2py_main():
    import platform

    options = dict(prog="hy2py", usage="%(prog)s [options] [FILE]",
                   formatter_class=argparse.RawDescriptionHelpFormatter)
    parser = argparse.ArgumentParser(**options)
    parser.add_argument("FILE", type=str, nargs='?',
                        help="Input Hy code (use STDIN if \"-\" or "
                             "not provided)")
    parser.add_argument("--with-source", "-s", action="store_true",
                        help="Show the parsed source structure")
    parser.add_argument("--with-ast", "-a", action="store_true",
                        help="Show the generated AST")
    parser.add_argument("--without-python", "-np", action="store_true",
                        help=("Do not show the Python code generated "
                              "from the AST"))

    options = parser.parse_args(sys.argv[1:])

    if options.FILE is None or options.FILE == '-':
        filename = '<stdin>'
        source = sys.stdin.read()
    else:
        filename = options.FILE
        with io.open(options.FILE, 'r', encoding='utf-8') as source_file:
            source = source_file.read()

    with filtered_hy_exceptions():
        hst = hy_parse(source, filename=filename)

    if options.with_source:
        # need special printing on Windows in case the
        # codepage doesn't support utf-8 characters
        if PY3 and platform.system() == "Windows":
            for h in hst:
                try:
                    print(h)
                except:
                    print(str(h).encode('utf-8'))
        else:
            print(hst)
        print()
        print()

    with filtered_hy_exceptions():
        _ast = hy_compile(hst, '__main__', filename=filename, source=source)

    if options.with_ast:
        if PY3 and platform.system() == "Windows":
            _print_for_windows(astor.dump_tree(_ast))
        else:
            print(astor.dump_tree(_ast))
        print()
        print()

    if not options.without_python:
        if PY3 and platform.system() == "Windows":
            _print_for_windows(astor.code_gen.to_source(_ast))
        else:
            print(astor.code_gen.to_source(_ast))

    parser.exit(0)
Beispiel #29
0
def run_command(source):
    tree = hy_parse(source)
    require("hy.cmdline", "__main__", assignments="ALL")
    pretty_error(hy_eval, tree, None, importlib.import_module('__main__'))
    return 0
Beispiel #30
0
def can_eval(expr):
    return hy_eval(hy_parse(expr))
Beispiel #31
0
    def hyc_compile(file_or_code, cfile=None, dfile=None, doraise=False,
                    module=None):
        """Write a Hy file, or code object, to pyc.

        This is a patched version of Python 2.7's `py_compile.compile`.

        Also, it tries its best to write the bytecode file atomically.

        Parameters
        ----------
        file_or_code : str or instance of `types.CodeType`
            A filename for a Hy or Python source file or its corresponding code
            object.
        cfile : str, optional
            The filename to use for the bytecode file.  If `None`, use the
            standard bytecode filename determined by `cache_from_source`.
        dfile : str, optional
            The filename to use for compile-time errors.
        doraise : bool, default False
            If `True` raise compilation exceptions; otherwise, ignore them.
        module : str or types.ModuleType, optional
            The module, or module name, in which the Hy tree is expanded.
            Default is the caller's module.

        Returns
        -------
        out : str
            The resulting bytecode file name.  Python 3.x returns this, but
            Python 2.7 doesn't; this function does for convenience.
        """

        if isinstance(file_or_code, types.CodeType):
            codeobject = file_or_code
            filename = codeobject.co_filename
        else:
            filename = file_or_code

            with open(filename, 'rb') as f:
                source_str = f.read().decode('utf-8')

            try:
                flags = None
                if _could_be_hy_src(filename):
                    hy_tree = hy_parse(source_str, filename=filename)

                    if module is None:
                        module = inspect.getmodule(inspect.stack()[1][0])
                    elif not inspect.ismodule(module):
                        module = importlib.import_module(module)

                    source = hy_compile(hy_tree, module)
                    flags = hy_ast_compile_flags

                codeobject = compile(source, dfile or filename, 'exec', flags)
            except Exception as err:

                py_exc = py_compile.PyCompileError(err.__class__, err,
                                                   dfile or filename)
                if doraise:
                    raise py_exc
                else:
                    traceback.print_exc()
                    return

        timestamp = long(os.stat(filename).st_mtime)

        if cfile is None:
            cfile = cache_from_source(filename)

        f = None
        try:
            f = tempfile.NamedTemporaryFile('wb', dir=os.path.split(cfile)[0],
                                            delete=False)
            f.write('\0\0\0\0')
            f.write(struct.pack('<I', timestamp))
            f.write(marshal.dumps(codeobject))
            f.flush()
            f.seek(0, 0)
            f.write(imp.get_magic())

            # Make sure it's written to disk.
            f.flush()
            os.fsync(f.fileno())
            f.close()

            # Rename won't replace an existing dest on Windows.
            if os.name == 'nt' and os.path.isfile(cfile):
                os.unlink(cfile)

            os.rename(f.name, cfile)
        except OSError:
            try:
                if f is not None:
                    os.unlink(f.name)
            except OSError:
                pass

        return cfile
Beispiel #32
0
def hy2py_main():
    import platform

    options = dict(prog="hy2py",
                   usage="%(prog)s [options] [FILE]",
                   formatter_class=argparse.RawDescriptionHelpFormatter)
    parser = argparse.ArgumentParser(**options)
    parser.add_argument("FILE",
                        type=str,
                        nargs='?',
                        help="Input Hy code (use STDIN if \"-\" or "
                        "not provided)")
    parser.add_argument("--with-source",
                        "-s",
                        action="store_true",
                        help="Show the parsed source structure")
    parser.add_argument("--with-ast",
                        "-a",
                        action="store_true",
                        help="Show the generated AST")
    parser.add_argument("--without-python",
                        "-np",
                        action="store_true",
                        help=("Do not show the Python code generated "
                              "from the AST"))

    options = parser.parse_args(sys.argv[1:])

    if options.FILE is None or options.FILE == '-':
        filename = '<stdin>'
        source = sys.stdin.read()
    else:
        filename = options.FILE
        with io.open(options.FILE, 'r', encoding='utf-8') as source_file:
            source = source_file.read()

    with filtered_hy_exceptions():
        hst = hy_parse(source, filename=filename)

    if options.with_source:
        # need special printing on Windows in case the
        # codepage doesn't support utf-8 characters
        if platform.system() == "Windows":
            for h in hst:
                try:
                    print(h)
                except:
                    print(str(h).encode('utf-8'))
        else:
            print(hst)
        print()
        print()

    with filtered_hy_exceptions():
        _ast = hy_compile(hst, '__main__', filename=filename, source=source)

    if options.with_ast:
        if platform.system() == "Windows":
            _print_for_windows(astor.dump_tree(_ast))
        else:
            print(astor.dump_tree(_ast))
        print()
        print()

    if not options.without_python:
        if platform.system() == "Windows":
            _print_for_windows(astor.code_gen.to_source(_ast))
        else:
            print(astor.code_gen.to_source(_ast))

    parser.exit(0)
Beispiel #33
0
 def _import_error_test():
     try:
         _ = hy_compile(hy_parse("(import \"sys\")"), '__main__')
     except HyTypeError:
         return "Error reported"