Python 3.4 assertion handling. Improve verify

3.4 has jump optimization like 3.5.
verify.py: show mismatch on verification mismatch
This commit is contained in:
rocky
2016-07-14 05:19:16 -04:00
parent 1e25ffa879
commit 7b7a9fa4cf
10 changed files with 35 additions and 10 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -148,6 +148,7 @@ def main(in_base, out_base, files, codes, outfile=None,
else:
print('\n# %s\n\t%s', infile, msg)
except verify.VerifyCmpError as e:
print(e)
verify_failed_files += 1
os.rename(outfile, outfile + '_unverified')
if not outfile:

View File

@@ -247,7 +247,7 @@ class Python3Parser(PythonParser):
'''
def p_misc(self, args):
def p_misc3(self, args):
"""
try_middle ::= JUMP_FORWARD COME_FROM except_stmts END_FINALLY NOP COME_FROM
"""
@@ -288,7 +288,6 @@ class Python3Parser(PythonParser):
def p_expr3(self, args):
'''
expr ::= LOAD_CLASSNAME
expr ::= LOAD_ASSERT
# Python 3.4+
expr ::= LOAD_CLASSDEREF
@@ -615,7 +614,7 @@ class Python35onParser(Python3Parser):
expr ::= yield_from
yield_from ::= expr GET_YIELD_FROM_ITER LOAD_CONST YIELD_FROM
# Python 3.5 has more loop optimization that removes
# Python 3.4+ has more loop optimization that removes
# JUMP_FORWARD in some cases, and hence we also don't
# see COME_FROM
_ifstmts_jump ::= c_stmts_opt

View File

@@ -37,6 +37,10 @@ class Python34Parser(Python3Parser):
# Is this 3.4 only?
yield_from ::= expr GET_ITER LOAD_CONST YIELD_FROM
# Python 3.4+ has more loop optimization that removes
# JUMP_FORWARD in some cases, and hence we also don't
# see COME_FROM
_ifstmts_jump ::= c_stmts_opt
"""
class Python34ParserSingle(Python34Parser, PythonParserSingle):
pass

View File

@@ -89,8 +89,14 @@ class Scanner2(scan.Scanner):
varnames = co.co_varnames
self.names = names
# Scan for assertions. Later we will
# turn 'LOAD_GLOBAL' to 'LOAD_ASSERT'.
# 'LOAD_ASSERT' is used in assert statements.
self.load_asserts = set()
for i in self.op_range(0, n):
# We need to detect the difference between
# "raise AssertionError" and
# "assert"
if self.code[i] == self.opc.PJIT and self.code[i+3] == self.opc.LOAD_GLOBAL:
if names[self.get_argument(i+3)] == 'AssertionError':
self.load_asserts.add(i+3)

View File

@@ -125,8 +125,14 @@ class Scanner26(scan.Scanner2):
codelen = len(self.code)
# Scan for assertions. Later we will
# turn 'LOAD_GLOBAL' to 'LOAD_ASSERT'.
# 'LOAD_ASSERT' is used in assert statements.
self.load_asserts = set()
for i in self.op_range(0, n):
# We need to detect the difference between
# "raise AssertionError" and
# "assert"
if (self.code[i] == self.opc.JUMP_IF_TRUE and
i + 4 < codelen and
self.code[i+3] == self.opc.POP_TOP and

View File

@@ -134,16 +134,19 @@ class Scanner3(scan.Scanner):
bytecode = Bytecode(co, self.opc)
# Scan for assertions. Later we will
# turn 'LOAD_GLOBAL' to 'LOAD_ASSERT' for those
# assertions
# turn 'LOAD_GLOBAL' to 'LOAD_ASSERT'.
# 'LOAD_ASSERT' is used in assert statements.
self.load_asserts = set()
bs = list(bytecode)
n = len(bs)
for i in range(n):
inst = bs[i]
if inst.opname == 'POP_JUMP_IF_TRUE' and i+1 < n:
next_inst = bs[i+1]
# We need to detect the difference between
# "raise AssertionError" and
# "assert"
if inst.opname == 'POP_JUMP_IF_TRUE' and i+3 < n:
next_inst = bs[i+3]
if (next_inst.opname == 'LOAD_GLOBAL' and
next_inst.argval == 'AssertionError'):
self.load_asserts.add(next_inst.offset)

View File

@@ -180,7 +180,13 @@ def cmp_code_objects(version, code_obj1, code_obj2, name=''):
if member in __IGNORE_CODE_MEMBERS__:
pass
elif member == 'co_code':
if version == 2.5:
if version == 2.3:
import uncompyle6.scanners.scanner23 as scan
scanner = scan.Scanner26()
elif version == 2.4:
import uncompyle6.scanners.scanner24 as scan
scanner = scan.Scanner25()
elif version == 2.5:
import uncompyle6.scanners.scanner25 as scan
scanner = scan.Scanner25()
elif version == 2.6: