diff --git a/test/bytecode_2.6/04_withas.pyc b/test/bytecode_2.6/04_withas.pyc index bfb6e394..31d0d29c 100644 Binary files a/test/bytecode_2.6/04_withas.pyc and b/test/bytecode_2.6/04_withas.pyc differ diff --git a/test/bytecode_2.7/04_withas.pyc b/test/bytecode_2.7/04_withas.pyc index 61acd311..33c302a2 100644 Binary files a/test/bytecode_2.7/04_withas.pyc and b/test/bytecode_2.7/04_withas.pyc differ diff --git a/test/bytecode_3.0/04_withas.pyc b/test/bytecode_3.0/04_withas.pyc index f0574c2e..09bda8ad 100644 Binary files a/test/bytecode_3.0/04_withas.pyc and b/test/bytecode_3.0/04_withas.pyc differ diff --git a/test/bytecode_3.1/04_withas.pyc b/test/bytecode_3.1/04_withas.pyc index 99ad4503..8259c657 100644 Binary files a/test/bytecode_3.1/04_withas.pyc and b/test/bytecode_3.1/04_withas.pyc differ diff --git a/test/bytecode_3.6/04_withas.pyc b/test/bytecode_3.6/04_withas.pyc index 2691fde2..95117e15 100644 Binary files a/test/bytecode_3.6/04_withas.pyc and b/test/bytecode_3.6/04_withas.pyc differ diff --git a/test/bytecode_3.7/04_withas.pyc b/test/bytecode_3.7/04_withas.pyc index c7551c4b..ee332c8f 100644 Binary files a/test/bytecode_3.7/04_withas.pyc and b/test/bytecode_3.7/04_withas.pyc differ diff --git a/test/simple_source/bug35/04_call_function.py b/test/simple_source/bug35/04_call_function.py index 7fad3438..cbfc63fb 100644 --- a/test/simple_source/bug35/04_call_function.py +++ b/test/simple_source/bug35/04_call_function.py @@ -2,6 +2,7 @@ # Bug was code not knowing which Python versions # have kwargs coming before positional args in code. +"""This program is self-checking!""" # RUNNABLE! def tometadata(self, metadata, schema, Table, args, name=None): diff --git a/test/simple_source/stmts/04_withas.py b/test/simple_source/stmts/04_withas.py index a35c0191..b21452db 100644 --- a/test/simple_source/stmts/04_withas.py +++ b/test/simple_source/stmts/04_withas.py @@ -16,3 +16,11 @@ def withas_bug(self, nested, a, b): with self.assertRaises(ZeroDivisionError): with nested(a(), b()) as (x, y): 1 // 0 + +# Adapted from 3.8 distutils/command/config.py +# In 3.8 the problem was in handling "with .. as" code +def _gen_temp_sourcefile(x, a, headers, lang): + with x as y: + if a: + y = 2 + return 5 diff --git a/uncompyle6/parsers/parse37base.py b/uncompyle6/parsers/parse37base.py index 673d2683..9a5bcf36 100644 --- a/uncompyle6/parsers/parse37base.py +++ b/uncompyle6/parsers/parse37base.py @@ -127,6 +127,7 @@ class Python37BaseParser(PythonParser): "RAISE", "SETUP", "UNPACK", + "WITH", ) ) @@ -993,55 +994,70 @@ class Python37BaseParser(PythonParser): ) custom_ops_processed.add(opname) + elif opname == "WITH_CLEANUP_START": + rules_str = """ + stmt ::= with_null + with_null ::= with_suffix + with_suffix ::= WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + """ + self.addRule(rules_str, nop_func) elif opname == "SETUP_WITH": rules_str = """ stmt ::= with stmt ::= withasstmt - with ::= expr SETUP_WITH POP_TOP suite_stmts_opt COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + with ::= expr + SETUP_WITH POP_TOP + suite_stmts_opt + COME_FROM_WITH + with_suffix withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + with_suffix + + with ::= expr + SETUP_WITH POP_TOP + suite_stmts_opt + POP_BLOCK LOAD_CONST COME_FROM_WITH + with_suffix + + withasstmt ::= expr + SETUP_WITH store suite_stmts_opt + POP_BLOCK LOAD_CONST COME_FROM_WITH + with_suffix with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + with_suffix withasstmt ::= expr SETUP_WITH store suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY - - with ::= expr - SETUP_WITH POP_TOP suite_stmts_opt - POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY - withasstmt ::= expr - SETUP_WITH store suite_stmts_opt - POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + with_suffix """ if self.version < 3.8: rules_str += """ with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + with_suffix """ else: rules_str += """ - with ::= expr + with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY + with_suffix withasstmt ::= expr SETUP_WITH store suite_stmts_opt POP_BLOCK LOAD_CONST COME_FROM_WITH - with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK + withasstmt ::= expr + SETUP_WITH store suite_stmts + POP_BLOCK BEGIN_FINALLY COME_FROM_WITH with_suffix + + with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK BEGIN_FINALLY COME_FROM_WITH - WITH_CLEANUP_START WITH_CLEANUP_FINISH - END_FINALLY + with_suffix """ self.addRule(rules_str, nop_func) diff --git a/uncompyle6/semantics/check_ast.py b/uncompyle6/semantics/check_ast.py index c2e20bef..3c5f4b78 100644 --- a/uncompyle6/semantics/check_ast.py +++ b/uncompyle6/semantics/check_ast.py @@ -8,22 +8,28 @@ FIXME idea: extend parsing system to do same kinds of checks or nonterminal before reduction and don't reduce when there is a problem. """ + def checker(ast, in_loop, errors): if ast is None: return - in_loop = (in_loop or (ast.kind in ('while1stmt', 'whileTruestmt', - 'whilestmt', 'whileelsestmt', 'while1elsestmt', - 'for_block')) - or ast.kind.startswith('async_for')) - if ast.kind in ('aug_assign1', 'aug_assign2') and ast[0][0] == 'and': + in_loop = ( + in_loop + or ast.kind.startswith("while") + or ast.kind.startswith("async_for") + ) + if ast.kind in ("aug_assign1", "aug_assign2") and ast[0][0] == "and": text = str(ast) - error_text = '\n# improper augmented assigment (e.g. +=, *=, ...):\n#\t' + '\n# '.join(text.split("\n")) + '\n' + error_text = ( + "\n# improper augmented assigment (e.g. +=, *=, ...):\n#\t" + + "\n# ".join(text.split("\n")) + + "\n" + ) errors.append(error_text) for node in ast: - if not in_loop and node.kind in ('continue', 'break'): + if not in_loop and node.kind in ("continue", "break"): text = str(node) - error_text = '\n# not in loop:\n#\t' + '\n# '.join(text.split("\n")) + error_text = "\n# not in loop:\n#\t" + "\n# ".join(text.split("\n")) errors.append(error_text) - if hasattr(node, '__repr1__'): + if hasattr(node, "__repr1__"): checker(node, in_loop, errors)