blacken main.py

This commit is contained in:
rocky
2019-12-23 04:44:40 -05:00
parent d9318e9bed
commit ddffc2c078

View File

@@ -22,17 +22,19 @@ from uncompyle6.disas import check_object_path
from uncompyle6.semantics import pysource from uncompyle6.semantics import pysource
from uncompyle6.parser import ParserError from uncompyle6.parser import ParserError
from uncompyle6.version import VERSION from uncompyle6.version import VERSION
# from uncompyle6.linenumbers import line_number_mapping # from uncompyle6.linenumbers import line_number_mapping
from uncompyle6.semantics.pysource import code_deparse from uncompyle6.semantics.pysource import code_deparse
from uncompyle6.semantics.fragments import code_deparse as code_deparse_fragments from uncompyle6.semantics.fragments import code_deparse as code_deparse_fragments
from uncompyle6.semantics.linemap import deparse_code_with_map from uncompyle6.semantics.linemap import deparse_code_with_map
from xdis.load import load_module from xdis.load import load_module
def _get_outstream(outfile): def _get_outstream(outfile):
dir = os.path.dirname(outfile) dir = os.path.dirname(outfile)
failed_file = outfile + '_failed' failed_file = outfile + "_failed"
if os.path.exists(failed_file): if os.path.exists(failed_file):
os.remove(failed_file) os.remove(failed_file)
try: try:
@@ -40,9 +42,10 @@ def _get_outstream(outfile):
except OSError: except OSError:
pass pass
if PYTHON_VERSION < 3.0: if PYTHON_VERSION < 3.0:
return open(outfile, mode='wb') return open(outfile, mode="wb")
else: else:
return open(outfile, mode='w', encoding='utf-8') return open(outfile, mode="w", encoding="utf-8")
def decompile( def decompile(
bytecode_version, bytecode_version,
@@ -75,81 +78,99 @@ def decompile(
real_out = out or sys.stdout real_out = out or sys.stdout
def write(s): def write(s):
s += '\n' s += "\n"
real_out.write(s) real_out.write(s)
assert iscode(co) assert iscode(co)
co_pypy_str = 'PyPy ' if is_pypy else '' co_pypy_str = "PyPy " if is_pypy else ""
run_pypy_str = 'PyPy ' if IS_PYPY else '' run_pypy_str = "PyPy " if IS_PYPY else ""
sys_version_lines = sys.version.split('\n') sys_version_lines = sys.version.split("\n")
if source_encoding: if source_encoding:
write('# -*- coding: %s -*-' % source_encoding) write("# -*- coding: %s -*-" % source_encoding)
write('# uncompyle6 version %s\n' write(
'# %sPython bytecode %s%s\n# Decompiled from: %sPython %s' % "# uncompyle6 version %s\n"
(VERSION, co_pypy_str, bytecode_version, "# %sPython bytecode %s%s\n# Decompiled from: %sPython %s"
" (%s)" % str(magic_int) if magic_int else "", % (
run_pypy_str, '\n# '.join(sys_version_lines))) VERSION,
co_pypy_str,
bytecode_version,
" (%s)" % str(magic_int) if magic_int else "",
run_pypy_str,
"\n# ".join(sys_version_lines),
)
)
if co.co_filename: if co.co_filename:
write('# Embedded file name: %s' % co.co_filename,) write("# Embedded file name: %s" % co.co_filename,)
if timestamp: if timestamp:
write('# Compiled at: %s' % datetime.datetime.fromtimestamp(timestamp)) write("# Compiled at: %s" % datetime.datetime.fromtimestamp(timestamp))
if source_size: if source_size:
write('# Size of source mod 2**32: %d bytes' % source_size) write("# Size of source mod 2**32: %d bytes" % source_size)
debug_opts = { debug_opts = {"asm": showasm, "ast": showast, "grammar": showgrammar}
'asm': showasm,
'ast': showast,
'grammar': showgrammar
}
try: try:
if mapstream: if mapstream:
if isinstance(mapstream, str): if isinstance(mapstream, str):
mapstream = _get_outstream(mapstream) mapstream = _get_outstream(mapstream)
deparsed = deparse_code_with_map(bytecode_version, co, out, showasm, showast, deparsed = deparse_code_with_map(
showgrammar, bytecode_version,
code_objects = code_objects, co,
is_pypy = is_pypy, out,
) showasm,
header_count = 3+len(sys_version_lines) showast,
linemap = [(line_no, deparsed.source_linemap[line_no]+header_count) showgrammar,
for line_no in code_objects=code_objects,
sorted(deparsed.source_linemap.keys())] is_pypy=is_pypy,
)
header_count = 3 + len(sys_version_lines)
linemap = [
(line_no, deparsed.source_linemap[line_no] + header_count)
for line_no in sorted(deparsed.source_linemap.keys())
]
mapstream.write("\n\n# %s\n" % linemap) mapstream.write("\n\n# %s\n" % linemap)
else: else:
if do_fragments: if do_fragments:
deparse_fn = code_deparse_fragments deparse_fn = code_deparse_fragments
else: else:
deparse_fn = code_deparse deparse_fn = code_deparse
deparsed = deparse_fn(co, out, bytecode_version, deparsed = deparse_fn(
debug_opts = debug_opts, co, out, bytecode_version, debug_opts=debug_opts, is_pypy=is_pypy
is_pypy=is_pypy) )
pass pass
return deparsed return deparsed
except pysource.SourceWalkerError as e: except pysource.SourceWalkerError as e:
# deparsing failed # deparsing failed
raise pysource.SourceWalkerError(str(e)) raise pysource.SourceWalkerError(str(e))
def compile_file(source_path): def compile_file(source_path):
if source_path.endswith('.py'): if source_path.endswith(".py"):
basename = source_path[:-3] basename = source_path[:-3]
else: else:
basename = source_path basename = source_path
if hasattr(sys, 'pypy_version_info'): if hasattr(sys, "pypy_version_info"):
bytecode_path = "%s-pypy%s.pyc" % (basename, PYTHON_VERSION) bytecode_path = "%s-pypy%s.pyc" % (basename, PYTHON_VERSION)
else: else:
bytecode_path = "%s-%s.pyc" % (basename, PYTHON_VERSION) bytecode_path = "%s-%s.pyc" % (basename, PYTHON_VERSION)
print("compiling %s to %s" % (source_path, bytecode_path)) print("compiling %s to %s" % (source_path, bytecode_path))
py_compile.compile(source_path, bytecode_path, 'exec') py_compile.compile(source_path, bytecode_path, "exec")
return bytecode_path return bytecode_path
def decompile_file(filename, outstream=None, showasm=None, showast=False, def decompile_file(
showgrammar=False, source_encoding=None, mapstream=None, do_fragments=False): filename,
outstream=None,
showasm=None,
showast=False,
showgrammar=False,
source_encoding=None,
mapstream=None,
do_fragments=False,
):
""" """
decompile Python byte-code file (.pyc). Return objects to decompile Python byte-code file (.pyc). Return objects to
all of the deparsed objects found in `filename`. all of the deparsed objects found in `filename`.
@@ -157,32 +178,68 @@ def decompile_file(filename, outstream=None, showasm=None, showast=False,
filename = check_object_path(filename) filename = check_object_path(filename)
code_objects = {} code_objects = {}
(version, timestamp, magic_int, co, is_pypy, (version, timestamp, magic_int, co, is_pypy, source_size) = load_module(
source_size) = load_module(filename, code_objects) filename, code_objects
)
if isinstance(co, list): if isinstance(co, list):
deparsed = [] deparsed = []
for con in co: for con in co:
deparsed.append( deparsed.append(
decompile(version, con, outstream, showasm, showast, decompile(
timestamp, showgrammar, source_encoding, code_objects=code_objects, version,
is_pypy=is_pypy, magic_int=magic_int), con,
mapstream=mapstream) outstream,
showasm,
showast,
timestamp,
showgrammar,
source_encoding,
code_objects=code_objects,
is_pypy=is_pypy,
magic_int=magic_int,
),
mapstream=mapstream,
)
else: else:
deparsed = [decompile(version, co, outstream, showasm, showast, deparsed = [
timestamp, showgrammar, source_encoding, decompile(
code_objects=code_objects, source_size=source_size, version,
is_pypy=is_pypy, magic_int=magic_int, co,
mapstream=mapstream, do_fragments=do_fragments)] outstream,
showasm,
showast,
timestamp,
showgrammar,
source_encoding,
code_objects=code_objects,
source_size=source_size,
is_pypy=is_pypy,
magic_int=magic_int,
mapstream=mapstream,
do_fragments=do_fragments,
)
]
co = None co = None
return deparsed return deparsed
# FIXME: combine into an options parameter # FIXME: combine into an options parameter
def main(in_base, out_base, compiled_files, source_files, outfile=None, def main(
showasm=None, showast=False, do_verify=False, in_base,
showgrammar=False, source_encoding=None, raise_on_error=False, out_base,
do_linemaps=False, do_fragments=False): compiled_files,
source_files,
outfile=None,
showasm=None,
showast=False,
do_verify=False,
showgrammar=False,
source_encoding=None,
raise_on_error=False,
do_linemaps=False,
do_fragments=False,
):
""" """
in_base base directory for input files in_base base directory for input files
out_base base directory for output files (ignored when out_base base directory for output files (ignored when
@@ -205,49 +262,46 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
infile = os.path.join(in_base, filename) infile = os.path.join(in_base, filename)
# print("XXX", infile) # print("XXX", infile)
if not os.path.exists(infile): if not os.path.exists(infile):
sys.stderr.write("File '%s' doesn't exist. Skipped\n" sys.stderr.write("File '%s' doesn't exist. Skipped\n" % infile)
% infile)
continue continue
if do_linemaps: if do_linemaps:
linemap_stream = infile + '.pymap' linemap_stream = infile + ".pymap"
pass pass
# print (infile, file=sys.stderr) # print (infile, file=sys.stderr)
if outfile: # outfile was given as parameter if outfile: # outfile was given as parameter
outstream = _get_outstream(outfile) outstream = _get_outstream(outfile)
elif out_base is None: elif out_base is None:
outstream = sys.stdout outstream = sys.stdout
if do_linemaps: if do_linemaps:
linemap_stream = sys.stdout linemap_stream = sys.stdout
if do_verify: if do_verify:
prefix = os.path.basename(filename) + '-' prefix = os.path.basename(filename) + "-"
if prefix.endswith('.py'): if prefix.endswith(".py"):
prefix = prefix[:-len('.py')] prefix = prefix[: -len(".py")]
# Unbuffer output if possible # Unbuffer output if possible
buffering = -1 if sys.stdout.isatty() else 0 buffering = -1 if sys.stdout.isatty() else 0
if PYTHON_VERSION >= 3.5: if PYTHON_VERSION >= 3.5:
t = tempfile.NamedTemporaryFile(mode='w+b', t = tempfile.NamedTemporaryFile(
buffering=buffering, mode="w+b", buffering=buffering, suffix=".py", prefix=prefix
suffix='.py', )
prefix=prefix)
else: else:
t = tempfile.NamedTemporaryFile(mode='w+b', t = tempfile.NamedTemporaryFile(
suffix='.py', mode="w+b", suffix=".py", prefix=prefix
prefix=prefix) )
current_outfile = t.name current_outfile = t.name
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering) sys.stdout = os.fdopen(sys.stdout.fileno(), "w", buffering)
tee = subprocess.Popen(["tee", current_outfile], tee = subprocess.Popen(["tee", current_outfile], stdin=subprocess.PIPE)
stdin=subprocess.PIPE)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno()) os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno()) os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
else: else:
if filename.endswith('.pyc'): if filename.endswith(".pyc"):
current_outfile = os.path.join(out_base, filename[0:-1]) current_outfile = os.path.join(out_base, filename[0:-1])
else: else:
current_outfile = os.path.join(out_base, filename) + '_dis' current_outfile = os.path.join(out_base, filename) + "_dis"
pass pass
pass pass
@@ -257,15 +311,25 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
# Try to uncompile the input file # Try to uncompile the input file
try: try:
deparsed = decompile_file(infile, outstream, showasm, showast, showgrammar, deparsed = decompile_file(
source_encoding, linemap_stream, do_fragments) infile,
outstream,
showasm,
showast,
showgrammar,
source_encoding,
linemap_stream,
do_fragments,
)
if do_fragments: if do_fragments:
for d in deparsed: for d in deparsed:
last_mod = None last_mod = None
offsets = d.offsets offsets = d.offsets
for e in sorted([k for k in offsets.keys() if isinstance(k[1], int)]): for e in sorted(
[k for k in offsets.keys() if isinstance(k[1], int)]
):
if e[0] != last_mod: if e[0] != last_mod:
line = '=' * len(e[0]) line = "=" * len(e[0])
outstream.write("%s\n%s\n%s\n" % (line, e[0], line)) outstream.write("%s\n%s\n%s\n" % (line, e[0], line))
last_mod = e[0] last_mod = e[0]
info = offsets[e] info = offsets[e]
@@ -290,9 +354,11 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
raise raise
except RuntimeError as e: except RuntimeError as e:
sys.stdout.write("\n%s\n" % str(e)) sys.stdout.write("\n%s\n" % str(e))
if str(e).startswith('Unsupported Python'): if str(e).startswith("Unsupported Python"):
sys.stdout.write("\n") sys.stdout.write("\n")
sys.stderr.write("\n# Unsupported bytecode in file %s\n# %s\n" % (infile, e)) sys.stderr.write(
"\n# Unsupported bytecode in file %s\n# %s\n" % (infile, e)
)
else: else:
if outfile: if outfile:
outstream.close() outstream.close()
@@ -309,22 +375,22 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
# else: # else:
# sys.stderr.write("\n# %s" % sys.exc_info()[1]) # sys.stderr.write("\n# %s" % sys.exc_info()[1])
# sys.stderr.write("\n# Can't uncompile %s\n" % infile) # sys.stderr.write("\n# Can't uncompile %s\n" % infile)
else: # uncompile successful else: # uncompile successful
if current_outfile: if current_outfile:
outstream.close() outstream.close()
if do_verify: if do_verify:
try: try:
msg = verify.compare_code_with_srcfile(infile, msg = verify.compare_code_with_srcfile(
current_outfile, infile, current_outfile, do_verify
do_verify) )
if not current_outfile: if not current_outfile:
if not msg: if not msg:
print('\n# okay decompiling %s' % infile) print("\n# okay decompiling %s" % infile)
okay_files += 1 okay_files += 1
else: else:
verify_failed_files += 1 verify_failed_files += 1
print('\n# %s\n\t%s', infile, msg) print("\n# %s\n\t%s", infile, msg)
pass pass
else: else:
okay_files += 1 okay_files += 1
@@ -332,7 +398,7 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
except verify.VerifyCmpError as e: except verify.VerifyCmpError as e:
print(e) print(e)
verify_failed_files += 1 verify_failed_files += 1
os.rename(current_outfile, current_outfile + '_unverified') os.rename(current_outfile, current_outfile + "_unverified")
sys.stderr.write("### Error Verifying %s\n" % filename) sys.stderr.write("### Error Verifying %s\n" % filename)
sys.stderr.write(str(e) + "\n") sys.stderr.write(str(e) + "\n")
if not outfile: if not outfile:
@@ -345,18 +411,31 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
okay_files += 1 okay_files += 1
pass pass
elif do_verify: elif do_verify:
sys.stderr.write("\n### uncompile successful, but no file to compare against\n") sys.stderr.write(
"\n### uncompile successful, but no file to compare against\n"
)
pass pass
else: else:
okay_files += 1 okay_files += 1
if not current_outfile: if not current_outfile:
mess = '\n# okay decompiling' mess = "\n# okay decompiling"
# mem_usage = __memUsage() # mem_usage = __memUsage()
print(mess, infile) print(mess, infile)
if current_outfile: if current_outfile:
sys.stdout.write("%s -- %s\r" % sys.stdout.write(
(infile, status_msg(do_verify, tot_files, okay_files, failed_files, "%s -- %s\r"
verify_failed_files, do_verify))) % (
infile,
status_msg(
do_verify,
tot_files,
okay_files,
failed_files,
verify_failed_files,
do_verify,
),
)
)
try: try:
# FIXME: Something is weird with Pypy here # FIXME: Something is weird with Pypy here
sys.stdout.flush() sys.stdout.flush()
@@ -375,24 +454,30 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
# ---- main ---- # ---- main ----
if sys.platform.startswith('linux') and os.uname()[2][:2] in ['2.', '3.', '4.']: if sys.platform.startswith("linux") and os.uname()[2][:2] in ["2.", "3.", "4."]:
def __memUsage(): def __memUsage():
mi = open('/proc/self/stat', 'r') mi = open("/proc/self/stat", "r")
mu = mi.readline().split()[22] mu = mi.readline().split()[22]
mi.close() mi.close()
return int(mu) / 1000000 return int(mu) / 1000000
else:
def __memUsage():
return ''
def status_msg(do_verify, tot_files, okay_files, failed_files,
verify_failed_files, weak_verify): else:
if weak_verify == 'weak':
verification_type = 'weak ' def __memUsage():
elif weak_verify == 'verify-run': return ""
verification_type = 'run '
def status_msg(
do_verify, tot_files, okay_files, failed_files, verify_failed_files, weak_verify
):
if weak_verify == "weak":
verification_type = "weak "
elif weak_verify == "verify-run":
verification_type = "run "
else: else:
verification_type = '' verification_type = ""
if tot_files == 1: if tot_files == 1:
if failed_files: if failed_files:
return "\n# decompile failed" return "\n# decompile failed"
@@ -402,7 +487,11 @@ def status_msg(do_verify, tot_files, okay_files, failed_files,
return "\n# Successfully decompiled file" return "\n# Successfully decompiled file"
pass pass
pass pass
mess = "decompiled %i files: %i okay, %i failed" % (tot_files, okay_files, failed_files) mess = "decompiled %i files: %i okay, %i failed" % (
tot_files,
okay_files,
failed_files,
)
if do_verify: if do_verify:
mess += (", %i %sverification failed" % (verify_failed_files, verification_type)) mess += ", %i %sverification failed" % (verify_failed_files, verification_type)
return mess return mess