diff --git a/test/bytecode_3.4_run/04_call_function.pyc b/test/bytecode_3.4_run/04_call_function.pyc index 115f9dd3..96fb939a 100644 Binary files a/test/bytecode_3.4_run/04_call_function.pyc and b/test/bytecode_3.4_run/04_call_function.pyc differ diff --git a/test/bytecode_3.5/04_call_function.pyc b/test/bytecode_3.5/04_call_function.pyc deleted file mode 100644 index 6b44e22d..00000000 Binary files a/test/bytecode_3.5/04_call_function.pyc and /dev/null differ 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)