You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Merge branch 'master' into python-2.4
This commit is contained in:
10
NEWS.md
10
NEWS.md
@@ -1,3 +1,13 @@
|
||||
3.6.6: 2020-4-20 Love in the time of Cholera
|
||||
============================================
|
||||
|
||||
The main reason for this release is an incompatablity bump in xdis which handles
|
||||
3.7 SipHash better.
|
||||
|
||||
* Go over "yield" as an expression precidence
|
||||
* Some small alignment with code in decompyle3 for "or" and "and" was done
|
||||
|
||||
|
||||
3.6.5: 2020-4-1 April Fool
|
||||
==========================
|
||||
|
||||
|
@@ -58,7 +58,7 @@ entry_points = {
|
||||
]}
|
||||
ftp_url = None
|
||||
install_requires = ["spark-parser >= 1.8.9, < 1.9.0",
|
||||
"xdis >= 4.3.2, < 4.4.0"]
|
||||
"xdis >= 4.4.0, < 4.5.0"]
|
||||
|
||||
license = "GPL3"
|
||||
mailing_list = "python-debugger@googlegroups.com"
|
||||
|
@@ -95,12 +95,19 @@ check-bytecode-2:
|
||||
--bytecode-2.5 --bytecode-2.6 --bytecode-2.7 --bytecode-pypy2.7
|
||||
|
||||
#: Check deparsing bytecode 3.x only
|
||||
# check-bytecode-3:
|
||||
# $(PYTHON) test_pythonlib.py \
|
||||
# --bytecode-3.0 \
|
||||
# --bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
|
||||
# --bytecode-3.4 --bytecode-3.5 --bytecode-3.6 \
|
||||
# --bytecode-3.7 \
|
||||
# --bytecode-pypy3.2 --bytecode-pypy3.6 --bytecode-3.8
|
||||
|
||||
# FIXME: Until we shaked out problems with xdis...
|
||||
check-bytecode-3:
|
||||
$(PYTHON) test_pythonlib.py --bytecode-3.0 \
|
||||
--bytecode-3.1 --bytecode-3.2 --bytecode-3.3 \
|
||||
$(PYTHON) test_pythonlib.py \
|
||||
--bytecode-3.4 --bytecode-3.5 --bytecode-3.6 \
|
||||
--bytecode-3.7 \
|
||||
--bytecode-pypy3.2 --bytecode-pypy3.6
|
||||
--bytecode-3.7 --bytecode-3.8
|
||||
|
||||
#: Check deparsing on selected bytecode 3.x
|
||||
check-bytecode-3-short:
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2015-2016, 2818-2019 by Rocky Bernstein
|
||||
# Copyright (c) 2015-2016, 2818-2020 by Rocky Bernstein
|
||||
# Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
|
||||
# Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
|
||||
# Copyright (c) 1999 John Aycock
|
||||
@@ -95,7 +95,9 @@ def disassemble_file(filename, outstream=None):
|
||||
try to find the corresponding compiled object.
|
||||
"""
|
||||
filename = check_object_path(filename)
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size) = load_module(filename)
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size, sip_hash) = load_module(
|
||||
filename
|
||||
)
|
||||
if type(co) == list:
|
||||
for con in co:
|
||||
disco(version, con, outstream)
|
||||
|
@@ -22,7 +22,7 @@ from xdis.bytecode import Bytecode, findlinestarts, offset2line
|
||||
|
||||
def line_number_mapping(pyc_filename, src_filename):
|
||||
(version, timestamp, magic_int, code1, is_pypy,
|
||||
source_size) = load_module(pyc_filename)
|
||||
source_size, sip_hash) = load_module(pyc_filename)
|
||||
try:
|
||||
code2 = load_file(src_filename)
|
||||
except SyntaxError, e:
|
||||
|
@@ -188,7 +188,7 @@ def decompile_file(
|
||||
|
||||
filename = check_object_path(filename)
|
||||
code_objects = {}
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size) = load_module(
|
||||
(version, timestamp, magic_int, co, is_pypy, source_size, sip_hash) = load_module(
|
||||
filename, code_objects
|
||||
)
|
||||
|
||||
|
@@ -194,9 +194,9 @@ class Python2Parser(PythonParser):
|
||||
expr ::= slice3
|
||||
expr ::= unary_convert
|
||||
|
||||
expr_jit ::= expr jmp_true
|
||||
expr_jt ::= expr jmp_true
|
||||
or ::= expr_jt expr come_from_opt
|
||||
and ::= expr jmp_false expr come_from_opt
|
||||
or ::= expr_jit expr come_from_opt
|
||||
|
||||
unary_convert ::= expr UNARY_CONVERT
|
||||
|
||||
|
@@ -278,10 +278,16 @@ class Python3Parser(PythonParser):
|
||||
POP_BLOCK LOAD_CONST COME_FROM_WITH
|
||||
WITH_CLEANUP END_FINALLY
|
||||
|
||||
expr_jt ::= expr jmp_true
|
||||
expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
|
||||
|
||||
## FIXME: Right now we have erroneous jump targets
|
||||
## This below is probably not correct when the COME_FROM is put in the right place
|
||||
and ::= expr jmp_false expr COME_FROM
|
||||
or ::= expr jmp_true expr COME_FROM
|
||||
and ::= expr jmp_false expr COME_FROM
|
||||
or ::= expr_jt expr COME_FROM
|
||||
or ::= expr_jt expr
|
||||
or ::= expr_jitop expr COME_FROM
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||
|
||||
# # something like the below is needed when the jump targets are fixed
|
||||
## or ::= expr JUMP_IF_TRUE_OR_POP COME_FROM expr
|
||||
@@ -339,9 +345,6 @@ class Python3Parser(PythonParser):
|
||||
ret_or ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
|
||||
if_exp_ret ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond
|
||||
|
||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||
or ::= expr jmp_true expr
|
||||
and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
|
||||
|
||||
# compare_chained1 is used exclusively in chained_compare
|
||||
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
|
||||
|
@@ -133,8 +133,9 @@ class Python30Parser(Python31Parser):
|
||||
|
||||
jump_except ::= _jump COME_FROM POP_TOP
|
||||
|
||||
expr_jt ::= expr jmp_true
|
||||
or ::= expr jmp_false expr jmp_true expr
|
||||
or ::= expr jmp_true expr
|
||||
or ::= expr_jt expr
|
||||
|
||||
import_from ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist _come_froms POP_TOP
|
||||
|
||||
|
@@ -637,7 +637,6 @@ class Python37Parser(Python37BaseParser):
|
||||
expr_pjit ::= expr POP_JUMP_IF_TRUE
|
||||
expr_jit ::= expr JUMP_IF_TRUE
|
||||
expr_jt ::= expr jmp_true
|
||||
expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
|
||||
|
||||
jmp_false37 ::= POP_JUMP_IF_FALSE COME_FROM
|
||||
list_if ::= expr jmp_false37 list_iter
|
||||
@@ -928,9 +927,9 @@ class Python37Parser(Python37BaseParser):
|
||||
ret_or ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
|
||||
if_exp_ret ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond
|
||||
|
||||
jitop_come_from ::= JUMP_IF_TRUE_OR_POP come_froms
|
||||
jitop_come_from_expr ::= JUMP_IF_TRUE_OR_POP come_froms expr
|
||||
jifop_come_from ::= JUMP_IF_FALSE_OR_POP come_froms
|
||||
or ::= and jitop_come_from expr COME_FROM
|
||||
or ::= and jitop_come_from_expr COME_FROM
|
||||
or ::= expr JUMP_IF_TRUE_OR_POP expr COME_FROM
|
||||
or ::= expr_jit expr COME_FROM
|
||||
or ::= expr_pjit expr POP_JUMP_IF_FALSE COME_FROM
|
||||
@@ -959,7 +958,7 @@ class Python37Parser(Python37BaseParser):
|
||||
|
||||
## Note that "jmp_false" is what we check on in the "and" reduce rule.
|
||||
and ::= expr jmp_false expr COME_FROM
|
||||
or ::= expr jmp_true expr COME_FROM
|
||||
or ::= expr_jt expr COME_FROM
|
||||
|
||||
# compare_chained1 is used exclusively in chained_compare
|
||||
compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
|
||||
|
@@ -15,7 +15,6 @@
|
||||
"""
|
||||
spark grammar differences over Python 3.7 for Python 3.8
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
from uncompyle6.parser import PythonParserSingle
|
||||
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
|
||||
|
@@ -3,9 +3,14 @@
|
||||
ASSERT_OPS = frozenset(["LOAD_ASSERT", "RAISE_VARARGS_1"])
|
||||
def or_check(self, lhs, n, rule, ast, tokens, first, last):
|
||||
rhs = rule[1]
|
||||
if rhs in (("expr_jt", "expr"),
|
||||
("expr_jitop", "expr", "COME_FROM"),
|
||||
("expr_jit", "expr", "\\e_come_from_opt")):
|
||||
|
||||
# print("XXX", first, last, rule)
|
||||
# for t in range(first, last): print(tokens[t])
|
||||
# print("="*40)
|
||||
|
||||
if rhs[0:2] in (("expr_jt", "expr"),
|
||||
("expr_jitop", "expr"),
|
||||
("expr_jit", "expr")):
|
||||
if tokens[last] in ASSERT_OPS or tokens[last-1] in ASSERT_OPS:
|
||||
return True
|
||||
|
||||
@@ -28,22 +33,32 @@ def or_check(self, lhs, n, rule, ast, tokens, first, last):
|
||||
jump_true = expr_jt[1][0]
|
||||
|
||||
jmp_true_target = jump_true.attr
|
||||
jmp_true_target < first_offset
|
||||
|
||||
last_token = tokens[last]
|
||||
last_token_offset = last_token.off2int()
|
||||
|
||||
# FIXME: use instructions for all of this
|
||||
if jmp_true_target < first_offset:
|
||||
return False
|
||||
elif jmp_true_target < last_token_offset:
|
||||
return True
|
||||
|
||||
jmp_false = tokens[last]
|
||||
# If the jmp is backwards
|
||||
if jmp_false == "POP_JUMP_IF_FALSE":
|
||||
jmp_false_offset = jmp_false.off2int()
|
||||
if jmp_false.attr < jmp_false_offset:
|
||||
if last_token == "POP_JUMP_IF_FALSE" and not self.version in (2.7, 3.5, 3.6):
|
||||
if last_token.attr < last_token_offset:
|
||||
# For a backwards loop, well compare to the instruction *after*
|
||||
# then POP_JUMP...
|
||||
jmp_false = tokens[last + 1]
|
||||
last_token = tokens[last + 1]
|
||||
# HACK alert 3 is the Python < 3.6ish thing.
|
||||
# Convert to using instructions
|
||||
return not (
|
||||
(jmp_false_offset <= jmp_true_target <= jmp_false_offset + 2)
|
||||
(last_token_offset <= jmp_true_target <= last_token_offset + 3)
|
||||
or jmp_true_target < tokens[first].off2int()
|
||||
)
|
||||
elif last_token == "JUMP_FORWARD" and expr_jt.kind != "expr_jitop":
|
||||
# "or" has to fall through to the next statement
|
||||
# FIXME: use instructions for all of this
|
||||
return True
|
||||
|
||||
|
||||
return False
|
||||
|
@@ -387,7 +387,7 @@ class Scanner3(Scanner):
|
||||
# pattr = 'code_object @ 0x%x %s->%s' %\
|
||||
# (id(const), const.co_filename, const.co_name)
|
||||
pattr = "<code_object " + const.co_name + ">"
|
||||
elif isinstance(const, str) or PYTHON_VERSION < 3.0 and isinstance(const, unicode):
|
||||
elif isinstance(const, str) or xdis.PYTHON_VERSION <= 2.7 and isinstance(const, unicode):
|
||||
opname = "LOAD_STR"
|
||||
else:
|
||||
if isinstance(inst.arg, int) and inst.arg < len(co.co_consts):
|
||||
|
@@ -70,7 +70,10 @@ class Scanner38(Scanner37):
|
||||
if self.debug:
|
||||
print("%sremove loop offset %s" % (" " * len(loop_ends), offset))
|
||||
pass
|
||||
next_end = loop_ends[-1] if len(loop_ends) else tokens[len(tokens)-1].off2int() + 10
|
||||
if len(loop_ends):
|
||||
next_end = loop_ends[-1]
|
||||
else:
|
||||
next_end = tokens[len(tokens)-1].off2int() + 10
|
||||
|
||||
if offset in jump_back_targets:
|
||||
next_end = off2int(jump_back_targets[offset], prefer_last=False)
|
||||
|
@@ -394,7 +394,7 @@ def compare_code_with_srcfile(pyc_filename, src_filename, verify):
|
||||
is returned. Otherwise a string message describing the mismatch is returned.
|
||||
"""
|
||||
(version, timestamp, magic_int, code_obj1, is_pypy,
|
||||
source_size) = load_module(pyc_filename)
|
||||
source_size, sip_hash) = load_module(pyc_filename)
|
||||
if magic_int != PYTHON_MAGIC_INT:
|
||||
msg = ("Can't compare code - Python is running with magic %s, but code is magic %s "
|
||||
% (PYTHON_MAGIC_INT, magic_int))
|
||||
@@ -421,9 +421,9 @@ def compare_code_with_srcfile(pyc_filename, src_filename, verify):
|
||||
def compare_files(pyc_filename1, pyc_filename2, verify):
|
||||
"""Compare two .pyc files."""
|
||||
(version1, timestamp, magic_int1, code_obj1, is_pypy,
|
||||
source_size) = uncompyle6.load_module(pyc_filename1)
|
||||
source_size, sip_hash) = uncompyle6.load_module(pyc_filename1)
|
||||
(version2, timestamp, magic_int2, code_obj2, is_pypy,
|
||||
source_size) = uncompyle6.load_module(pyc_filename2)
|
||||
source_size, sip_hash) = uncompyle6.load_module(pyc_filename2)
|
||||
if (magic_int1 != magic_int2) and verify == 'verify':
|
||||
verify = 'weak_verify'
|
||||
cmp_code_objects(version1, is_pypy, code_obj1, code_obj2, verify)
|
||||
|
@@ -12,4 +12,4 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# This file is suitable for sourcing inside bash as
|
||||
# well as importing into Python
|
||||
VERSION="3.6.5" # noqa
|
||||
VERSION="3.6.6" # noqa
|
||||
|
Reference in New Issue
Block a user