library/compiler/__main__.py (93 lines of code) (raw):

# Portions copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) # pyre-unsafe import argparse import importlib.util import marshal import os import re import sys from dis import dis from . import pycodegen, static try: # pyre-ignore[21]: Could not find a module corresponding to import `cinder`. from cinder import StrictModule except ImportError: StrictModule = None # https://www.python.org/dev/peps/pep-0263/ coding_re = re.compile(rb"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)") def open_with_coding(fname): with open(fname, "rb") as f: line = f.readline() m = coding_re.match(line) if not m: line = f.readline() m = coding_re.match(line) encoding = "utf-8" if m: encoding = m.group(1).decode() return open(fname, encoding=encoding) argparser = argparse.ArgumentParser( prog="compiler", description="Compile/execute a Python3 source file", epilog="""\ By default, compile source code into in-memory code object and execute it. If -c is specified, instead of executing write .pyc file. """, ) argparser.add_argument( "-c", action="store_true", help="compile into .pyc file instead of executing" ) argparser.add_argument("--dis", action="store_true", help="disassemble compiled code") argparser.add_argument("--output", help="path to the output .pyc file") argparser.add_argument( "--modname", help="module name to compile as (default __main__)", default="__main__" ) argparser.add_argument("input", help="source .py file") group = argparser.add_mutually_exclusive_group() group.add_argument( "--static", action="store_true", help="compile using static compiler" ) group.add_argument( "--builtin", action="store_true", help="compile using built-in C compiler" ) group.add_argument( "--opt", action="store", type=int, default=-1, help="set optimization level to compile with", ) argparser.add_argument("--strict", action="store_true", help="run in strict module") args = argparser.parse_args() with open_with_coding(args.input) as f: fileinfo = os.stat(args.input) source = f.read() if args.builtin: codeobj = compile(source, args.input, "exec") else: compiler = pycodegen.CinderCodeGenerator if args.static: compiler = static.StaticCodeGenerator codeobj = pycodegen.compile( source, args.input, "exec", optimize=args.opt, compiler=compiler, modname=args.modname, ) if args.dis: dis(codeobj) if args.c: if args.output: name = args.output else: name = args.input.rsplit(".", 1)[0] + ".pyc" with open(name, "wb") as f: hdr = pycodegen.make_header(int(fileinfo.st_mtime), fileinfo.st_size) f.write(importlib.util.MAGIC_NUMBER) f.write(hdr) marshal.dump(codeobj, f) else: if args.strict and StrictModule is not None: d = {} mod = StrictModule(d, False) d["__name__"] = "__main__" sys.modules["__main__"] = mod exec(codeobj, d, d) else: exec(codeobj)