You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
Merge branch 'python-3.0-to-3.2' into python-2.4
This commit is contained in:
10
.github/ISSUE_TEMPLATE/bug-report.md
vendored
10
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -5,11 +5,11 @@ about: Tell us about uncompyle6 bugs
|
||||
---
|
||||
|
||||
<!-- __Note:__ If you are using this program to do something illegal - don't.
|
||||
The issue may flagged to make it easier for those looking for illegal activity.
|
||||
The issue may be flagged to make it easier for those looking for illegal activity.
|
||||
|
||||
Bugs are not for asking questions about a problem you
|
||||
are trying to solve that involve the use of uncompyle6 along the way,
|
||||
although I may be more tolerent of this if you sponsor the project.
|
||||
although I may be more tolerant of this if you sponsor the project.
|
||||
|
||||
Bugs are also not for general or novice kind help on how to install
|
||||
this Python program in your environment in the way you would like to
|
||||
@@ -33,7 +33,7 @@ Funding the project was added to partially address the problem that there are
|
||||
lots of people seeking help and reporting bugs, but few people who are
|
||||
willing or capable of providing help or fixing bugs.
|
||||
|
||||
Tasks or the kinds of things others can do but you can't do or don't
|
||||
Tasks or the kinds of things others can do, but you can't do or don't
|
||||
want to do yourself are typically the kind of thing that you pay
|
||||
someone to do, especially when you are the primary beneficiary of the
|
||||
work, or the task is complex, long, or tedious. If your code is over
|
||||
@@ -56,7 +56,7 @@ Prerequisites/Caveats
|
||||
contact me by email and explain who you are and the need for privacy.
|
||||
But be mindful that you may be asked to sponsor the project for the
|
||||
personal and private help that you are requesting.
|
||||
* If the legitimacy of the activity is deemed suspicous, I may flag it as suspicious,
|
||||
* If the legitimacy of the activity is deemed suspicious, I may flag it as suspicious,
|
||||
making the issue even more easy to detect.
|
||||
|
||||
Bug reports that violate the above may be discarded.
|
||||
@@ -80,7 +80,7 @@ $ uncompyle6 <command-line-options>
|
||||
$
|
||||
```
|
||||
|
||||
Provide links to the Python bytecode. For example you can create a
|
||||
Provide links to the Python bytecode. For example, you can create a
|
||||
gist with the information. If you have the correct source code, you
|
||||
can add that too.
|
||||
|
||||
|
11
.isort.cfg
Normal file
11
.isort.cfg
Normal file
@@ -0,0 +1,11 @@
|
||||
[settings]
|
||||
multi_line_output = 3
|
||||
include_trailing_comma = True
|
||||
force_grid_wrap = 0
|
||||
use_parentheses = True
|
||||
line_length = 88
|
||||
known_crunch = cr, zz9d, zz9lib, pycrunch, silhouette
|
||||
sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,CRUNCH,LOCALFOLDER
|
||||
default_section = THIRDPARTY
|
||||
combine_as_imports = 1
|
||||
profile = black
|
BIN
test/bytecode_3.7/02_while1_if_while1.pyc
Normal file
BIN
test/bytecode_3.7/02_while1_if_while1.pyc
Normal file
Binary file not shown.
@@ -193,9 +193,9 @@ def main_bin():
|
||||
try:
|
||||
result = main(src_base, out_base, pyc_paths, source_paths, outfile,
|
||||
**options)
|
||||
result = list(result) + [options.get('do_verify', None)]
|
||||
result = [options.get('do_verify', None)] + list(result)
|
||||
if len(pyc_paths) > 1:
|
||||
mess = status_msg(do_verify, *result)
|
||||
mess = status_msg(*result)
|
||||
print('# ' + mess)
|
||||
pass
|
||||
except ImportError:
|
||||
|
@@ -545,7 +545,7 @@ if __name__ == "__main__":
|
||||
# Check grammar
|
||||
p = Python26Parser()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (2, 6):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2016-2020 Rocky Bernstein
|
||||
# Copyright (c) 2016-2020, 2022 Rocky Bernstein
|
||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <hartmut@goebel.noris.de>
|
||||
|
||||
@@ -375,11 +375,11 @@ if __name__ == "__main__":
|
||||
# Check grammar
|
||||
p = Python27Parser()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (2, 7):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2016-2017 Rocky Bernstein
|
||||
# Copyright (c) 2016-2017, 2022 Rocky Bernstein
|
||||
"""
|
||||
spark grammar differences over Python 3.1 for Python 3.0.
|
||||
"""
|
||||
@@ -364,11 +364,11 @@ if __name__ == '__main__':
|
||||
p = Python30Parser()
|
||||
p.remove_rules_30()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 0):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2016-2017 Rocky Bernstein
|
||||
# Copyright (c) 2016-2017, 2022 Rocky Bernstein
|
||||
"""
|
||||
spark grammar differences over Python 3.2 for Python 3.1.
|
||||
"""
|
||||
@@ -55,11 +55,11 @@ if __name__ == '__main__':
|
||||
p = Python31Parser()
|
||||
p.remove_rules_31()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 1):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2017-2018 Rocky Bernstein
|
||||
# Copyright (c) 2017-2018, 2022 Rocky Bernstein
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -70,11 +70,11 @@ if __name__ == '__main__':
|
||||
# Check grammar
|
||||
p = Python34Parser()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE == (3, 4):
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 4):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2016-2017, 2019, 2021 Rocky Bernstein
|
||||
# Copyright (c) 2016-2017, 2019, 2021-2022 Rocky Bernstein
|
||||
"""
|
||||
spark grammar differences over Python 3.4 for Python 3.5.
|
||||
"""
|
||||
@@ -272,11 +272,11 @@ if __name__ == '__main__':
|
||||
# Check grammar
|
||||
p = Python35Parser()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 5):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
||||
|
@@ -672,11 +672,11 @@ if __name__ == '__main__':
|
||||
# Check grammar
|
||||
p = Python36Parser()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 6):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
|
||||
|
@@ -1739,13 +1739,13 @@ if __name__ == "__main__":
|
||||
# FIXME: DRY this with other parseXX.py routines
|
||||
p = Python37Parser()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 7):
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 7):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(
|
||||
set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
|
@@ -609,13 +609,13 @@ if __name__ == "__main__":
|
||||
p = Python38Parser()
|
||||
p.remove_rules_38()
|
||||
p.check_grammar()
|
||||
from xdis import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
from xdis.version_info import PYTHON_VERSION_TRIPLE, IS_PYPY
|
||||
|
||||
if PYTHON_VERSION_TRIPLE[:2] == (3, 8):
|
||||
lhs, rhs, tokens, right_recursive, dup_rhs = p.check_sets()
|
||||
from uncompyle6.scanner import get_scanner
|
||||
|
||||
s = get_scanner(PYTHON_VERSION, IS_PYPY)
|
||||
s = get_scanner(PYTHON_VERSION_TRIPLE, IS_PYPY)
|
||||
opcode_set = set(s.opc.opname).union(
|
||||
set(
|
||||
"""JUMP_BACK CONTINUE RETURN_END_IF COME_FROM
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2020 Rocky Bernstein
|
||||
# Copyright (c) 2020, 2022 Rocky Bernstein
|
||||
|
||||
|
||||
def while1stmt(self, lhs, n, rule, ast, tokens, first, last):
|
||||
@@ -37,15 +37,14 @@ def while1stmt(self, lhs, n, rule, ast, tokens, first, last):
|
||||
if tokens[loop_end] == "JUMP_BACK":
|
||||
loop_end += 1
|
||||
loop_end_offset = tokens[loop_end].off2int(prefer_last=False)
|
||||
for t in range(first+1, loop_end):
|
||||
for t in range(first + 1, loop_end):
|
||||
token = tokens[t]
|
||||
# token could be a pseudo-op like "LOAD_STR", which is not in
|
||||
# self.opc. We will replace that with LOAD_CONST as an
|
||||
# example of an instruction that is not in self.opc.JUMP_OPS
|
||||
if self.opc.opmap.get(token.kind, "LOAD_CONST") in self.opc.JUMP_OPS:
|
||||
# token.opc. We will replace that with LOAD_CONST as an
|
||||
# example of an instruction that is not in token.opc.JUMP_OPS
|
||||
if token.opc.opmap.get(token.kind, "LOAD_CONST") in token.opc.JUMP_OPS:
|
||||
if token.attr >= loop_end_offset:
|
||||
return True
|
||||
|
||||
|
||||
# SETUP_LOOP location must jump either to the last token or the token after the last one
|
||||
return tokens[first].attr not in (offset, offset + 2)
|
||||
|
@@ -41,7 +41,7 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
Python version 3.6 and above.
|
||||
"""
|
||||
|
||||
# MAKE_CLOSURE adds an additional closure slot
|
||||
# MAKE_CLOSURE adds a closure slot
|
||||
|
||||
# In Python 3.6 and above stack change again. I understand
|
||||
# 3.7 changes some of those changes, although I don't
|
||||
@@ -151,13 +151,13 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
kwonlyargcount = code.co_kwonlyargcount
|
||||
|
||||
paramnames = list(scanner_code.co_varnames[:argc])
|
||||
kwargs = list(scanner_code.co_varnames[argc : argc + kwonlyargcount])
|
||||
kwargs = list(scanner_code.co_varnames[argc: argc + kwonlyargcount])
|
||||
|
||||
paramnames.reverse()
|
||||
defparams.reverse()
|
||||
|
||||
try:
|
||||
ast = self.build_ast(
|
||||
tree = self.build_ast(
|
||||
scanner_code._tokens,
|
||||
scanner_code._customize,
|
||||
scanner_code,
|
||||
@@ -177,10 +177,12 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
if defparams:
|
||||
for i, defparam in enumerate(defparams):
|
||||
params.append(
|
||||
build_param(paramnames[i], defparam, annotate_dict.get(paramnames[i]))
|
||||
build_param(
|
||||
tree, paramnames[i], defparam, annotate_dict.get(paramnames[i])
|
||||
)
|
||||
)
|
||||
|
||||
for param in paramnames[i + 1 :]:
|
||||
for param in paramnames[i + 1:]:
|
||||
if param in annotate_dict:
|
||||
params.append("%s: %s" % (param, annotate_dict[param]))
|
||||
else:
|
||||
@@ -205,7 +207,13 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
|
||||
# dump parameter list (with default values)
|
||||
if is_lambda:
|
||||
self.write("lambda ", ", ".join(params))
|
||||
self.write("lambda")
|
||||
if len(params):
|
||||
self.write(" ", ", ".join(params))
|
||||
elif kwonlyargcount > 0 and not (4 & code.co_flags):
|
||||
assert argc == 0
|
||||
self.write(" ")
|
||||
|
||||
# If the last statement is None (which is the
|
||||
# same thing as "return None" in a lambda) and the
|
||||
# next to last statement is a "yield". Then we want to
|
||||
@@ -213,16 +221,16 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
# to have something to after the yield finishes.
|
||||
# FIXME: this is a bit hoaky and not general
|
||||
if (
|
||||
len(ast) > 1
|
||||
and self.traverse(ast[-1]) == "None"
|
||||
and self.traverse(ast[-2]).strip().startswith("yield")
|
||||
len(tree) > 1
|
||||
and self.traverse(tree[-1]) == "None"
|
||||
and self.traverse(tree[-2]).strip().startswith("yield")
|
||||
):
|
||||
del ast[-1]
|
||||
del tree[-1]
|
||||
# Now pick out the expr part of the last statement
|
||||
ast_expr = ast[-1]
|
||||
while ast_expr.kind != "expr":
|
||||
ast_expr = ast_expr[0]
|
||||
ast[-1] = ast_expr
|
||||
tree_expr = tree[-1]
|
||||
while tree_expr.kind != "expr":
|
||||
tree_expr = tree_expr[0]
|
||||
tree[-1] = tree_expr
|
||||
pass
|
||||
else:
|
||||
self.write("(", ", ".join(params))
|
||||
@@ -236,11 +244,9 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
else:
|
||||
self.write("*, ")
|
||||
pass
|
||||
ends_in_comma = True
|
||||
else:
|
||||
if argc > 0:
|
||||
self.write(", ")
|
||||
ends_in_comma = True
|
||||
|
||||
# ann_dict = kw_dict = default_tup = None
|
||||
kw_dict = None
|
||||
@@ -335,11 +341,11 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
# docstring exists, dump it
|
||||
self.println(self.traverse(node[-2]))
|
||||
|
||||
assert ast == "stmts"
|
||||
assert tree in ("stmts", "lambda_start")
|
||||
|
||||
all_globals = find_all_globals(ast, set())
|
||||
all_globals = find_all_globals(tree, set())
|
||||
globals, nonlocals = find_globals_and_nonlocals(
|
||||
ast, set(), set(), code, self.version
|
||||
tree, set(), set(), code, self.version
|
||||
)
|
||||
|
||||
for g in sorted((all_globals & self.mod_globs) | globals):
|
||||
@@ -350,9 +356,9 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None):
|
||||
|
||||
self.mod_globs -= all_globals
|
||||
has_none = "None" in code.co_names
|
||||
rn = has_none and not find_none(ast)
|
||||
rn = has_none and not find_none(tree)
|
||||
self.gen_source(
|
||||
ast,
|
||||
tree,
|
||||
code.co_name,
|
||||
scanner_code._customize,
|
||||
is_lambda=is_lambda,
|
||||
|
@@ -905,7 +905,7 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin):
|
||||
p2 = (1, -2, ", ")
|
||||
if op == "CALL_FUNCTION_VAR":
|
||||
# Python 3.5 only puts optional args (the VAR part)
|
||||
# lowest down the stack
|
||||
# the lowest down the stack
|
||||
if self.version == (3, 5):
|
||||
if str == "%c(%C, ":
|
||||
entry = ("%c(*%C, %c)", 0, p2, -2)
|
||||
@@ -929,7 +929,7 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin):
|
||||
elif op == "CALL_FUNCTION_VAR_KW":
|
||||
str += "*%c, **%c)"
|
||||
# Python 3.5 only puts optional args (the VAR part)
|
||||
# lowest down the stack
|
||||
# the lowest down the stack
|
||||
na = v & 0xFF # positional parameters
|
||||
if self.version == (3, 5) and na == 0:
|
||||
if p2[2]:
|
||||
@@ -1207,7 +1207,7 @@ class SourceWalker(GenericASTTraversal, NonterminalActions, ComprehensionMixin):
|
||||
return transform_tree
|
||||
|
||||
# The bytecode for the end of the main routine has a
|
||||
# "return None". However you can't issue a "return" statement in
|
||||
# "return None". However, you can't issue a "return" statement in
|
||||
# main. So as the old cigarette slogan goes: I'd rather switch (the token stream)
|
||||
# than fight (with the grammar to not emit "return None").
|
||||
if self.hide_internal:
|
||||
|
Reference in New Issue
Block a user