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)