Merge branch 'master' into python-2.4

This commit is contained in:
rocky
2020-04-20 23:11:08 -04:00
23 changed files with 77 additions and 38 deletions

10
NEWS.md
View File

@@ -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
==========================

View File

@@ -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"

View File

@@ -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:

View File

@@ -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)

View File

@@ -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:

View File

@@ -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
)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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)

View File

@@ -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)

View File

@@ -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