def make_doc_function(node): """ Makes the doc of the node node""" # first case : it is a dict function # FIXME : to be improved, what do we want ? if util.use_parameter_class(node): member_list = CL.get_members(util.get_decl_param_class(node), True) member_list2 = treat_member_list(member_list) h = ['Parameter Name','Type','Default', 'Documentation'] l = [(m.spelling,m.ctype, m.initializer.replace("res.",""), m.doc) for m in member_list2] table = make_table(h, l) doc = doc + '\n' + table return doc # General case p = ProcessedDoc(node) # general treatment and analysis, common with cpp2rst doc = "%s\n\n%s\n"%(p.brief_doc, p.doc) params = p.elements['params'] # parameters of the function if params: doc += "Parameters\n----------\n" for p in params: name, comment = (p + ' ').split(' ',1) doc += "%s \n%s\n"%(name, decal(comment)) if p.elements['return']: _type = '' # FIXME : deduce the type ? doc += "Returns\n-------\n%s\n%s"(_type, decal(comment)) return doc
def generate_desc_file(self, output_filename, verbose=True): """ Makes the desc file""" # First treat the parameter class if any (classes passed by dictionnary that MUST be converted) param_cls_list = list(self.get_all_param_classes()) # Precompute self.all_enums = list(self.all_enums_gen()) self.all_classes = list(self.all_classes_gen()) self.all_functions = list(self.all_functions_gen()) self.param_cls_list = param_cls_list # checks for c in param_cls_list: for m in CL.get_members(c, True): assert CL.is_public( m ), "Parameter class : all members must be public. %s::%s is not" % ( c.spelling, m.spelling) # analyse the modules and converters that need to be added print "Analysing dependencies" types_being_wrapped_or_converted = param_cls_list + self.all_classes + self.all_enums import_list, converters_list = self.DE( self.get_all_params_ret_type(param_cls_list), types_being_wrapped_or_converted) # Reporting if self.all_classes: print "Wrapping classes:" for c in self.all_classes: print " ", c.spelling if self.all_enums: print "Wrapping enums:" for c in self.all_enums: print " ", c.spelling if self.all_functions: print "Wrapping functions:" for c in self.all_functions: print " ", c.spelling if param_cls_list: print "Generating converters for :" for c in param_cls_list: print " ", c.spelling # Render mako print "Generating " + output_filename tpl = Template(filename=util.script_path() + '/mako/desc.py', strict_undefined=True) rendered = tpl.render(W=self, CL=CL, doc=doc, util=util, import_list=import_list, converters_list=converters_list, using_list=list(self.namespaces) + list(self.namespace_to_factor)) open(output_filename, "w").write(util.clean_end_and_while_char(rendered))
def make_doc(node): """ process doc of node""" doc = process_doc(node.raw_comment) if util.use_parameter_class(node): doc = doc + '\n' + doc_format_param( CL.get_members(util.get_decl_param_class(node), True)) return replace_latex(replace_cpp_keywords_by_py_keywords(doc))
def generate_desc_file(self, output_filename, verbose = True): """ Makes the desc file""" # First treat the parameter class if any (classes passed by dictionnary that MUST be converted) param_cls_list = list(self.get_all_param_classes()) for c in param_cls_list : open('parameters_%s.rst'%c.spelling, 'w').write(doc.doc_param_dict_format(CL.get_members(c, True))) # Precompute self.all_enums = list(self.all_enums_gen()) self.all_classes = list(self.all_classes_gen()) self.all_functions = list(self.all_functions_gen()) self.param_cls_list = param_cls_list # checks for c in param_cls_list: for m in CL.get_members(c, True): assert CL.is_public(m), "Parameter class : all members must be public. %s::%s is not"%(c.spelling, m.spelling) # analyse the modules and converters that need to be added print "Analysing dependencies" types_being_wrapped_or_converted = param_cls_list + self.all_classes + self.all_enums import_list, converters_list = self.DE(self.get_all_params_ret_type(param_cls_list), types_being_wrapped_or_converted) if any(map(self.has_hdf5_scheme, self.all_classes)): converters_list.append("triqs/cpp2py_converters/h5.hpp") # Reporting if self.all_classes: print "Wrapping classes:" for c in self.all_classes: print " ", c.spelling if self.all_enums: print "Wrapping enums:" for c in self.all_enums: print " ", c.spelling if self.all_functions: print "Wrapping functions:" for c in self.all_functions: print " ", c.spelling if param_cls_list: print "Generating converters for :" for c in param_cls_list: print " ", c.spelling # Render mako print "Generating " + output_filename tpl = Template(filename= util.script_path() + '/mako/desc.py', strict_undefined = True) rendered = tpl.render(W = self, CL = CL, doc = doc, util = util, import_list = import_list, converters_list = converters_list, using_list = list(self.namespaces) + list(self.namespace_to_factor)) open(output_filename, "w").write(util.clean_end_and_while_char(rendered))
def get_all_params_ret_type(self, param_cls_list): """Yields every parameters and return type of every methods and functions""" for f in self.all_functions_gen(): yield getattr(f, 'result_type', None) for p in CL.get_params(f): yield p.type for x in itertools.chain(param_cls_list, self.all_classes_gen()): for m in CL.get_members(x, False): # False : no inherited yield m.type for m in itertools.chain(CL.get_constructors(x), CL.get_methods(x)): yield getattr(m, 'result_type', None) for p in CL.get_params(m): yield p.type
def get_all_params_ret_type(self, param_cls_list): """Yields every parameters and return type of every methods and functions""" for f in self.all_functions_gen(): yield getattr(f, 'result_type', None) for p in CL.get_params(f) : yield p.type for x in itertools.chain(param_cls_list, self.all_classes_gen()): for m in CL.get_members(x, False): # False : no inherited yield m.type for m in itertools.chain(CL.get_constructors(x), CL.get_methods(x)): # A minimal filter, do not reuse self.keep_fnt here, because the namespace is N1::N2:...::ClassName if CL.is_template(m) or ("ignore_in_python" in CL.get_annotations(m)): continue yield getattr(m, 'result_type', None) for p in CL.get_params(m) : yield p.type
def make_h5(self, cls): print CL.get_annotations(cls) """cls : AST node for a class. Returns the h5_read/write code""" # FIXME : treat template ! h5w = '\n'.join('h5_write(gr, "%s", %s);'%(x.spelling, x.spelling) for x in CL.get_members(cls, False)) h5 = """ void h5_write(triqs::h5::group h5group, std::string const & subgroup_name, {cls_name} const &x) {{ auto gr = h5group.create_group(subgroup_name); {h5w} }} void h5_read(triqs::h5::group h5group, std::string const & subgroup_name,{cls_name} &x) {{ auto gr = h5group.open_group(subgroup_name); {h5r} }} """.format(cls_name = cls.spelling, h5w = h5w, h5r = h5w.replace('write', 'read')) ns = ':'.join(CL.get_namespace_list(cls)) r = "namespace %s {{\n {H5} \n}}"%ns if ns else '' "{H5}" return r.format(H5 = h5)
def get_all_params_ret_type(self, param_cls_list): """Yields every parameters and return type of every methods and functions""" for f in self.all_functions_gen(): yield getattr(f, 'result_type', None) for p in CL.get_params(f): yield p.type for x in itertools.chain(param_cls_list, self.all_classes_gen()): for m in CL.get_members(x, False): # False : no inherited yield m.type for m in itertools.chain(CL.get_constructors(x), CL.get_methods(x)): # A minimal filter, do not reuse self.keep_fnt here, because the namespace is N1::N2:...::ClassName if CL.is_template(m) or ("ignore_in_python" in CL.get_annotations(m)): continue yield getattr(m, 'result_type', None) for p in CL.get_params(m): yield p.type
def make_doc_function(node): """ Makes the doc of the node node""" pdoc = ProcessedDoc( node) # general treatment and analysis, common with cpp2rst # first case : it is a dict function # FIXME : to be improved, what do we want ? if util.use_parameter_class(node): member_list = CL.get_members(util.get_decl_param_class(node), True) table = doc_param_dict_format(member_list) return "%s\n\n%s\n\n%s\n" % (pdoc.brief_doc, pdoc.doc, table) # member_list2 = treat_member_list(member_list) # h = ['Parameter Name','Type','Default', 'Documentation'] # l = [(m.spelling,m.ctype, m.initializer.replace("res.",""), m.doc) for m in member_list2] # table = make_table(h, *l) # doc = clean_doc_string(node.raw_comment) + '\n' + table # return doc # General case doc = "\n%s\n%s" % (pdoc.brief_doc, pdoc.doc) doc = doc.strip() + "\n" params = pdoc.elements.pop('param', None) # parameters of the function if params: doc += "\nParameters\n----------\n" for p in params: name, comment = (p + ' ').split(' ', 1) doc += "%s \n%s\n\n" % (name, decal(comment)) ret = pdoc.elements.pop('return', None) if ret: _type = '' # FIXME : deduce the type ? doc += "Returns\n-------\nout %s\n%s\n\n" % (_type, decal(ret)) return doc.strip()
def make_doc_function(node): """ Makes the doc of the node node""" pdoc = ProcessedDoc(node) # general treatment and analysis, common with cpp2rst # first case : it is a dict function # FIXME : to be improved, what do we want ? if util.use_parameter_class(node): member_list = CL.get_members(util.get_decl_param_class(node), True) table = doc_param_dict_format(member_list) return "%s\n\n%s\n\n%s\n"%( pdoc.brief_doc, pdoc.doc, table) # member_list2 = treat_member_list(member_list) # h = ['Parameter Name','Type','Default', 'Documentation'] # l = [(m.spelling,m.ctype, m.initializer.replace("res.",""), m.doc) for m in member_list2] # table = make_table(h, *l) # doc = clean_doc_string(node.raw_comment) + '\n' + table # return doc # General case doc = "\n%s\n%s"%(pdoc.brief_doc, pdoc.doc) doc = doc.strip() + "\n" params = pdoc.elements.pop('param', None) # parameters of the function if params: doc += "\nParameters\n----------\n" for p in params: name, comment = (p + ' ').split(' ',1) doc += "%s \n%s\n\n"%(name, decal(comment)) ret = pdoc.elements.pop('return', None) if ret: _type = '' # FIXME : deduce the type ? doc += "Returns\n-------\nout %s\n%s\n\n"%(_type, decal(ret)) return doc.strip()
def render_cls(cls, all_methods, all_friend_functions): """ Generate the rst page for a class * cls : node for the classf_name : name of the function * doc_methods : ?? """ cls_doc = cls.processed_doc doc_elem = cls_doc.elements R = rst_start # include incl = doc_elem.pop('include', '') # class header cls_name_fully_qualified = CL.fully_qualified_name(cls) R += """ .. _{cls.spelling}: {cls_name_fully_qualified} {separator} Defined in header <*{incl}*> .. code-block:: c {templ_synop}class {cls.spelling}; {cls_doc.brief_doc} {cls_doc.doc} """.format(cls=cls, incl=incl.strip(), separator='=' * (len(cls_name_fully_qualified)), templ_synop=make_synopsis_template_decl(cls), cls_doc=cls_doc, cls_name_fully_qualified=cls_name_fully_qualified) # R += cls_doc.doc if 'tparam' in doc_elem: R += render_list(doc_elem.pop('tparam'), 'Template parameters') if 'note' in doc_elem: R += render_note(doc_elem.pop('note')) if 'warning' in doc_elem: R += render_warning(doc_elem.pop('warning')) if 'figure' in doc_elem: R += render_fig(doc_elem.pop('figure')) # Members c_members = list(CL.get_members(cls, True)) if len(c_members) > 0: R += make_header('Public members') R += render_table([(t.spelling, t.type.spelling, replace_latex(clean_doc_string(t.raw_comment)) if t.raw_comment else '') for t in c_members]) # Using : TODO : KEEP THIS ? c_usings = list(CL.get_usings(cls)) for t in c_usings: t.my_tag = t.spelling if len(c_usings) > 0: R += make_header('Member types') R += render_table([(t.spelling, replace_latex(clean_doc_string(t.raw_comment)) if t.raw_comment else '') for t in c_usings]) # A table for all member functions and all friend functions def group_of_overload(f_list): s = set(f.processed_doc.elements['group'] for f in f_list if 'group' in f.processed_doc.elements) assert len(s) < 2, "Can not have different group for various overload" return s.pop if s else '' def make_func_list(all_f, header_name): R = '' if len(all_f) > 0: R += make_header(header_name) R += render_table([ (":ref:`%s <%s_%s>`" % (name, escape_lg(cls.spelling), escape_lg(name)), f_list[0].processed_doc.brief_doc) for (name, f_list) in all_f.items() ]) R += toctree_hidden for f_name in all_f: R += " {cls.spelling}/{f_name}\n".format(cls=cls, f_name=f_name) return R R += make_func_list(all_methods, 'Member functions') R += make_func_list(all_friend_functions, 'Non Member functions') # Example if 'example' in doc_elem: R += render_example(doc_elem.pop('example')) return R
def analyse_one_ns(self, namespace): print "*** Namespace %s ***" % namespace # ---------------------- # Filters # ---------------------- def keep_ns(n): """Given a namespace node n, shall we keep it ?""" ns = CL.fully_qualified(n) return ns in namespace def keep_cls(c): """ Given a class node, shall we keep it ? Reject if no raw_comment. Keeps if its namespace is EXACTLY in self.namespaces e.g. A::B::cls will be kept iif A::B is in self.namespaces, not it A is. The filter to keep a class/struct or an enum : it must have a raw comment if we a namespace list, it must be in it. if target_file_only it has to be in the file given to c++2py """ if c.spelling.startswith('_'): return False # FIXME : Commented for debug if not c.raw_comment: return False if namespace: qualified_ns = CL.get_namespace(c) if qualified_ns != namespace: return False return (c.location.file.name == self.filename) if self.target_file_only else True def keep_fnt(f): #print "RAW", f.spelling, f.raw_comment if not f.raw_comment: return False if f.spelling.startswith('operator') or f.spelling in [ 'begin', 'end' ]: return False return keep_cls(f) def keep_using(c): #if not c.raw_comment : return False if namespace: qualified_ns = CL.get_namespace(c) if qualified_ns != namespace: return False return (c.location.file.name == self.filename) if self.target_file_only else True # ---------------------- # A list of AST nodes for classes classes = CL.get_classes(self.root, keep_cls, traverse_namespaces=True, keep_ns=keep_ns) classes = list( classes) # make a list to avoid exhaustion of the generator D = OrderedDict() for cls in classes: cls.namespace = CL.get_namespace(cls) cls.name = CL.get_name_with_template_specialization( cls) or cls.spelling cls.fully_qualified_name = '::'.join([cls.namespace, cls.name]) cls.name_for_label = synopsis.make_label(cls.fully_qualified_name) D[cls.fully_qualified_name] = cls # print "CLASS", cls.name # print "CLASS", cls.fully_qualified_name # print "CLASS", cls.name_for_label # print "CLASS", "----------------------" print " ... class : %s" % cls.fully_qualified_name, cls.location #assert ',' not in cls.fully_qualified_name, "Not implemented" # process the doc of the class and add it to the node cls.processed_doc = ProcessedDoc(cls) # all methods and constructors # we build a OrderedDict of the constructors (first) and the methods, in order of declaration constructors = list(CL.get_constructors(cls)) for f in constructors: f.is_constructor = True # tag them for later use methods = OrderedDict() if constructors: methods['constructor'] = constructors methods.update( self.regroup_func_by_names(CL.get_methods( cls, True))) # True : with inherited #methods.update(self.regroup_func_by_names(CL.get_methods(cls, True, keep = keep_fnt))) # True : with inherited # all non member functions friend_functions = self.regroup_func_by_names( CL.get_friend_functions(cls)) #friend_functions = self.regroup_func_by_names(CL.get_friend_functions(cls, keep = keep_fnt)) # Analyse the doc string for all methods and functions, and store the result in the node itself for (n, f_list) in (methods.items() + friend_functions.items()): for f in f_list: f.processed_doc = ProcessedDoc(f) # attach to the node cls.methods, cls.friend_functions = methods, friend_functions # members cls.members = list(CL.get_members(cls, True)) # using cls.usings = list(CL.get_usings(cls)) # , keep_using)) # Eliminate doublons, like forward declarations classes = D.values() # A list of AST nodes for the methods and functions functions = CL.get_functions(self.root, keep_fnt, traverse_namespaces=True, keep_ns=keep_ns) functions = list( functions) # make a to avoid exhaustion of the generator # Analyse the doc strings for f in functions: f.processed_doc = ProcessedDoc(f) # Find the using of this namespace, and make the list unique based on the fully_qualified_name usings = list( CL.get_usings(self.root, keep_using, traverse_namespaces=True, keep_ns=keep_ns)) D = OrderedDict() for c in usings: c.namespace = CL.get_namespace(c) c.fully_qualified_name = '::'.join([c.namespace, c.spelling]) D[c.fully_qualified_name] = c usings = D.values() return classes, functions, usings
def analyse_one_ns(self, namespace): print "*** Namespace %s ***"%namespace # ---------------------- # Filters # ---------------------- def keep_ns(n): """Given a namespace node n, shall we keep it ?""" ns = CL.fully_qualified(n) return ns in namespace def keep_cls(c): """ Given a class node, shall we keep it ? Reject if no raw_comment. Keeps if its namespace is EXACTLY in self.namespaces e.g. A::B::cls will be kept iif A::B is in self.namespaces, not it A is. The filter to keep a class/struct or an enum : it must have a raw comment if we a namespace list, it must be in it. if target_file_only it has to be in the file given to c++2py """ if c.spelling.startswith('_') : return False # FIXME : Commented for debug if not c.raw_comment : return False if namespace: qualified_ns = CL.get_namespace(c) if qualified_ns != namespace : return False return (c.location.file.name == self.filename) if self.target_file_only else True def keep_fnt(f): #print "RAW", f.spelling, f.raw_comment if not f.raw_comment : return False if f.spelling.startswith('operator') or f.spelling in ['begin','end'] : return False return keep_cls(f) def keep_using(c): #if not c.raw_comment : return False if namespace: qualified_ns = CL.get_namespace(c) if qualified_ns != namespace : return False return (c.location.file.name == self.filename) if self.target_file_only else True # ---------------------- # A list of AST nodes for classes classes = CL.get_classes(self.root, keep_cls, traverse_namespaces = True, keep_ns = keep_ns) classes = list(classes) # make a list to avoid exhaustion of the generator D = OrderedDict() for cls in classes: cls.namespace = CL.get_namespace(cls) cls.name = CL.get_name_with_template_specialization(cls) or cls.spelling cls.fully_qualified_name = '::'.join([cls.namespace, cls.name]) cls.name_for_label = synopsis.make_label(cls.fully_qualified_name) D[cls.fully_qualified_name] = cls # print "CLASS", cls.name # print "CLASS", cls.fully_qualified_name # print "CLASS", cls.name_for_label # print "CLASS", "----------------------" print " ... class : %s"%cls.fully_qualified_name, cls.location #assert ',' not in cls.fully_qualified_name, "Not implemented" # process the doc of the class and add it to the node cls.processed_doc = ProcessedDoc(cls) # all methods and constructors # we build a OrderedDict of the constructors (first) and the methods, in order of declaration constructors = list(CL.get_constructors(cls)) for f in constructors : f.is_constructor = True # tag them for later use methods = OrderedDict() if constructors: methods['constructor'] = constructors methods.update(self.regroup_func_by_names(CL.get_methods(cls, True))) # True : with inherited #methods.update(self.regroup_func_by_names(CL.get_methods(cls, True, keep = keep_fnt))) # True : with inherited # all non member functions friend_functions = self.regroup_func_by_names(CL.get_friend_functions(cls)) #friend_functions = self.regroup_func_by_names(CL.get_friend_functions(cls, keep = keep_fnt)) # Analyse the doc string for all methods and functions, and store the result in the node itself for (n,f_list) in (methods.items() + friend_functions.items()): for f in f_list: f.processed_doc = ProcessedDoc(f) # attach to the node cls.methods, cls.friend_functions = methods, friend_functions # members cls.members = list(CL.get_members(cls, True)) # using cls.usings = list(CL.get_usings(cls)) # , keep_using)) # Eliminate doublons, like forward declarations classes = D.values() # A list of AST nodes for the methods and functions functions = CL.get_functions(self.root, keep_fnt, traverse_namespaces = True, keep_ns = keep_ns) functions = list(functions) # make a to avoid exhaustion of the generator # Analyse the doc strings for f in functions: f.processed_doc = ProcessedDoc(f) # Find the using of this namespace, and make the list unique based on the fully_qualified_name usings = list(CL.get_usings(self.root, keep_using, traverse_namespaces = True, keep_ns = keep_ns)) D = OrderedDict() for c in usings: c.namespace = CL.get_namespace(c) c.fully_qualified_name = '::'.join([c.namespace, c.spelling]) D[c.fully_qualified_name] = c usings = D.values() return classes, functions, usings
def render_cls(cls, all_m, all_friend_functions, doc_methods, doc_class, cls_doc): doc_elem = doc_class.elements R = rst_start # include incl = doc_elem['include'] if incl: R += """ .. code-block:: c #include <{incl}> """.format(incl=incl.strip()) # class header R += """ .. _{cls.spelling}: {cls.spelling} {separator} {cls_doc.brief_doc} {cls_doc.processed_doc} **Synopsis**: .. code-block:: c {templ_synop}class {cls.spelling}; """.format(cls=cls, separator='=' * (len(cls.spelling) + 2), templ_synop=make_synopsis_template_decl(cls), cls_doc=cls_doc) # doc, note, warning, figure R += replace_latex(doc_class.processed_doc) R += replace_latex(render_note('note', doc_elem)) R += replace_latex(render_note('warning', doc_elem)) R += render_fig(doc_elem) R += render_list(doc_elem['tparam'], 'Template parameters') c_members = list(CL.get_members(cls, True)) if len(c_members) > 0: R += head('Public members') R += make_table( ['Member', 'Type', 'Comment'], [(t.spelling, t.type.spelling, replace_latex(t.raw_comment) if t.raw_comment else '') for t in c_members]) c_usings = list(CL.get_usings(cls)) if len(c_usings) > 0: R += head('Member types') R += make_table(['Member type', 'Comment'], [ (t.spelling, replace_latex(t.raw_comment) if t.raw_comment else '') for t in c_usings ]) if len(all_m) > 0: R += head('Member functions') R += make_table(['Member function', 'Comment'], [(":ref:`%s <%s_%s>`" % (name, escape_lg(cls.spelling), escape_lg(name)), replace_latex(doc_methods[name][0].brief_doc)) for name in all_m]) R += toctree_hidden for m_name in all_m: R += " {cls.spelling}/{m_name}\n".format(cls=cls, m_name=m_name) if len(all_friend_functions) > 0: R += head('Non Member functions') R += make_table(['Non member function', 'Comment'], [(":ref:`%s <%s_%s>`" % (name, escape_lg(cls.spelling), escape_lg(name)), replace_latex(doc_methods[name][0].brief_doc)) for name in all_friend_functions]) R += toctree_hidden for f_name in all_friend_functions: R += " {cls.spelling}/{f_name}\n".format(cls=cls, f_name=f_name) code, d1, d2, s, e = prepare_example(cls.spelling, 4) if code is not None: R += """ Example --------- {d1} .. triqs_example:: linenos:{s},{e} {code} {d2} """.format(d1=d1, d2=d2, s=s, e=e, code=code) return R