def n_mkfunc(self, node): """If the function has a docstring (this is found in the code constants), pull that out and make it part of the syntax tree. When generating the source string that AST node rather than the code field is seen and used. """ if self.version >= (3, 7): code_index = -3 else: code_index = -2 code = find_code_node(node, code_index).attr mkfunc_pattr = node[-1].pattr if isinstance(mkfunc_pattr, tuple): assert len(mkfunc_pattr, 4) and isinstance(mkfunc_pattr, int) is_closure = node[-1].pattr[3] != 0 else: # FIXME: This is what we had before. It is hoaky and probably wrong. is_closure = mkfunc_pattr == "closure" if ((not is_closure) and len(code.co_consts) > 0 and isinstance(code.co_consts[0], str)): docstring_node = SyntaxTree( "docstring", [Token("LOAD_STR", has_arg=True, pattr=code.co_consts[0])]) docstring_node.transformed_by = "n_mkfunc" node = SyntaxTree("mkfunc", node[:-1] + [docstring_node, node[-1]]) node.transformed_by = "n_mkfunc" return node
def n_mkfunc(self, node): """If the function has a docstring (this is found in the code constants), pull that out and make it part of the syntax tree. When generating the source string that AST node rather than the code field is seen and used. """ if self.version >= 3.7: code_index = -3 else: code_index = -2 code = find_code_node(node, code_index).attr if ( node[-1].pattr != "closure" and len(code.co_consts) > 0 and code.co_consts[0] is not None ): docstring_node = SyntaxTree( "docstring", [Token("LOAD_STR", has_arg=True, pattr=code.co_consts[0])] ) docstring_node.transformed_by = "n_mkfunc" node = SyntaxTree("mkfunc", node[:-1] + [docstring_node, node[-1]]) node.transformed_by = "n_mkfunc" return node
def n_classdef3(node): """Handle "classdef" nonterminal for 3.0 >= version 3.0 <= 3.5 """ assert 3.0 <= self.version <= 3.5 # class definition ('class X(A,B,C):') cclass = self.currentclass # Pick out various needed bits of information # * class_name - the name of the class # * subclass_info - the parameters to the class e.g. # class Foo(bar, baz) # ---------- # * subclass_code - the code for the subclass body subclass_info = None if node == "classdefdeco2": if self.version <= 3.3: class_name = node[2][0].attr else: class_name = node[1][2].attr build_class = node else: build_class = node[0] class_name = node[1][0].attr build_class = node[0] assert "mkfunc" == build_class[1] mkfunc = build_class[1] if mkfunc[0] in ("kwargs", "no_kwargs"): if 3.0 <= self.version <= 3.2: for n in mkfunc: if hasattr(n, "attr") and iscode(n.attr): subclass_code = n.attr break elif n == "expr": subclass_code = n[0].attr pass pass else: for n in mkfunc: if hasattr(n, "attr") and iscode(n.attr): subclass_code = n.attr break pass pass if node == "classdefdeco2": subclass_info = node else: subclass_info = node[0] elif build_class[1][0] == "load_closure": # Python 3 with closures not functions load_closure = build_class[1] if hasattr(load_closure[-3], "attr"): # Python 3.3 classes with closures work like this. # Note have to test before 3.2 case because # index -2 also has an attr. subclass_code = find_code_node(load_closure, -3).attr elif hasattr(load_closure[-2], "attr"): # Python 3.2 works like this subclass_code = find_code_node(load_closure, -2).attr else: raise "Internal Error n_classdef: cannot find class body" if hasattr(build_class[3], "__len__"): if not subclass_info: subclass_info = build_class[3] elif hasattr(build_class[2], "__len__"): subclass_info = build_class[2] else: raise "Internal Error n_classdef: cannot superclass name" elif not subclass_info: if mkfunc[0] in ("no_kwargs", "kwargs"): subclass_code = mkfunc[1].attr else: subclass_code = mkfunc[0].attr if node == "classdefdeco2": subclass_info = node else: subclass_info = node[0] if node == "classdefdeco2": self.write("\n") else: self.write("\n\n") self.currentclass = str(class_name) self.write(self.indent, "class ", self.currentclass) self.print_super_classes3(subclass_info) self.println(":") # class body self.indent_more() self.build_class(subclass_code) self.indent_less() self.currentclass = cclass if len(self.param_stack) > 1: self.write("\n\n") else: self.write("\n\n\n") self.prune()