diff --git a/test/bytecode_3.6_run/08_test_contextmanager.pyc b/test/bytecode_3.6_run/08_test_contextmanager.pyc new file mode 100644 index 000000000..999815b0d Binary files /dev/null and b/test/bytecode_3.6_run/08_test_contextmanager.pyc differ diff --git a/test/bytecode_3.8_run/08_test_contextmanager.pyc b/test/bytecode_3.8_run/08_test_contextmanager.pyc new file mode 100644 index 000000000..f610c7e9c Binary files /dev/null and b/test/bytecode_3.8_run/08_test_contextmanager.pyc differ diff --git a/test/simple_source/stmts/08_test_contextmanager.py b/test/simple_source/stmts/08_test_contextmanager.py new file mode 100644 index 000000000..9a6ea5f97 --- /dev/null +++ b/test/simple_source/stmts/08_test_contextmanager.py @@ -0,0 +1,21 @@ +""" +This program is self checking! +""" + + +class TestContextManager: + def __enter__(self): + return 1, 2 + + def __exit__(self, exc_type, exc_value, exc_tb): + return self, exc_type, exc_value, exc_tb + + +with open(__file__) as a: + assert a + +with open(__file__) as a, open(__file__) as b: + assert a.read() == b.read() + +with TestContextManager() as a, b: + assert (a, b) == (1, 2) diff --git a/uncompyle6/parsers/parse38.py b/uncompyle6/parsers/parse38.py index 103674196..7ce4e93c4 100644 --- a/uncompyle6/parsers/parse38.py +++ b/uncompyle6/parsers/parse38.py @@ -586,6 +586,15 @@ def customize_grammar_rules(self, tokens, customize): GET_ITER CALL_FUNCTION_1 """ self.addRule(rule, nop_func) + elif opname == "SETUP_WITH": + rules_str = """ + stmt ::= with_as_pass + with_as_pass ::= expr + SETUP_WITH store pass + POP_BLOCK BEGIN_FINALLY COME_FROM_WITH + with_suffix + """ + self.addRule(rules_str, nop_func) def reduce_is_invalid(self, rule, ast, tokens, first, last): invalid = super(Python38Parser, self).reduce_is_invalid( diff --git a/uncompyle6/semantics/consts.py b/uncompyle6/semantics/consts.py index bc62b205e..07bebb521 100644 --- a/uncompyle6/semantics/consts.py +++ b/uncompyle6/semantics/consts.py @@ -272,8 +272,6 @@ (2, NO_PARENTHESIS_EVER) ), - "IMPORT_FROM": ("%{pattr}",), - "IMPORT_NAME_ATTR": ("%{pattr}",), "attribute": ("%c.%[1]{pattr}", (0, "expr")), "delete_subscript": ( "%|del %p[%c]\n", @@ -431,7 +429,12 @@ # If there are situations where we need "with ... as ()" # We may need to customize this in n_withasstmt - "withasstmt": ("%|with %c as %c:\n%+%c%-", 0, 2, 3), + "withasstmt": ( + "%|with %c as %c:\n%+%c%-", + (0, "expr"), + (2, "store"), + (3, ("suite_stmts_opt", "suite_stmts")), + ), "expr_stmt": ( "%|%p\n", diff --git a/uncompyle6/semantics/customize38.py b/uncompyle6/semantics/customize38.py index 10a83b806..670232996 100644 --- a/uncompyle6/semantics/customize38.py +++ b/uncompyle6/semantics/customize38.py @@ -23,8 +23,8 @@ from uncompyle6.semantics.customize37 import FSTRING_CONVERSION_MAP from uncompyle6.semantics.helper import escape_string, strip_quotes -def customize_for_version38(self, version): +def customize_for_version38(self, version): # FIXME: pytest doesn't add proper keys in testing. Reinstate after we have fixed pytest. # for lhs in 'for forelsestmt forelselaststmt ' # 'forelselaststmtc tryfinally38'.split(): @@ -40,10 +40,10 @@ def customize_for_version38(self, version): ), "async_forelse_stmt38": ( "%|async for %c in %c:\n%+%c%-%|else:\n%+%c%-\n\n", - (7, 'store'), - (0, 'expr'), - (8, 'for_block'), - (-1, 'else_suite') + (7, "store"), + (0, "expr"), + (8, "for_block"), + (-1, "else_suite"), ), "async_with_stmt38": ( "%|async with %c:\n%+%c%-\n", @@ -70,8 +70,15 @@ def customize_for_version38(self, version): ), # Python 3.8 reverses the order of keys and items # from all prior versions of Python. - "dict_comp_body": ("%c: %c", (0, "expr"), (1, "expr"),), - "except_cond1a": ("%|except %c:\n", (1, "expr"),), + "dict_comp_body": ( + "%c: %c", + (0, "expr"), + (1, "expr"), + ), + "except_cond1a": ( + "%|except %c:\n", + (1, "expr"), + ), "except_cond_as": ( "%|except %c as %c:\n", (1, "expr"), @@ -121,10 +128,19 @@ def customize_for_version38(self, version): -2, ), "ifpoplaststmtc": ("%|if %c:\n%+%c%-", (0, "testexpr"), (2, "l_stmts")), + "named_expr": ( # AKA "walrus operator" + "%c := %p", + (2, "store"), + (0, "expr", PRECEDENCE["named_expr"] - 1), + ), "pop_return": ("%|return %c\n", (1, "return_expr")), "popb_return": ("%|return %c\n", (0, "return_expr")), "pop_ex_return": ("%|return %c\n", (0, "return_expr")), - "set_for": (" for %c in %c", (2, "store"), (0, "expr_or_arg"),), + "set_for": ( + " for %c in %c", + (2, "store"), + (0, "expr_or_arg"), + ), "whilestmt38": ( "%|while %c:\n%+%c%-\n\n", (1, ("bool_op", "testexpr", "testexprc")), @@ -211,10 +227,11 @@ def customize_for_version38(self, version): (2, "suite_stmts_opt"), (8, "suite_stmts_opt"), ), - "named_expr": ( # AKA "walrus operator" - "%c := %p", + "with_as_pass": ( + "%|with %c as %c:\n%+%c%-", + (0, "expr"), (2, "store"), - (0, "expr", PRECEDENCE["named_expr"] - 1), + (3, "pass"), ), } )