diff --git a/test/bytecode_3.4/03_py3_def.pyc b/test/bytecode_3.4/03_py3_def.pyc new file mode 100644 index 00000000..8da342d9 Binary files /dev/null and b/test/bytecode_3.4/03_py3_def.pyc differ diff --git a/test/bytecode_3.4/15_static_method.pyc b/test/bytecode_3.4/15_static_method.pyc new file mode 100644 index 00000000..0427ec27 Binary files /dev/null and b/test/bytecode_3.4/15_static_method.pyc differ diff --git a/test/bytecode_3.5/03_py3_def.pyc b/test/bytecode_3.5/03_py3_def.pyc new file mode 100644 index 00000000..b1abd88c Binary files /dev/null and b/test/bytecode_3.5/03_py3_def.pyc differ diff --git a/test/simple_source/def/03_py3_def.py b/test/simple_source/def/03_py3_def.py new file mode 100644 index 00000000..5208fcdc --- /dev/null +++ b/test/simple_source/def/03_py3_def.py @@ -0,0 +1,16 @@ +# Test of Python 3's *, or named parameters +# kwargs ::= \e_kwargs kwarg +# kwargs ::= kwargs kwarg +# mkfunc ::= pos_arg \e_kwargs LOAD_CONST LOAD_CONST MAKE_FUNCTION_N2_1 +# +def x0(*, file='sample_file'): + pass + +def x1(a, *, file=None): + pass + +def x2(a=5, *, file='filex2'): + pass + +def x3(a=5, *, file='filex2', stuff=None): + pass diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index f6d4a5d9..fcb91d59 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -201,6 +201,8 @@ class Python3Parser(PythonParser): del_stmt ::= expr DELETE_ATTR kwarg ::= LOAD_CONST expr + kwargs ::= kwargs kwarg + kwargs ::= classdef ::= build_class designator # Python3 introduced LOAD_BUILD_CLASS @@ -507,21 +509,17 @@ class Python3Parser(PythonParser): elif opname_base == 'UNPACK_LIST': rule = 'unpack_list ::= ' + opname + ' designator' * token.attr elif opname_base.startswith('MAKE_FUNCTION'): - self.addRule('mklambda ::= %s LOAD_LAMBDA %s' % - ('expr ' * token.attr, opname), nop_func) - rule = 'mkfunc ::= %sLOAD_CONST %s' % ('expr ' * token.attr, opname) - self.add_unique_rule(rule, opname, token.attr, customize) - if opname.startswith('MAKE_FUNCTION_N'): - args_pos = token.attr & 0xff - args_kw = (token.attr >> 8) & 0xff - rule = ('mkfunc ::= %s %s %s %s' % + args_pos, args_kw, annotate_args = token.attr + self.addRule('mklambda ::= %sLOAD_LAMBDA %s' % + ('pos_arg ' * args_pos, opname), nop_func) + if self.version > 3.2: + rule = ('mkfunc ::= %skwargs %s %s' % ('pos_arg ' * args_pos, - 'expr ' * args_kw, - 'LOAD_CONST ' * 3, + 'LOAD_CONST ' * 2, opname)) else: - rule = 'mkfunc ::= %sLOAD_CONST LOAD_CONST %s' % ('pos_arg ' * token.attr, opname) - pass + rule = ('mkfunc ::= %sLOAD_CONST %s' % + ('pos_arg ' * args_pos, opname)) self.add_unique_rule(rule, opname, token.attr, customize) elif opname.startswith('MAKE_CLOSURE'): self.add_unique_rule('mklambda ::= %sload_closure LOAD_LAMBDA %s' % diff --git a/uncompyle6/scanners/dis35.py b/uncompyle6/scanners/dis35.py index bb4d3c7f..30ba5a35 100644 --- a/uncompyle6/scanners/dis35.py +++ b/uncompyle6/scanners/dis35.py @@ -306,7 +306,8 @@ def _get_instructions_bytes(code, varnames=None, names=None, constants=None, elif op in hasfree: argval, argrepr = _get_name_info(arg, cells) elif op in hasnargs: - argrepr = "%d positional, %d keyword pair" % (code[i-2], code[i-1]) + argrepr = ("%d positional, %d keyword pair, %d annotated" % + (code[i-2], code[i-1], code[i])) yield Instruction(opname[op_num], op, arg, argval, argrepr, offset, starts_line, is_jump_target) diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index d21e56e8..042c21b5 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -167,7 +167,29 @@ class Scanner3(scan.Scanner): elif op in op3.hasfree: pattr = free[oparg] - if op_name in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET', 'BUILD_SLICE', + if op_name == 'MAKE_FUNCTION': + argc = oparg + attr = ((argc & 0xFF), (argc >> 8) & 0xFF, (argc >> 16) & 0x7FFF) + pos_args, name_pair_args, annotate_args = attr + if name_pair_args > 0: + op_name = 'MAKE_FUNCTION_N%d' % name_pair_args + pass + if annotate_args > 0: + op_name = '%s_A_%d' % [op_name, annotate_args] + pass + op_name = '%s_%d' % (op_name, pos_args) + pattr = ("%d positional, %d keyword pair, %d annotated" % + (pos_args, name_pair_args, annotate_args)) + tokens.append( + Token( + type_ = op_name, + attr = (pos_args, name_pair_args, annotate_args), + pattr = pattr, + offset = offset, + linestart = linestart) + ) + continue + elif op_name in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET', 'BUILD_SLICE', 'UNPACK_SEQUENCE', 'MAKE_FUNCTION', 'CALL_FUNCTION', 'MAKE_CLOSURE', 'CALL_FUNCTION_VAR', 'CALL_FUNCTION_KW', diff --git a/uncompyle6/scanners/scanner34.py b/uncompyle6/scanners/scanner34.py index e19c120e..e03352ec 100644 --- a/uncompyle6/scanners/scanner34.py +++ b/uncompyle6/scanners/scanner34.py @@ -108,10 +108,32 @@ class Scanner34(scan3.Scanner3): else: pattr = const pass + elif opname == 'MAKE_FUNCTION': + argc = inst.argval + attr = ((argc & 0xFF), (argc >> 8) & 0xFF, (argc >> 16) & 0x7FFF) + pos_args, name_pair_args, annotate_args = attr + if name_pair_args > 0: + opname = 'MAKE_FUNCTION_N%d' % name_pair_args + pass + if annotate_args > 0: + opname = '%s_A_%d' % [op_name, annotate_args] + pass + opname = '%s_%d' % (opname, pos_args) + pattr = ("%d positional, %d keyword pair, %d annotated" % + (pos_args, name_pair_args, annotate_args)) + tokens.append( + Token( + type_ = opname, + attr = (pos_args, name_pair_args, annotate_args), + pattr = pattr, + offset = inst.offset, + linestart = inst.starts_line) + ) + continue elif opname in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET', 'BUILD_SLICE', 'UNPACK_SEQUENCE', - 'MAKE_FUNCTION', 'MAKE_CLOSURE', - 'DUP_TOPX', 'RAISE_VARARGS' + 'MAKE_CLOSURE', + 'RAISE_VARARGS' ): # if opname == 'BUILD_TUPLE' and \ # self.code[self.prev[offset]] == LOAD_CLOSURE: diff --git a/uncompyle6/scanners/scanner35.py b/uncompyle6/scanners/scanner35.py index 469c31cb..f1f47257 100644 --- a/uncompyle6/scanners/scanner35.py +++ b/uncompyle6/scanners/scanner35.py @@ -30,6 +30,8 @@ class Scanner35(scan3.Scanner3): # we do post-processing like we do here. def disassemble(self, co, classname=None, code_objects={}): + + # dis.disassemble(co) # DEBUG # Container for tokens tokens = [] customize = {} @@ -104,28 +106,37 @@ class Scanner35(scan3.Scanner3): else: pattr = const pass + elif opname == 'MAKE_FUNCTION': + argc = inst.argval + attr = ((argc & 0xFF), (argc >> 8) & 0xFF, (argc >> 16) & 0x7FFF) + pos_args, name_pair_args, annotate_args = attr + if name_pair_args > 0: + opname = 'MAKE_FUNCTION_N%d' % name_pair_args + pass + if annotate_args > 0: + opname = '%s_A_%d' % [op_name, annotate_args] + pass + opname = '%s_%d' % (opname, pos_args) + pattr = ("%d positional, %d keyword pair, %d annotated" % + (pos_args, name_pair_args, annotate_args)) + tokens.append( + Token( + type_ = opname, + attr = (pos_args, name_pair_args, annotate_args), + pattr = pattr, + offset = inst.offset, + linestart = inst.starts_line) + ) + continue elif opname in ('BUILD_LIST', 'BUILD_TUPLE', 'BUILD_SET', 'BUILD_SLICE', - 'BUILD_MAP', - 'UNPACK_SEQUENCE', - 'MAKE_FUNCTION', 'MAKE_CLOSURE', - 'DUP_TOPX', 'RAISE_VARARGS' + 'BUILD_MAP', 'UNPACK_SEQUENCE', 'MAKE_CLOSURE', + 'RAISE_VARARGS' ): pos_args = inst.argval - if inst.opname == 'MAKE_FUNCTION': - argc = inst.argval - pos_args = (argc & 0xFF) - name_pair_args = (argc >> 8) & 0xFF - if name_pair_args > 0: - opname = 'MAKE_FUNCTION_N%d' % name_pair_args - pass - annotate_args = (argc >> 16) & 0x7FFF - if annotate_args > 0: - opname = '%s_A_%d' % [op_name, annotate_args] - pass - elif inst.opname != 'BUILD_SLICE': + if inst.opname != 'BUILD_SLICE': customize[opname] = pos_args + pass opname = '%s_%d' % (opname, pos_args) - elif opname == 'JUMP_ABSOLUTE': pattr = inst.argval target = self.get_target(inst.offset) diff --git a/uncompyle6/semantics/fragments.py b/uncompyle6/semantics/fragments.py index feff2cc1..02053312 100644 --- a/uncompyle6/semantics/fragments.py +++ b/uncompyle6/semantics/fragments.py @@ -191,7 +191,7 @@ class FragmentsWalker(pysource.SourceWalker, object): pass pass self.set_pos_info(node, start, len(self.f.getvalue())) - self.print_() + self.println() self.prune() # stop recursing def n_return_if_stmt(self, node): @@ -208,7 +208,7 @@ class FragmentsWalker(pysource.SourceWalker, object): self.preorder(node[0]) if hasattr(node[-1], 'offset'): self.set_pos_info(node[-1], start, len(self.f.getvalue())) - self.print_() + self.println() self.set_pos_info(node, start, len(self.f.getvalue())) self.prune() # stop recursing @@ -350,7 +350,7 @@ class FragmentsWalker(pysource.SourceWalker, object): self.write(sep); sep = ", " self.preorder(subnode) self.set_pos_info(node, start, len(self.f.getvalue())) - self.print_() + self.println() self.prune() # stop recursing def n_ifelsestmtr(self, node): @@ -365,7 +365,7 @@ class FragmentsWalker(pysource.SourceWalker, object): start = len(self.f.getvalue()) + len(self.indent) self.write(self.indent, 'if ') self.preorder(node[0]) - self.print_(':') + self.println(':') self.indentMore() node[1].parent = node self.preorder(node[1]) @@ -387,13 +387,13 @@ class FragmentsWalker(pysource.SourceWalker, object): else: prev_stmt_is_if_ret = False if not past_else and not if_ret_at_end: - self.print_(self.indent, 'else:') + self.println(self.indent, 'else:') self.indentMore() past_else = True n.parent = node self.preorder(n) if not past_else or if_ret_at_end: - self.print_(self.indent, 'else:') + self.println(self.indent, 'else:') self.indentMore() node[2][1].parent = node self.preorder(node[2][1]) @@ -414,7 +414,7 @@ class FragmentsWalker(pysource.SourceWalker, object): self.write(self.indent, 'elif ') node[0].parent = node self.preorder(node[0]) - self.print_(':') + self.println(':') self.indentMore() node[1].parent = node self.preorder(node[1]) @@ -424,7 +424,7 @@ class FragmentsWalker(pysource.SourceWalker, object): n[0].type = 'elifstmt' n.parent = node self.preorder(n) - self.print_(self.indent, 'else:') + self.println(self.indent, 'else:') self.indentMore() node[2][1].parent = node self.preorder(node[2][1]) @@ -680,7 +680,7 @@ class FragmentsWalker(pysource.SourceWalker, object): self.print_super_classes3(subclass_info) else: self.print_super_classes(build_list) - self.print_(':') + self.println(':') # class body self.indentMore() @@ -704,7 +704,7 @@ class FragmentsWalker(pysource.SourceWalker, object): self.name = name # if code would be empty, append 'pass' if len(ast) == 0: - self.print_(self.indent, 'pass') + self.println(self.indent, 'pass') else: self.customize(customize) self.text = self.traverse(ast, isLambda=isLambda) @@ -1238,19 +1238,23 @@ class FragmentsWalker(pysource.SourceWalker, object): - handle defaults - handle format tuple parameters """ - # if formal parameter is a tuple, the paramater name - # starts with a dot (eg. '.1', '.2') - if name.startswith('.'): - # replace the name with the tuple-string - name = self.get_tuple_parameter(ast, name) + if self.version < 3.0: + # if formal parameter is a tuple, the paramater name + # starts with a dot (eg. '.1', '.2') + if name.startswith('.'): + # replace the name with the tuple-string + name = self.get_tuple_parameter(ast, name) + pass + pass if default: if self.showast: + print() print('--', name) print(default) print('--') pass - result = '%s = ' % name + result = '%s=' % name old_last_finish = self.last_finish self.last_finish = len(result) value = self.traverse(default, indent='') @@ -1262,14 +1266,22 @@ class FragmentsWalker(pysource.SourceWalker, object): else: return name - # node[-1] == MAKE_xxx_n + # node[-1] == MAKE_FUNCTION_n + + args_node = node[-1] + if isinstance(args_node.attr, tuple): + defparams = node[:args_node.attr[0]] + pos_args, kw_args, annotate_args = args_node.attr + else: + defparams = node[:args_node.attr] + kw_args, annotate_args = (0, 0) + pos_args = args_node.attr + pass - defparams = node[:node[-1].attr] code = node[code_index].attr - assert type(code) == CodeType + assert iscode(code) code = Code(code, self.scanner, self.currentclass) - # assert isinstance(code, Code) # add defaults values to parameter names argc = code.co_argcount @@ -1284,7 +1296,7 @@ class FragmentsWalker(pysource.SourceWalker, object): isLambda = isLambda, noneInNames = ('None' in code.co_names)) except ParserError as p: - self.write( str(p)) + self.write(str(p)) self.ERROR = p return @@ -1292,12 +1304,6 @@ class FragmentsWalker(pysource.SourceWalker, object): params = [build_param(ast, name, default) for name, default in zip_longest(paramnames, defparams, fillvalue=None)] - # params = [ build_param(ast, name, default) for - # name, default in zip(paramnames, defparams) ] - # params = [] - # for i, name in enumerate(paramnames): - # default = defparams[i] if len(defparams) > i else None - # params.append( build_param(ast, name, default) ) params.reverse() # back to correct order @@ -1311,10 +1317,27 @@ class FragmentsWalker(pysource.SourceWalker, object): # dump parameter list (with default values) indent = self.indent if isLambda: - self.write("lambda ", ", ".join(params), ": ") + self.write("lambda ", ", ".join(params)) else: - self.print_("(", ", ".join(params), "):") - # self.print_(indent, '#flags:\t', int(code.co_flags)) + self.write("(", ", ".join(params)) + # self.println(indent, '#flags:\t', int(code.co_flags)) + + if kw_args > 0: + if argc > 0: + self.write(", *, ") + else: + self.write("*, ") + for n in node: + if n == 'pos_arg': + continue + self.preorder(n) + break + pass + + if isLambda: + self.write(": ") + else: + self.println("):") if len(code.co_consts)>0 and code.co_consts[0] is not None and not isLambda: # ugly # docstring exists, dump it @@ -1325,7 +1348,7 @@ class FragmentsWalker(pysource.SourceWalker, object): all_globals = find_all_globals(ast, set()) for g in ((all_globals & self.mod_globs) | find_globals(ast, set())): - self.print_(self.indent, 'global ', g) + self.println(self.indent, 'global ', g) self.mod_globs -= all_globals rn = ('None' in code.co_names) and not find_none(ast) self.gen_source(ast, code.co_name, code._customize, isLambda=isLambda, diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 479e5635..d9166c99 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -48,6 +48,9 @@ methods implement most of the below. %c evaluate children N[A] recursively* %C evaluate children N[A[0]]..N[A[1]-1] recursively, separate by A[2]* %P same as %C but sets operator precedence + %D same as %C but is for left-recursive lists like kwargs which + goes to epsilon at the beginning. Using %C an extra separator + with an epsilon appears at the beginning %, print ',' if last %C only printed one item (for tuples--unused) %| tab to current indentation level %+ increase current indentation level @@ -261,6 +264,7 @@ TABLE_DIRECT = { 'classdefdeco': ( '%c', 0), 'classdefdeco1': ( '\n\n%|@%c%c', 0, 1), 'kwarg': ( '%[0]{pattr}=%c', 1), + 'kwargs': ( '%D', (0, maxint, ', ') ), 'importlist2': ( '%C', (0, maxint, ', ') ), 'assert': ( '%|assert %c\n' , 0 ), @@ -597,7 +601,7 @@ class SourceWalker(GenericASTTraversal, object): out = out[:-self.pending_newlines] self.f.write(out) - def print_(self, *data): + def println(self, *data): if data and not(len(data) == 1 and data[0] ==''): self.write(*data) self.pending_newlines = max(self.pending_newlines, 1) @@ -654,14 +658,14 @@ class SourceWalker(GenericASTTraversal, object): self.write(quote) if len(trimmed) == 0: - self.print_(quote) + self.println(quote) elif len(trimmed) == 1: - self.print_(trimmed[0], quote) + self.println(trimmed[0], quote) else: - self.print_(trimmed[0]) + self.println(trimmed[0]) for line in trimmed[1:-1]: - self.print_( indent, line ) - self.print_(indent, trimmed[-1], quote) + self.println( indent, line ) + self.println(indent, trimmed[-1], quote) def n_return_stmt(self, node): if self.params['isLambda']: @@ -672,7 +676,7 @@ class SourceWalker(GenericASTTraversal, object): if self.return_none or node != AST('return_stmt', [AST('ret_expr', [NONE]), Token('RETURN_VALUE')]): self.write(' ') self.preorder(node[0]) - self.print_() + self.println() self.prune() # stop recursing def n_return_if_stmt(self, node): @@ -684,7 +688,7 @@ class SourceWalker(GenericASTTraversal, object): if self.return_none or node != AST('return_stmt', [AST('ret_expr', [NONE]), Token('RETURN_END_IF')]): self.write(' ') self.preorder(node[0]) - self.print_() + self.println() self.prune() # stop recursing def n_yield(self, node): @@ -817,7 +821,7 @@ class SourceWalker(GenericASTTraversal, object): for subnode in node[1]: self.write(sep); sep = ", " self.preorder(subnode) - self.print_() + self.println() self.prune() # stop recursing def n_ifelsestmt(self, node, preprocess=0): @@ -860,7 +864,7 @@ class SourceWalker(GenericASTTraversal, object): self.write(self.indent, 'if ') self.preorder(node[0]) - self.print_(':') + self.println(':') self.indentMore() self.preorder(node[1]) self.indentLess() @@ -880,12 +884,12 @@ class SourceWalker(GenericASTTraversal, object): else: prev_stmt_is_if_ret = False if not past_else and not if_ret_at_end: - self.print_(self.indent, 'else:') + self.println(self.indent, 'else:') self.indentMore() past_else = True self.preorder(n) if not past_else or if_ret_at_end: - self.print_(self.indent, 'else:') + self.println(self.indent, 'else:') self.indentMore() self.preorder(node[2][1]) self.indentLess() @@ -902,7 +906,7 @@ class SourceWalker(GenericASTTraversal, object): self.write(self.indent, 'elif ') self.preorder(node[0]) - self.print_(':') + self.println(':') self.indentMore() self.preorder(node[1]) self.indentLess() @@ -910,7 +914,7 @@ class SourceWalker(GenericASTTraversal, object): for n in node[2][0]: n[0].type = 'elifstmt' self.preorder(n) - self.print_(self.indent, 'else:') + self.println(self.indent, 'else:') self.indentMore() self.preorder(node[2][1]) self.indentLess() @@ -952,6 +956,7 @@ class SourceWalker(GenericASTTraversal, object): self.indentMore() self.make_function(node, isLambda=False, code_index=code_index) + if len(self.param_stack) > 1: self.write('\n\n') else: @@ -1135,7 +1140,10 @@ class SourceWalker(GenericASTTraversal, object): if self.version > 3.0: currentclass = node[1][0].pattr buildclass = node[0] - subclass = buildclass[1][0].attr + if buildclass[1][0] == 'kwargs': + subclass = buildclass[1][1].attr + else: + subclass = buildclass[1][0].attr subclass_info = node[0] else: buildclass = node[0] @@ -1157,7 +1165,7 @@ class SourceWalker(GenericASTTraversal, object): self.print_super_classes3(subclass_info) else: self.print_super_classes(build_list) - self.print_(':') + self.println(':') # class body self.indentMore() @@ -1354,7 +1362,7 @@ class SourceWalker(GenericASTTraversal, object): %c, %C, and so on. """ - # self.print_("-----") + # self.println("-----") # self.print(startnode) fmt = entry[0] @@ -1412,6 +1420,19 @@ class SourceWalker(GenericASTTraversal, object): if remaining > 0: self.write(sep) arg += 1 + elif typ == 'D': + low, high, sep = entry[arg] + remaining = len(node[low:high]) + for subnode in node[low:high]: + remaining -= 1 + if len(subnode) > 0: + self.preorder(subnode) + if remaining > 0: + self.write(sep) + pass + pass + pass + arg += 1 elif typ == 'P': p = self.prec low, high, sep, self.prec = entry[arg] @@ -1530,12 +1551,13 @@ class SourceWalker(GenericASTTraversal, object): - handle format tuple parameters """ if self.version < 3.0: - # rocky: is this still even relevant? # if formal parameter is a tuple, the paramater name # starts with a dot (eg. '.1', '.2') if name.startswith('.'): # replace the name with the tuple-string name = self.get_tuple_parameter(ast, name) + pass + pass if default: if self.showast: @@ -1543,15 +1565,25 @@ class SourceWalker(GenericASTTraversal, object): print('--', name) print(default) print('--') - result = '%s = %s' % (name, self.traverse(default, indent='') ) + result = '%s=%s' % (name, self.traverse(default, indent='') ) if result[-2:] == '= ': # default was 'LOAD_CONST None' result += 'None' return result else: return name - # node[-1] == MAKE_xxx_n - defparams = node[:node[-1].attr] + # node[-1] == MAKE_FUNCTION_n + + args_node = node[-1] + if isinstance(args_node.attr, tuple): + defparams = node[:args_node.attr[0]] + pos_args, kw_args, annotate_args = args_node.attr + else: + defparams = node[:args_node.attr] + kw_args, annotate_args = (0, 0) + pos_args = args_node.attr + pass + code = node[code_index].attr assert iscode(code) @@ -1570,19 +1602,14 @@ class SourceWalker(GenericASTTraversal, object): isLambda = isLambda, noneInNames = ('None' in code.co_names)) except ParserError as p: - self.write( str(p)) + self.write(str(p)) self.ERROR = p return # build parameters + params = [build_param(ast, name, default) for name, default in zip_longest(paramnames, defparams, fillvalue=None)] - # params = [ build_param(ast, name, default) for - # name, default in zip(paramnames, defparams) ] - # params = [] - # for i, name in enumerate(paramnames): - # default = defparams[i] if len(defparams) > i else None - # params.append( build_param(ast, name, default) ) params.reverse() # back to correct order @@ -1596,10 +1623,27 @@ class SourceWalker(GenericASTTraversal, object): # dump parameter list (with default values) indent = self.indent if isLambda: - self.write("lambda ", ", ".join(params), ": ") + self.write("lambda ", ", ".join(params)) else: - self.print_("(", ", ".join(params), "):") - # self.print_(indent, '#flags:\t', int(code.co_flags)) + self.write("(", ", ".join(params)) + # self.println(indent, '#flags:\t', int(code.co_flags)) + + if kw_args > 0: + if argc > 0: + self.write(", *, ") + else: + self.write("*, ") + for n in node: + if n == 'pos_arg': + continue + self.preorder(n) + break + pass + + if isLambda: + self.write(": ") + else: + self.println("):") if len(code.co_consts)>0 and code.co_consts[0] is not None and not isLambda: # ugly # docstring exists, dump it @@ -1610,10 +1654,11 @@ class SourceWalker(GenericASTTraversal, object): all_globals = find_all_globals(ast, set()) for g in ((all_globals & self.mod_globs) | find_globals(ast, set())): - self.print_(self.indent, 'global ', g) + self.println(self.indent, 'global ', g) self.mod_globs -= all_globals rn = ('None' in code.co_names) and not find_none(ast) - self.gen_source(ast, code.co_name, code._customize, isLambda=isLambda, returnNone=rn) + self.gen_source(ast, code.co_name, code._customize, isLambda=isLambda, + returnNone=rn) code._tokens = None; code._customize = None # save memory def build_class(self, code): @@ -1624,7 +1669,7 @@ class SourceWalker(GenericASTTraversal, object): code = Code(code, self.scanner, self.currentclass) indent = self.indent - # self.print_(indent, '#flags:\t', int(code.co_flags)) + # self.println(indent, '#flags:\t', int(code.co_flags)) ast = self.build_ast(code._tokens, code._customize) code._tokens = None # save memory assert ast == 'stmts' @@ -1664,7 +1709,7 @@ class SourceWalker(GenericASTTraversal, object): except: docstring = code.co_consts[0] self.print_docstring(indent, docstring) - self.print_() + self.println() del ast[i] @@ -1676,7 +1721,7 @@ class SourceWalker(GenericASTTraversal, object): # print ast[-1][-1] for g in find_globals(ast, set()): - self.print_(indent, 'global ', g) + self.println(indent, 'global ', g) self.gen_source(ast, code.co_name, code._customize) code._tokens = None; code._customize = None # save memory @@ -1690,14 +1735,14 @@ class SourceWalker(GenericASTTraversal, object): self.name = name # if code would be empty, append 'pass' if len(ast) == 0: - self.print_(self.indent, 'pass') + self.println(self.indent, 'pass') else: self.customize(customize) if isLambda: self.write(self.traverse(ast, isLambda=isLambda)) else: self.text = self.traverse(ast, isLambda=isLambda) - self.print_(self.text) + self.println(self.text) self.return_none = rn def build_ast(self, tokens, customize, isLambda=0, noneInNames=False): @@ -1711,7 +1756,7 @@ class SourceWalker(GenericASTTraversal, object): except (python_parser.ParserError, AssertionError) as e: raise ParserError(e, tokens) if self.showast: - self.print_(repr(ast)) + self.println(repr(ast)) return ast # The bytecode for the end of the main routine has a @@ -1735,7 +1780,7 @@ class SourceWalker(GenericASTTraversal, object): raise ParserError(e, tokens) if self.showast: - self.print_(repr(ast)) + self.println(repr(ast)) return ast