From 5c31fdc362c70b7c914c65f557eefcc262126c9f Mon Sep 17 00:00:00 2001 From: rocky Date: Fri, 24 Jan 2020 05:47:41 -0500 Subject: [PATCH] Fix bug in 3.6 handling kwonly params ... when there are annotation args --- .../bytecode_3.6_run/05_call_function_kw2.pyc | Bin 0 -> 271 bytes .../bytecode_3.7_run/05_call_function_kw2.pyc | Bin 0 -> 275 bytes .../bytecode_3.8_run/05_call_function_kw2.pyc | Bin 0 -> 283 bytes test/simple_source/bug36/02_call_ex_kw.py | 11 +++ uncompyle6/semantics/make_function36.py | 70 +++++++++--------- 5 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 test/bytecode_3.6_run/05_call_function_kw2.pyc create mode 100644 test/bytecode_3.7_run/05_call_function_kw2.pyc create mode 100644 test/bytecode_3.8_run/05_call_function_kw2.pyc diff --git a/test/bytecode_3.6_run/05_call_function_kw2.pyc b/test/bytecode_3.6_run/05_call_function_kw2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7523f20c684c08e79facac8d3b616b3bcefabfd GIT binary patch literal 271 zcmXr!<>i|3d3)3r1_p-5Knw@WK$Zg#7xMv$6y_Ah6s8u&D25bsWjc#Oy9sXJ~=TbCqAt-FS#T$ zKQBJJ+(@sW@)mDNemu}{ka3xL=^#fJgPq1$#0F$*GWuykSYV@(2v(r%Ee@O9{FKt1 LR6DRfpa=s1+~PY_ literal 0 HcmV?d00001 diff --git a/test/bytecode_3.7_run/05_call_function_kw2.pyc b/test/bytecode_3.7_run/05_call_function_kw2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bef1b0e5f94a63e9d9d5dba7d0f9c27915c07a66 GIT binary patch literal 275 zcmZ?b<>g`kf*GH;M{NPpk3k$5U~GZ2H7)-Yr-q%hV1mG?3Ml`{Kg`kf*GH;M{NPpk3k${zzpO#0C6!NkVs)pVN79aVT@u(VF+f>WbsR80*b-_ zh|L1T&Oi)SUc->Zkiu94)Y8iYRL<-dqRAA+oSK(@i#<6%uOzjiM3eCrdwhIxNl|>f zCetmJ;?$h9B1WM0l?+87lYVIzXXX~L-<^8=L7Hn8qh3=H$eumF6Xv zWaj6^XO|o46;$5hEy<4u8V)ipGcO(F@M5s@7>n3|Y)wW#O$ZBYG!nrIl)c4albfGX Nnv-e=()SsN82~(QJN5to literal 0 HcmV?d00001 diff --git a/test/simple_source/bug36/02_call_ex_kw.py b/test/simple_source/bug36/02_call_ex_kw.py index 0ca044b3..86bdb924 100644 --- a/test/simple_source/bug36/02_call_ex_kw.py +++ b/test/simple_source/bug36/02_call_ex_kw.py @@ -59,3 +59,14 @@ assert p == Point(**dict(x=11, y=22)) def posonly_sum(pos_arg1, *arg, **kwarg): return pos_arg1 + sum(arg) + sum(kwarg.values()) assert 1+2+3+4 == posonly_sum(1,*(2,3),**{"4":4}) + +# From 3.7 test_grammar.py +# Bug was in handling keyword-only parameters when there are annotations. +# The stack order from least- to most-recent is: +# default, keyword, annotation, closure +# This changes in between Python 3.5 and 3.6. +def f(a, b: 1, c: 2, d, e: 3=4, f=5, *g: 6, h: 7, i=8, j: 9=10, + **k: 11) -> 12: pass + +assert f.__annotations__ == {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, + 'k': 11, 'return': 12} diff --git a/uncompyle6/semantics/make_function36.py b/uncompyle6/semantics/make_function36.py index 325e226b..f273f265 100644 --- a/uncompyle6/semantics/make_function36.py +++ b/uncompyle6/semantics/make_function36.py @@ -92,38 +92,40 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None): else: pos_args, kw_args, annotate_argc, closure = args_attr - i = -4 - kw_pairs = 0 - if closure: - # FIXME: fill in - i -= 1 - - if annotate_argc: - # Turn into subroutine and DRY with other use - annotate_node = node[i] - if annotate_node == "expr": - annotate_node = annotate_node[0] - annotate_name_node = annotate_node[-1] - if annotate_node == "dict" and annotate_name_node.kind.startswith( - "BUILD_CONST_KEY_MAP" - ): - types = [ - self.traverse(n, indent="") for n in annotate_node[:-2] - ] - names = annotate_node[-2].attr - l = len(types) - assert l == len(names) - for i in range(l): - annotate_dict[names[i]] = types[i] - pass + i = -4 + kw_pairs = 0 + if annotate_argc: + # Turn into subroutine and DRY with other use + annotate_node = node[i] + if annotate_node == "expr": + annotate_node = annotate_node[0] + annotate_name_node = annotate_node[-1] + if annotate_node == "dict" and annotate_name_node.kind.startswith( + "BUILD_CONST_KEY_MAP" + ): + types = [ + self.traverse(n, indent="") for n in annotate_node[:-2] + ] + names = annotate_node[-2].attr + l = len(types) + assert l == len(names) + for i in range(l): + annotate_dict[names[i]] = types[i] pass - i -= 1 - if kw_args: - kw_node = node[i] - if kw_node == "expr": - kw_node = kw_node[0] - if kw_node == "dict": - kw_pairs = kw_node[-1].attr + pass + i -= 1 + + if closure: + # FIXME: fill in + # annotate = node[i] + i -= 1 + + if kw_args: + kw_node = node[pos_args] + if kw_node == "expr": + kw_node = kw_node[0] + if kw_node == "dict": + kw_pairs = kw_node[-1].attr defparams = [] # FIXME: DRY with code below @@ -323,7 +325,9 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None): self.write(" -> %s" % annotate_dict["return"]) self.println(":") - if node[-2] == "docstring" and not is_lambda: + if ( + node[-2] == "docstring" and not is_lambda + ): # docstring exists, dump it self.println(self.traverse(node[-2])) @@ -351,7 +355,7 @@ def make_function36(self, node, is_lambda, nested=1, code_node=None): # was optimized away. Here, we need to put in unreachable code to # add in "yield" just so that the compiler will mark # the GENERATOR bit of the function. See for example - # Python 3.x's test_generator.py test program. + # Python 3.x's test_connection.py and test_contexlib_async test programs. if code.co_flags & (CO_GENERATOR | CO_ASYNC_GENERATOR): need_bogus_yield = True for token in scanner_code._tokens: