From 74f01fbe3345e3e0248281cc3f33a726bfcd0c6f Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 26 Mar 2018 07:42:15 -0400 Subject: [PATCH] Python 3.5 CALL_FUNCTION_VAR handling --- test/bytecode_3.4_run/04_call_function.pyc | Bin 1251 -> 1247 bytes test/bytecode_3.5/04_call_function.pyc | Bin 991 -> 0 bytes test/simple_source/bug35/04_call_function.py | 8 +++-- uncompyle6/semantics/customize.py | 36 ++++++++++++------- 4 files changed, 29 insertions(+), 15 deletions(-) delete mode 100644 test/bytecode_3.5/04_call_function.pyc diff --git a/test/bytecode_3.4_run/04_call_function.pyc b/test/bytecode_3.4_run/04_call_function.pyc index 115f9dd3796584937f6bee5ed81d13b1e89eef48..96fb939a10086794abdaece1c7b683373589c18a 100644 GIT binary patch delta 231 zcmaFNd7o4H9S<*8`t==A0xS#+j~S2vGmz~7#KpZ6mCJ-uIT@N67#K4d7*e|`d82oNw$ZemuJWn@TUVvwu>Qp^yF1wyfcsL6+zW7(LBKn|R& k%Oc09KG}z*L6Qx~EfxS0{OmkzGK@ToJS-B-JZ$W&08Hv5MgRZ+ delta 235 zcmcc5`IuAr9S<*;R_2bV|I7>wj~S2v3y|#q#KoNxmCN{27#K1c7*er2aB3LvTiGSG4`V4mE)auK`{ z|A+s;-!fNE`~*E&)d&*pOjUo=U0qdQRoxs8``G%P{PchyxUzi4FImh!tAam5;o*dk zF!oUdH~|tq3{gZVJyaeN);ioX!M9UKG41hWI%#b@@_ zL(z9O41kSzX`DwKURLLiyyo59W3}+H2(ch60!eP+VFBy{Up+dCu!#7%H*O=7e^6Bx zQycB=XL`rPoi;G4oFv^!*{sNHrir~J;byj7sx}atHmI{owV{=xZ_pC^*8?-HW~E9^ zGuOFV+n(<{dA7FxG|jWJOega?x6`J6G&^Yfwz+T}NU~j4AfF<-;praZoNMit>>`d+ zp8+#qLZ?EV#x88^wSHb2EuP%Lxe}l4YHF;W*=eOx=Ai^E@wsvCNeez>LF~8P3xl>R zW`|9!+Mb|7l{U+z0~$l?-OV_+{De+)VzSg!N=H2C=9;Wkf!<+_t}@f5TXhvTGU zRNmBu(F1;eChbcidpNBpP3-Fx{?$WK%dBEA=}BU#WRip~mw!o)Hu>)H+uAB!XQfzQ zT}%Gb zchyJ&A@67;y|UqHlK*!3l`%@oNV)jV%a!Odk=hMG_j%P6^HRNVvnDlP=?tQ~G@wCn G%l{3KKE+Z1 diff --git a/test/simple_source/bug35/04_call_function.py b/test/simple_source/bug35/04_call_function.py index 421c3f76..6355d27e 100644 --- a/test/simple_source/bug35/04_call_function.py +++ b/test/simple_source/bug35/04_call_function.py @@ -1,6 +1,8 @@ # From sql/schema.py and 3.5 _strptime.py # Note that kwargs comes before "positional" args +# RUNNABLE! + def tometadata(self, metadata, schema, Table, args, name=None): table = Table( name, metadata, schema=schema, @@ -23,16 +25,18 @@ def Time2Internaldate(date_time): assert Time2Internaldate(time.localtime()) # From 3.5.5 tkinter/dialog.py -def test_varargs0_ext(self): +def test_varargs0_ext(): try: {}.__contains__(*()) except TypeError: pass +test_varargs0_ext() + # From 3.4.6 tkinter/dialog.py # Bug is in position of *cnf. -def __init__(self, master=None, cnf={}): +def __init__(self, cnf={}): self.num = self.tk.call( 'tk_dialog', self._w, cnf['title'], cnf['text'], diff --git a/uncompyle6/semantics/customize.py b/uncompyle6/semantics/customize.py index a5411dcf..b0d1a3ea 100644 --- a/uncompyle6/semantics/customize.py +++ b/uncompyle6/semantics/customize.py @@ -254,8 +254,8 @@ def customize_for_version(self, is_pypy, version): elif key.kind.startswith('CALL_FUNCTION_VAR'): # CALL_FUNCTION_VAR's top element of the stack contains # the variable argument list, then comes - # annotation args, then keyword args, - # and finally on the most bottom (but position 1 + # annotation args, then keyword args. + # In the most least-top-most stack entry, but position 1 # in node order, the positional args. argc = node[-1].attr nargs = argc & 0xFF @@ -320,11 +320,15 @@ def customize_for_version(self, is_pypy, version): key = key[i] pass if key.kind.startswith('CALL_FUNCTION_VAR_KW'): - # Python 3.5 changes the stack position of *args. kwargs come - # after *args whereas in earlier Pythons, *args is at the end - # which simplifies things from our perspective. - # Python 3.6+ replaces CALL_FUNCTION_VAR_KW with CALL_FUNCTION_EX - # We will just swap the order to make it look like earlier Python 3. + # Python 3.5 changes the stack position of + # *args: kwargs come after *args whereas + # in earlier Pythons, *args is at the end + # which simplifies things from our + # perspective. Python 3.6+ replaces + # CALL_FUNCTION_VAR_KW with + # CALL_FUNCTION_EX We will just swap the + # order to make it look like earlier + # Python 3. entry = table[key.kind] kwarg_pos = entry[2][1] args_pos = kwarg_pos - 1 @@ -335,7 +339,15 @@ def customize_for_version(self, is_pypy, version): args_pos = kwarg_pos kwarg_pos += 1 elif key.kind.startswith('CALL_FUNCTION_VAR'): - nargs = node[-1].attr & 0xFF + # CALL_FUNCTION_VAR's top element of the stack contains + # the variable argument list, then comes + # annotation args, then keyword args. + # In the most least-top-most stack entry, but position 1 + # in node order, the positional args. + argc = node[-1].attr + nargs = argc & 0xFF + kwargs = (argc >> 8) & 0xFF + # FIXME: handle annotation args if nargs > 0: template = ('%c(%C, ', 0, (1, nargs+1, ', ')) else: @@ -343,16 +355,14 @@ def customize_for_version(self, is_pypy, version): self.template_engine(template, node) args_node = node[-2] - if args_node == 'pos_arg': - args_node = args_node[0] - if args_node == 'expr': + if args_node in ('pos_arg', 'expr'): args_node = args_node[0] if args_node == 'build_list_unpack': template = ('*%P)', (0, len(args_node)-1, ', *', 100)) self.template_engine(template, args_node) else: - if len(node) > 3: - template = ('*%c, %C)', 1, (2, -1, ', ')) + if len(node) - nargs > 3: + template = ('*%c, %C)', 1, (nargs+kwargs+1, -1, ', ')) else: template = ('*%c)', 1) self.template_engine(template, node)