You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
blacken main.py
This commit is contained in:
@@ -22,17 +22,19 @@ from uncompyle6.disas import check_object_path
|
||||
from uncompyle6.semantics import pysource
|
||||
from uncompyle6.parser import ParserError
|
||||
from uncompyle6.version import VERSION
|
||||
|
||||
# from uncompyle6.linenumbers import line_number_mapping
|
||||
|
||||
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 xdis.load import load_module
|
||||
|
||||
|
||||
def _get_outstream(outfile):
|
||||
dir = os.path.dirname(outfile)
|
||||
failed_file = outfile + '_failed'
|
||||
failed_file = outfile + "_failed"
|
||||
if os.path.exists(failed_file):
|
||||
os.remove(failed_file)
|
||||
try:
|
||||
@@ -40,9 +42,10 @@ def _get_outstream(outfile):
|
||||
except OSError:
|
||||
pass
|
||||
if PYTHON_VERSION < 3.0:
|
||||
return open(outfile, mode='wb')
|
||||
return open(outfile, mode="wb")
|
||||
else:
|
||||
return open(outfile, mode='w', encoding='utf-8')
|
||||
return open(outfile, mode="w", encoding="utf-8")
|
||||
|
||||
|
||||
def decompile(
|
||||
bytecode_version,
|
||||
@@ -75,81 +78,99 @@ def decompile(
|
||||
real_out = out or sys.stdout
|
||||
|
||||
def write(s):
|
||||
s += '\n'
|
||||
s += "\n"
|
||||
real_out.write(s)
|
||||
|
||||
assert iscode(co)
|
||||
|
||||
co_pypy_str = 'PyPy ' if is_pypy else ''
|
||||
run_pypy_str = 'PyPy ' if IS_PYPY else ''
|
||||
sys_version_lines = sys.version.split('\n')
|
||||
co_pypy_str = "PyPy " if is_pypy else ""
|
||||
run_pypy_str = "PyPy " if IS_PYPY else ""
|
||||
sys_version_lines = sys.version.split("\n")
|
||||
if source_encoding:
|
||||
write('# -*- coding: %s -*-' % source_encoding)
|
||||
write('# uncompyle6 version %s\n'
|
||||
'# %sPython bytecode %s%s\n# Decompiled from: %sPython %s' %
|
||||
(VERSION, co_pypy_str, bytecode_version,
|
||||
" (%s)" % str(magic_int) if magic_int else "",
|
||||
run_pypy_str, '\n# '.join(sys_version_lines)))
|
||||
write("# -*- coding: %s -*-" % source_encoding)
|
||||
write(
|
||||
"# uncompyle6 version %s\n"
|
||||
"# %sPython bytecode %s%s\n# Decompiled from: %sPython %s"
|
||||
% (
|
||||
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:
|
||||
write('# Embedded file name: %s' % co.co_filename,)
|
||||
write("# Embedded file name: %s" % co.co_filename,)
|
||||
if timestamp:
|
||||
write('# Compiled at: %s' % datetime.datetime.fromtimestamp(timestamp))
|
||||
write("# Compiled at: %s" % datetime.datetime.fromtimestamp(timestamp))
|
||||
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 = {
|
||||
'asm': showasm,
|
||||
'ast': showast,
|
||||
'grammar': showgrammar
|
||||
}
|
||||
debug_opts = {"asm": showasm, "ast": showast, "grammar": showgrammar}
|
||||
|
||||
try:
|
||||
if mapstream:
|
||||
if isinstance(mapstream, str):
|
||||
mapstream = _get_outstream(mapstream)
|
||||
|
||||
deparsed = deparse_code_with_map(bytecode_version, co, out, showasm, showast,
|
||||
showgrammar,
|
||||
code_objects = code_objects,
|
||||
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())]
|
||||
deparsed = deparse_code_with_map(
|
||||
bytecode_version,
|
||||
co,
|
||||
out,
|
||||
showasm,
|
||||
showast,
|
||||
showgrammar,
|
||||
code_objects=code_objects,
|
||||
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)
|
||||
else:
|
||||
if do_fragments:
|
||||
deparse_fn = code_deparse_fragments
|
||||
else:
|
||||
deparse_fn = code_deparse
|
||||
deparsed = deparse_fn(co, out, bytecode_version,
|
||||
debug_opts = debug_opts,
|
||||
is_pypy=is_pypy)
|
||||
deparsed = deparse_fn(
|
||||
co, out, bytecode_version, debug_opts=debug_opts, is_pypy=is_pypy
|
||||
)
|
||||
pass
|
||||
return deparsed
|
||||
except pysource.SourceWalkerError as e:
|
||||
# deparsing failed
|
||||
raise pysource.SourceWalkerError(str(e))
|
||||
|
||||
|
||||
def compile_file(source_path):
|
||||
if source_path.endswith('.py'):
|
||||
if source_path.endswith(".py"):
|
||||
basename = source_path[:-3]
|
||||
else:
|
||||
basename = source_path
|
||||
|
||||
if hasattr(sys, 'pypy_version_info'):
|
||||
if hasattr(sys, "pypy_version_info"):
|
||||
bytecode_path = "%s-pypy%s.pyc" % (basename, PYTHON_VERSION)
|
||||
else:
|
||||
bytecode_path = "%s-%s.pyc" % (basename, PYTHON_VERSION)
|
||||
|
||||
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
|
||||
|
||||
|
||||
def decompile_file(filename, outstream=None, showasm=None, showast=False,
|
||||
showgrammar=False, source_encoding=None, mapstream=None, do_fragments=False):
|
||||
def decompile_file(
|
||||
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
|
||||
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)
|
||||
code_objects = {}
|
||||
(version, timestamp, magic_int, co, is_pypy,
|
||||
source_size) = load_module(filename, code_objects)
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size) = load_module(
|
||||
filename, code_objects
|
||||
)
|
||||
|
||||
if isinstance(co, list):
|
||||
deparsed = []
|
||||
for con in co:
|
||||
deparsed.append(
|
||||
decompile(version, con, outstream, showasm, showast,
|
||||
timestamp, showgrammar, source_encoding, code_objects=code_objects,
|
||||
is_pypy=is_pypy, magic_int=magic_int),
|
||||
mapstream=mapstream)
|
||||
decompile(
|
||||
version,
|
||||
con,
|
||||
outstream,
|
||||
showasm,
|
||||
showast,
|
||||
timestamp,
|
||||
showgrammar,
|
||||
source_encoding,
|
||||
code_objects=code_objects,
|
||||
is_pypy=is_pypy,
|
||||
magic_int=magic_int,
|
||||
),
|
||||
mapstream=mapstream,
|
||||
)
|
||||
else:
|
||||
deparsed = [decompile(version, co, 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)]
|
||||
deparsed = [
|
||||
decompile(
|
||||
version,
|
||||
co,
|
||||
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
|
||||
return deparsed
|
||||
|
||||
|
||||
# FIXME: combine into an options parameter
|
||||
def main(in_base, out_base, 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):
|
||||
def main(
|
||||
in_base,
|
||||
out_base,
|
||||
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
|
||||
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)
|
||||
# print("XXX", infile)
|
||||
if not os.path.exists(infile):
|
||||
sys.stderr.write("File '%s' doesn't exist. Skipped\n"
|
||||
% infile)
|
||||
sys.stderr.write("File '%s' doesn't exist. Skipped\n" % infile)
|
||||
continue
|
||||
|
||||
if do_linemaps:
|
||||
linemap_stream = infile + '.pymap'
|
||||
linemap_stream = infile + ".pymap"
|
||||
pass
|
||||
|
||||
# print (infile, file=sys.stderr)
|
||||
|
||||
if outfile: # outfile was given as parameter
|
||||
if outfile: # outfile was given as parameter
|
||||
outstream = _get_outstream(outfile)
|
||||
elif out_base is None:
|
||||
outstream = sys.stdout
|
||||
if do_linemaps:
|
||||
linemap_stream = sys.stdout
|
||||
if do_verify:
|
||||
prefix = os.path.basename(filename) + '-'
|
||||
if prefix.endswith('.py'):
|
||||
prefix = prefix[:-len('.py')]
|
||||
prefix = os.path.basename(filename) + "-"
|
||||
if prefix.endswith(".py"):
|
||||
prefix = prefix[: -len(".py")]
|
||||
|
||||
# Unbuffer output if possible
|
||||
buffering = -1 if sys.stdout.isatty() else 0
|
||||
if PYTHON_VERSION >= 3.5:
|
||||
t = tempfile.NamedTemporaryFile(mode='w+b',
|
||||
buffering=buffering,
|
||||
suffix='.py',
|
||||
prefix=prefix)
|
||||
t = tempfile.NamedTemporaryFile(
|
||||
mode="w+b", buffering=buffering, suffix=".py", prefix=prefix
|
||||
)
|
||||
else:
|
||||
t = tempfile.NamedTemporaryFile(mode='w+b',
|
||||
suffix='.py',
|
||||
prefix=prefix)
|
||||
t = tempfile.NamedTemporaryFile(
|
||||
mode="w+b", suffix=".py", prefix=prefix
|
||||
)
|
||||
current_outfile = t.name
|
||||
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering)
|
||||
tee = subprocess.Popen(["tee", current_outfile],
|
||||
stdin=subprocess.PIPE)
|
||||
sys.stdout = os.fdopen(sys.stdout.fileno(), "w", buffering)
|
||||
tee = subprocess.Popen(["tee", current_outfile], stdin=subprocess.PIPE)
|
||||
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
|
||||
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
|
||||
else:
|
||||
if filename.endswith('.pyc'):
|
||||
if filename.endswith(".pyc"):
|
||||
current_outfile = os.path.join(out_base, filename[0:-1])
|
||||
else:
|
||||
current_outfile = os.path.join(out_base, filename) + '_dis'
|
||||
current_outfile = os.path.join(out_base, filename) + "_dis"
|
||||
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:
|
||||
deparsed = decompile_file(infile, outstream, showasm, showast, showgrammar,
|
||||
source_encoding, linemap_stream, do_fragments)
|
||||
deparsed = decompile_file(
|
||||
infile,
|
||||
outstream,
|
||||
showasm,
|
||||
showast,
|
||||
showgrammar,
|
||||
source_encoding,
|
||||
linemap_stream,
|
||||
do_fragments,
|
||||
)
|
||||
if do_fragments:
|
||||
for d in deparsed:
|
||||
last_mod = None
|
||||
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:
|
||||
line = '=' * len(e[0])
|
||||
line = "=" * len(e[0])
|
||||
outstream.write("%s\n%s\n%s\n" % (line, e[0], line))
|
||||
last_mod = e[0]
|
||||
info = offsets[e]
|
||||
@@ -290,9 +354,11 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
|
||||
raise
|
||||
except RuntimeError as 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.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:
|
||||
if outfile:
|
||||
outstream.close()
|
||||
@@ -309,22 +375,22 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
|
||||
# else:
|
||||
# sys.stderr.write("\n# %s" % sys.exc_info()[1])
|
||||
# sys.stderr.write("\n# Can't uncompile %s\n" % infile)
|
||||
else: # uncompile successful
|
||||
else: # uncompile successful
|
||||
if current_outfile:
|
||||
outstream.close()
|
||||
|
||||
if do_verify:
|
||||
try:
|
||||
msg = verify.compare_code_with_srcfile(infile,
|
||||
current_outfile,
|
||||
do_verify)
|
||||
msg = verify.compare_code_with_srcfile(
|
||||
infile, current_outfile, do_verify
|
||||
)
|
||||
if not current_outfile:
|
||||
if not msg:
|
||||
print('\n# okay decompiling %s' % infile)
|
||||
print("\n# okay decompiling %s" % infile)
|
||||
okay_files += 1
|
||||
else:
|
||||
verify_failed_files += 1
|
||||
print('\n# %s\n\t%s', infile, msg)
|
||||
print("\n# %s\n\t%s", infile, msg)
|
||||
pass
|
||||
else:
|
||||
okay_files += 1
|
||||
@@ -332,7 +398,7 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
|
||||
except verify.VerifyCmpError as e:
|
||||
print(e)
|
||||
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(str(e) + "\n")
|
||||
if not outfile:
|
||||
@@ -345,18 +411,31 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
|
||||
okay_files += 1
|
||||
pass
|
||||
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
|
||||
else:
|
||||
okay_files += 1
|
||||
if not current_outfile:
|
||||
mess = '\n# okay decompiling'
|
||||
mess = "\n# okay decompiling"
|
||||
# mem_usage = __memUsage()
|
||||
print(mess, infile)
|
||||
if current_outfile:
|
||||
sys.stdout.write("%s -- %s\r" %
|
||||
(infile, status_msg(do_verify, tot_files, okay_files, failed_files,
|
||||
verify_failed_files, do_verify)))
|
||||
sys.stdout.write(
|
||||
"%s -- %s\r"
|
||||
% (
|
||||
infile,
|
||||
status_msg(
|
||||
do_verify,
|
||||
tot_files,
|
||||
okay_files,
|
||||
failed_files,
|
||||
verify_failed_files,
|
||||
do_verify,
|
||||
),
|
||||
)
|
||||
)
|
||||
try:
|
||||
# FIXME: Something is weird with Pypy here
|
||||
sys.stdout.flush()
|
||||
@@ -375,24 +454,30 @@ def main(in_base, out_base, compiled_files, source_files, outfile=None,
|
||||
|
||||
# ---- 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():
|
||||
mi = open('/proc/self/stat', 'r')
|
||||
mi = open("/proc/self/stat", "r")
|
||||
mu = mi.readline().split()[22]
|
||||
mi.close()
|
||||
return int(mu) / 1000000
|
||||
else:
|
||||
def __memUsage():
|
||||
return ''
|
||||
|
||||
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:
|
||||
|
||||
def __memUsage():
|
||||
return ""
|
||||
|
||||
|
||||
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:
|
||||
verification_type = ''
|
||||
verification_type = ""
|
||||
if tot_files == 1:
|
||||
if failed_files:
|
||||
return "\n# decompile failed"
|
||||
@@ -402,7 +487,11 @@ def status_msg(do_verify, tot_files, okay_files, failed_files,
|
||||
return "\n# Successfully decompiled file"
|
||||
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:
|
||||
mess += (", %i %sverification failed" % (verify_failed_files, verification_type))
|
||||
mess += ", %i %sverification failed" % (verify_failed_files, verification_type)
|
||||
return mess
|
||||
|
Reference in New Issue
Block a user