From 01b2b467579243c1c9128af5b29726c6fb2c4479 Mon Sep 17 00:00:00 2001 From: rocky Date: Tue, 17 Dec 2019 09:28:48 -0500 Subject: [PATCH] Handle named parameters in 3.0..3.3 lambdas What a pain. Thank you, Python! --- .../04_lambda_star_default.pyc | Bin 0 -> 915 bytes .../04_lambda_star_default.pyc | Bin 0 -> 894 bytes .../04_lambda_star_default.pyc | Bin 0 -> 895 bytes .../04_lambda_star_default.pyc | Bin 0 -> 1001 bytes .../bug33/04_lambda_star_default.py | 3 +- uncompyle6/semantics/make_function.py | 64 ++++++++++++------ 6 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 test/bytecode_3.0_run/04_lambda_star_default.pyc create mode 100644 test/bytecode_3.1_run/04_lambda_star_default.pyc create mode 100644 test/bytecode_3.2_run/04_lambda_star_default.pyc create mode 100644 test/bytecode_3.3_run/04_lambda_star_default.pyc diff --git a/test/bytecode_3.0_run/04_lambda_star_default.pyc b/test/bytecode_3.0_run/04_lambda_star_default.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e366eaa9dda0be4ade7e878fd8123b84ebc8a54 GIT binary patch literal 915 zcmb_aJx{|h5Iv^_N}-4qW`-=ZAlRr72v}Jz- ztDt;MfYrM`JNNPK**lA^=F{^_-_VCuXS~Pe9@$x<2clC33c$|O;aJhBqF9j)XvNMD z?-|)9od*dOOr7lF_ZZutUf5zbCSZq!f7k(= zYqA^iPa(4xD&8K4>?lNtpJ8{K*y_?_GOH^+`N$jc>+D>T6=@u~+?OWq4E)8`R%c^7 zN_94{I&zgRBO9MkFYZFtMJS!$W(WFHQYA3)6Zc|!m@dNSZI0U6HVH1szs;6); zg+`LzMU*FlJ9Zx9?mHKkRgzyHm1SN|=Mwab7bJ3Kx%FwhE3XI#^R?w*O|7X{;yI-x literal 0 HcmV?d00001 diff --git a/test/bytecode_3.1_run/04_lambda_star_default.pyc b/test/bytecode_3.1_run/04_lambda_star_default.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57e564ba8d41b760c37c485e4f458f0c6aceb02a GIT binary patch literal 894 zcmb_aO-}+b5S{LV@@YKkmD64X61+)>M!n*Jg9!=Qly=buaB;g0G0~Wa|G>ZCU-LhB zbY@mQ_24B__^8-ng%7&CR17v0IaKVjA_uy%R6KtxbOCxn6@4fVfd>84 zJjZEE2#@#^bgmZ&Ty_Hl2uR}c2y>&;TSql%nab=VF2EfjSTmhXqR_@JQBh;)Zd$EI z^EjNy=}^nirZNe2G?H$T)@KhKWG2jF!M~5brugCWZ}tqgHEy@At@y-+EO}})kYAqvgsi_VS892cTk|# zHw*47DEFsEo&klU&oRdpUBbPdhZe1v$5XegP#P+VqYu2~AZS qs`6axAkD($?kY`_w5W^GFYZhgV-Dg(nJ5_Yy`c{^`@m|8w)g^TrKBJL literal 0 HcmV?d00001 diff --git a/test/bytecode_3.3_run/04_lambda_star_default.pyc b/test/bytecode_3.3_run/04_lambda_star_default.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b156da172e64758aebe89936079408625623da4d GIT binary patch literal 1001 zcmcIiy-veG4ECiz^cMu35M7bF&{irNRRsdpE)10_RaJ7ALe!L$Tuv1dEVOUH&cv(n z1`LeY4s8M>h*Ru1{v7+WeJ_=2>Gkbn^ezA-q)ry?Qxv^GrSK830vMuUfy$7r%5bq1 zFcjblP+8blTY%rH3R4U82}Bk=#aIrp0%JRj4N_Phu_9x;jOi~-mEfwehqa}JiVnR= z&QWv;)dM~PCKd)Fd+0Y%L4!g}4%Na_(T$-#lpWbIh#z2%P-$;A_ua7$Oeo!!W3D@$ zR{MDD+cQVmV;$MySh*A1_)&9y&q?OCoR;ZN<|8&fNww*aKaaxv4$<(K;^+V#aVpFe zhlt}_fk58R7To2LdIlpCzPtm9Xx;EKX_x{xME<4o0#@k8Q|WCJ6%;Tv z@+wb8GMLSK&2>O(0YtyqHbijor_s}*lTu89au>mTM?5O!5#-Uzxw6gLVJ-VS=^tTy zapG7WAH!)UPneVw<5VEQoy3$ePPNlc-Yz-m`tX{`(1sd0)7lLqFSxx7!yrti#MUov YX#sO~XMr-l+vA%`j!LFx)kR%=0#-$~mjD0& literal 0 HcmV?d00001 diff --git a/test/simple_source/bug33/04_lambda_star_default.py b/test/simple_source/bug33/04_lambda_star_default.py index e27f0eee..879b8960 100644 --- a/test/simple_source/bug33/04_lambda_star_default.py +++ b/test/simple_source/bug33/04_lambda_star_default.py @@ -3,6 +3,7 @@ # Bug is handling default value after * argument in a lambda. # That's a mouthful of desciption; I am not sure if the really # hacky fix to the code is even correct. + # # FIXME: try and test with more than one default argument. @@ -14,4 +15,4 @@ packs = {w: (lambda *data, width=w: pack(width, data)) for w in (1, 2, 4)} assert packs[1]('a') == (1, ('a',)) assert packs[2]('b') == (2, ('b',)) -assert packs[4]('b') == (4, ('c',)) +assert packs[4]('c') == (4, ('c',)) diff --git a/uncompyle6/semantics/make_function.py b/uncompyle6/semantics/make_function.py index 4abfdedd..7f13599a 100644 --- a/uncompyle6/semantics/make_function.py +++ b/uncompyle6/semantics/make_function.py @@ -602,9 +602,8 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): pass if ( - 3.0 <= self.version <= 3.3 + self.version <= 3.3 and len(node) > 2 - and node[lambda_index] != "LOAD_LAMBDA" and (have_kwargs or node[lc_index].kind != "load_closure") ): @@ -615,12 +614,22 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): default_values_start = 0 if node[0] == "no_kwargs": default_values_start += 1 - # args are after kwargs; kwargs are bundled as one node - if node[default_values_start] == "kwargs": - default_values_start += 1 - defparams = node[ - default_values_start : default_values_start + args_node.attr[0] - ] + + # If in a lambda named args are a sequence of kwarg, not bundled. + # If not in a lambda, named args are after kwargs; kwargs are bundled as one node. + if node[default_values_start] == "kwarg": + assert node[lambda_index] == "LOAD_LAMBDA" + i = default_values_start + defparams = [] + while node[i] == "kwarg": + defparams.append(node[i][1]) + i += 1 + else: + if node[default_values_start] == "kwargs": + default_values_start += 1 + defparams = node[ + default_values_start : default_values_start + args_node.attr[0] + ] else: if self.version < 3.6: defparams = node[: args_node.attr[0]] @@ -718,11 +727,19 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): paramnames = list(scanner_code.co_varnames[:argc]) if kwonlyargcount > 0: - kwargs = list(scanner_code.co_varnames[argc : argc + kwonlyargcount]) + if self.version <= 3.3 and is_lambda: + kwargs = [] + for i in range(kwonlyargcount): + paramnames.append(scanner_code.co_varnames[argc+i]) + pass + pass + else: + kwargs = list(scanner_code.co_varnames[argc : argc + kwonlyargcount]) - # defaults are for last n parameters, thus reverse - paramnames.reverse() - defparams.reverse() + # defaults are for last n parameters when not in a lambda, thus reverse + if not is_lambda: + paramnames.reverse() + defparams.reverse() try: ast = self.build_ast( @@ -776,6 +793,9 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): params.append("*%s: %s" % (star_arg, annotate_dict[star_arg])) else: params.append("*%s" % star_arg) + pass + if is_lambda and self.version <= 3.3: + params.reverse() else: params.append("*%s" % code.co_varnames[argc]) argc += 1 @@ -810,7 +830,7 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): # created a parameter list and at the very end did a join on that? # Unless careful, We might lose line breaks though. ends_in_comma = False - if kwonlyargcount > 0: + if kwonlyargcount > 0 and not is_lambda: if not (4 & code.co_flags): if argc > 0: self.write(", *, ") @@ -819,7 +839,7 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): pass ends_in_comma = True else: - if argc > 0: + if argc > 0 and node[0] != "kwarg": self.write(", ") ends_in_comma = True @@ -832,14 +852,18 @@ def make_function3(self, node, is_lambda, nested=1, code_node=None): default = self.traverse(n[1], indent="") idx = kwargs.index(name) kw_args[idx] = "%s=%s" % (name, default) + pass + pass - other_kw = [c == None for c in kw_args] + if kw_nodes != "kwarg": + other_kw = [c == None for c in kw_args] - for i, flag in enumerate(other_kw): - if flag: - kw_args[i] = "%s" % kwargs[i] - self.write(", ".join(kw_args)) - ends_in_comma = False + for i, flag in enumerate(other_kw): + if flag: + kw_args[i] = "%s" % kwargs[i] + self.write(", ".join(kw_args)) + ends_in_comma = False + pass elif self.version >= 3.6: # argc = node[-1].attr # co = node[-3].attr