You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
try/else on 2.6 fixup
This commit is contained in:
BIN
test/bytecode_2.5_run/02_try_else_loop.pyc
Normal file
BIN
test/bytecode_2.5_run/02_try_else_loop.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.5_run/03_try_else.pyc
Normal file
BIN
test/bytecode_2.5_run/03_try_else.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6_run/02_try_else_loop.pyc
Normal file
BIN
test/bytecode_2.6_run/02_try_else_loop.pyc
Normal file
Binary file not shown.
BIN
test/bytecode_2.6_run/03_try_else.pyc
Normal file
BIN
test/bytecode_2.6_run/03_try_else.pyc
Normal file
Binary file not shown.
17
test/simple_source/bug25/02_try_else_loop.py
Normal file
17
test/simple_source/bug25/02_try_else_loop.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# From 2.4 test_binop.py bug is missing 'else:' in 2nd try.
|
||||
def test_constructor():
|
||||
for bad in "0", 0.0, 0j, (), [], {}, None:
|
||||
try:
|
||||
raise TypeError(bad)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "%r didn't raise TypeError" % bad
|
||||
try:
|
||||
raise TypeError(bad)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
assert False, "%r didn't raise TypeError" % bad
|
||||
|
||||
test_constructor()
|
18
test/simple_source/bug25/03_try_else.py
Normal file
18
test/simple_source/bug25/03_try_else.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# From Python 2.4. test_cgi.py
|
||||
# Bug was in putting try block inside the ifelse statement.
|
||||
|
||||
# Note: this is a self testing program - will assert on failure.
|
||||
def do_test(method):
|
||||
if method == "GET":
|
||||
rc = 0
|
||||
elif method == "POST":
|
||||
rc = 1
|
||||
else:
|
||||
raise ValueError, "unknown method: %s" % method
|
||||
try:
|
||||
rc = 2
|
||||
except ZeroDivisionError:
|
||||
rc = 3
|
||||
return rc
|
||||
|
||||
assert 2 == do_test("GET")
|
@@ -47,27 +47,19 @@ case $PYVERSION in
|
||||
[test_sax.py]=1 # Control flow?
|
||||
[test_trace.py]=1 # Line numbers are expected to be different
|
||||
[test_types.py]=1 # Control flow?
|
||||
[test_zipfile64.py]=1 # Runs ok but takes 204 seconds
|
||||
nn [test_zipfile64.py]=1 # Runs ok but takes 204 seconds
|
||||
)
|
||||
;;
|
||||
2.6)
|
||||
SKIP_TESTS=(
|
||||
[test_binop.py]=1 # need to fix tryelse
|
||||
[test_cmath.py]=1 # Control flow?
|
||||
[test_codecs.py]=1 # need to fix tryelse
|
||||
[test_coercion.py]=1 # Control flow?
|
||||
[test_cookielib.py]=1 # Control flow?
|
||||
[test_decorators.py]=1 # Syntax Error - look at
|
||||
[test_enumerate.py]=1 # Control flow?
|
||||
[test_file.py]=1 # Control flow?
|
||||
[test_frozen.py]=1 # Control flow?
|
||||
[test_ftplib.py]=1 # Control flow?
|
||||
[test_funcattrs.py]=1 # Control flow?
|
||||
[test_grp.py]=1 # Long test - might work Control flow?
|
||||
[test_imp.py]=1
|
||||
[test_int.py]=1
|
||||
[test_long.py]=1
|
||||
[test_pty.py]=1
|
||||
[test_pwd.py]=1 # Long test - might work? Control flow?
|
||||
[test_queue.py]=1 # Control flow?
|
||||
[test_re.py]=1 # Probably Control flow?
|
||||
|
@@ -69,7 +69,6 @@ class Python24Parser(Python25Parser):
|
||||
super(Python24Parser, self).customize_grammar_rules(tokens, customize)
|
||||
if self.version == 2.4:
|
||||
self.check_reduce['nop_stmt'] = 'tokens'
|
||||
self.check_reduce['try_except'] = 'tokens'
|
||||
|
||||
def reduce_is_invalid(self, rule, ast, tokens, first, last):
|
||||
invalid = super(Python24Parser,
|
||||
|
@@ -19,9 +19,6 @@ class Python25Parser(Python26Parser):
|
||||
|
||||
return_if_stmt ::= ret_expr RETURN_END_IF JUMP_BACK
|
||||
|
||||
# We have no jumps to jumps, so no "come_froms" but a single "COME_FROM"
|
||||
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite COME_FROM
|
||||
|
||||
# Python 2.6 uses ROT_TWO instead of the STORE_xxx
|
||||
# withas is allowed as a "from future" in 2.5
|
||||
# 2.6 and 2.7 do something slightly different
|
||||
@@ -39,8 +36,6 @@ class Python25Parser(Python26Parser):
|
||||
# loop. FIXME: should "come_froms" below be a single COME_FROM?
|
||||
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suite come_froms
|
||||
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suitel
|
||||
|
||||
# Python 2.6 omits the LOAD_FAST DELETE_FAST below
|
||||
# withas is allowed as a "from future" in 2.5
|
||||
@@ -59,9 +54,6 @@ class Python25Parser(Python26Parser):
|
||||
def customize_grammar_rules(self, tokens, customize):
|
||||
# Remove grammar rules inherited from Python 2.6 or Python 2
|
||||
self.remove_rules("""
|
||||
# No jump to jumps in 2.4 so we have a single "COME_FROM", not "come_froms"
|
||||
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite come_froms
|
||||
|
||||
setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
|
||||
withstmt ::= expr setupwith SETUP_FINALLY suite_stmts_opt
|
||||
POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
|
||||
|
@@ -40,6 +40,8 @@ class Python26Parser(Python2Parser):
|
||||
|
||||
tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suite come_froms
|
||||
tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
|
||||
except_handler else_suitel
|
||||
|
||||
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM POP_TOP
|
||||
|
||||
@@ -155,10 +157,12 @@ class Python26Parser(Python2Parser):
|
||||
ifstmt ::= testexpr_then _ifstmts_jump
|
||||
|
||||
# Semantic actions want the else to be at position 3
|
||||
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite come_froms
|
||||
ifelsestmt ::= testexpr_then c_stmts_opt jf_cf_pop else_suite come_froms
|
||||
ifelsestmt ::= testexpr_then c_stmts_opt filler else_suitel come_froms POP_TOP
|
||||
|
||||
# We have no jumps to jumps, so no "come_froms" but a single "COME_FROM"
|
||||
ifelsestmt ::= testexpr c_stmts_opt jf_cf_pop else_suite COME_FROM
|
||||
|
||||
# Semantic actions want else_suitel to be at index 3
|
||||
ifelsestmtl ::= testexpr_then c_stmts_opt jb_cf_pop else_suitel
|
||||
ifelsestmtc ::= testexpr_then c_stmts_opt ja_cf_pop else_suitec
|
||||
@@ -307,6 +311,7 @@ class Python26Parser(Python2Parser):
|
||||
super(Python26Parser, self).customize_grammar_rules(tokens, customize)
|
||||
self.check_reduce['and'] = 'AST'
|
||||
self.check_reduce['list_for'] = 'AST'
|
||||
self.check_reduce['try_except'] = 'tokens'
|
||||
|
||||
def reduce_is_invalid(self, rule, ast, tokens, first, last):
|
||||
invalid = super(Python26Parser,
|
||||
@@ -333,6 +338,23 @@ class Python26Parser(Python2Parser):
|
||||
# The JUMP_ABSOLUTE has to be to the last POP_TOP or this is invalid
|
||||
ja_attr = ast[4].attr
|
||||
return tokens[last].offset != ja_attr
|
||||
elif rule[0] == 'try_except':
|
||||
# We need to distingush try_except from try_except_else and we do that
|
||||
# by checking the jump before the END_FINALLY
|
||||
# If we have:
|
||||
# insn
|
||||
# POP_TOP
|
||||
# END_FINALLY
|
||||
# COME_FROM
|
||||
# then insn has to be either a JUMP_FORWARD or a RETURN_VALUE
|
||||
if last == len(tokens):
|
||||
last -= 1
|
||||
if tokens[last] != 'COME_FROM' and tokens[last-1] == 'COME_FROM':
|
||||
last -= 1
|
||||
return (tokens[last] == 'COME_FROM'
|
||||
and tokens[last-1] == 'END_FINALLY'
|
||||
and tokens[last-2] == 'POP_TOP'
|
||||
and tokens[last-3].kind not in frozenset(('JUMP_FORWARD', 'RETURN_VALUE')))
|
||||
return False
|
||||
class Python26ParserSingle(Python2Parser, PythonParserSingle):
|
||||
pass
|
||||
|
Reference in New Issue
Block a user