Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if `bytecode_version` is None, use the current Python intepreter
version.
Caller is responsible for closing `out` and `mapstream`
"""
if bytecode_version is None:
bytecode_version = sysinfo2float()
# store final output stream for case of error
real_out = out or sys.stdout
def write(s):
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")
if source_encoding:
write("# -*- coding: %s -*-" % source_encoding)
write(
"# decompyle3 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),
def is_async_fn(node):
code_node = node[0][0]
for n in node[0]:
if hasattr(n, "attr") and iscode(n.attr):
code_node = n
break
pass
pass
is_code = hasattr(code_node, "attr") and iscode(code_node.attr)
return is_code and co_flags_is_async(code_node.attr.co_flags)
):
"""
Parse a code object to an abstract syntax tree representation.
:param version: The python version this code is from as a float, for
example 2.6, 2.7, 3.2, 3.3, 3.4, 3.5 etc.
:param co: The code object to parse.
:param out: File like object to write the output to.
:param showasm: Flag which determines whether the disassembled and
ingested code is written to sys.stdout or not.
:param parser_debug: dict containing debug flags for the spark parser.
:return: Abstract syntax tree representation of the code object.
"""
assert iscode(co)
from decompyle3.scanner import get_scanner
scanner = get_scanner(version, is_pypy)
tokens, customize = scanner.ingest(co)
maybe_show_asm(showasm, tokens)
# For heavy grammar debugging
# parser_debug = {'rules': True, 'transition': True, 'reduce' : True,
# 'showstack': 'full'}
p = get_python_parser(version, parser_debug)
return parse(p, tokens, customize, is_lambda)
class_name = node[1][1].attr
else:
class_name = node[1][2].attr
build_class = node
else:
build_class = node[0]
if build_class == "build_class_kw":
mkfunc = build_class[1]
assert mkfunc == "mkfunc"
subclass_info = build_class
if hasattr(mkfunc[0], "attr") and iscode(mkfunc[0].attr):
subclass_code = mkfunc[0].attr
else:
assert mkfunc[0] == "load_closure"
subclass_code = mkfunc[1].attr
assert iscode(subclass_code)
if build_class[1][0] == "load_closure":
code_node = build_class[1][1]
else:
code_node = build_class[1][0]
class_name = code_node.attr.co_name
assert "mkfunc" == build_class[1]
mkfunc = build_class[1]
if mkfunc[0] in ("kwargs", "no_kwargs"):
for n in mkfunc:
if hasattr(n, "attr") and iscode(n.attr):
subclass_code = n.attr
break
pass
if node == "classdefdeco2":
subclass_info = node
def comprehension_walk3(self, node, iter_index, code_index=-5):
"""
List comprehensions the way they are done in Python3.
They're more other comprehensions, e.g. set comprehensions
See if we can combine code.
"""
p = self.prec
self.prec = 27
code = node[code_index].attr
assert iscode(code), node[code_index]
code_name = code.co_name
code = Code(code, self.scanner, self.currentclass)
ast = self.build_ast(code._tokens, code._customize)
self.customize(code._customize)
if ast[0] == "sstmt":
ast = ast[0]
# skip over stmt return ret_expr
ast = ast[0][0][0]
store = None
if ast in ["set_comp_func", "dict_comp_func"]:
# Offset 0: BUILD_SET should have the span
# of '{'
self.gen_source(ast, code_name, {})
def n_mkfunc(self, node):
# MAKE_FUNCTION ..
code_node = node[-3]
if not iscode(code_node.attr):
# docstring exists
code_node = node[-4]
code = code_node.attr
assert iscode(code)
func_name = code.co_name
self.write(func_name)
self.indent_more()
make_function36(self, node, is_lambda=False, code_node=code_node)
if len(self.param_stack) > 1:
self.write("\n\n")
else:
def find_code_node(node, start: int):
for i in range(-start, len(node) + 1):
if node[-i].kind == "LOAD_CODE":
code_node = node[-i]
assert iscode(code_node.attr)
return code_node
pass
assert False, "did not find code node starting at %d in %s" % (start, node)
def build_class(self, code):
"""Dump class definition, doc string and class body."""
assert iscode(code)
self.classes.append(self.currentclass)
code = Code(code, self.scanner, self.currentclass)
indent = self.indent
# self.println(indent, '#flags:\t', int(code.co_flags))
ast = self.build_ast(code._tokens, code._customize)
# save memory by deleting no-longer-used structures
code._tokens = None
assert ast == "stmts"
if ast[0] == "docstring":
self.println(self.traverse(ast[0]))
del ast[0]