def __init__(self, node): raw_doc = node.raw_comment if not raw_doc: raw_doc = "\n\n" # default value # Clean *, &&, /// and co. doc = clean_doc_string(raw_doc.strip()) # split : the first line is brief, and the rest doc = replace_latex(doc) if '$' in doc: print "FAILED to process the latex for node %s" % CL.fully_qualified( node) print doc doc2 = doc.strip().split( '@', 1)[0] # Get rid of everything after the first @ spl = doc2.strip().split('\n', 1) self.brief_doc, self.doc = spl[0], (spl[1] if len(spl) > 1 else '') assert '@' not in self.doc, "ouch!" # Extract the @XXXX elements with a regex @XXXX YYYY (YYYY can be multiline). d = dict((key, []) for key in self.fields_with_multiple_entry) regex = r'@(\w+)\s*([^@]*)' for m in re.finditer(regex, doc, re.DOTALL): key, val = m.group(1), replace_latex(m.group(2)).strip() if key not in self.fields_allowed_in_docs: print "Field %s is not recognized" % key if key in self.fields_with_multiple_entry: d[key].append(val) else: d[key] = val self.elements = d
def make_signature_for_desc(self, f, is_constructor=False, is_free_function=False): """Given a node of a function/methods, it makes the signature for desc file""" # first format the arguments def cls(t): tname = util.decay(t) tname = tname.replace(' ', '') for ns in self.namespace_to_factor: tname = re.sub(ns + '::', '', tname) return tname if util.use_parameter_class(f): r = '**%s' % cls(CL.get_params(f).next().type.spelling) else: plist = [(cls(p.type.spelling), p.spelling, CL.get_param_default_value(p)) for p in CL.get_params(f)] r = ', '.join("%s %s" % (t, n) + (" = %s" % d.replace('"', '\\"') if d else "") for t, n, d in plist) if is_constructor: return "(%s)" % r else: f_name = f.spelling if not is_free_function else CL.fully_qualified( f) return ("%s %s (%s)" % (cls(f.result_type.spelling), f_name, r)).strip()
def __init__(self, node): raw_doc = node.raw_comment if not raw_doc : raw_doc = "\n\n" # default value # Clean *, &&, /// and co. doc = clean_doc_string(raw_doc.strip()) # split : the first line is brief, and the rest doc = replace_latex(doc) if '$' in doc : print "FAILED to process the latex for node %s"%CL.fully_qualified(node) print doc doc2 = doc.strip().split('@',1)[0] # Get rid of everything after the first @ spl = doc2.strip().split('\n',1) self.brief_doc, self.doc = spl[0], (spl[1] if len(spl)>1 else '') assert '@' not in self.doc, "ouch!" # Extract the @XXXX elements with a regex @XXXX YYYY (YYYY can be multiline). d = dict( (key, []) for key in self.fields_with_multiple_entry) regex = r'@(\w+)\s*([^@]*)' for m in re.finditer(regex, doc, re.DOTALL): key, val = m.group(1), replace_latex(m.group(2)).strip() if key not in self.fields_allowed_in_docs: print "Field %s is not recognized"%key if key in self.fields_with_multiple_entry: d[key].append(val) else: d[key] = val self.elements = d
def keep_cls(self, c): """Keeps the class 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. """ if not c.raw_comment: return False if len(self.namespaces) > 0: ns = CL.fully_qualified(c.referenced).rsplit('::', 1)[0] return ns in self.namespaces return True
def __init__(self, node): raw_doc = node.raw_comment if not raw_doc : raw_doc = "\n\n" # default value # Clean *, &&, /// and co. doc = clean_doc_string(raw_doc).rstrip() # do NOT remove leading space # split : the first line is brief, and the rest doc = replace_latex(doc) if '$' in doc : print("FAILED to process the latex for node %s"%CL.fully_qualified(node)) print(doc) doc2 = doc.split('@',1)[0] # Get rid of everything after the first @ self.doc = doc2 assert '@' not in self.doc, "Internal Error in doc processing !" # Process the main part of the doc self.doc = strip_left_spaces(self.doc) # Extract the @XXXX elements with a regex @XXXX YYYY (YYYY can be multiline). d = dict( (key, []) for key in self.fields_with_multiple_entry) regex = r'@(\w+)\s(\s*[^@]*)' for m in re.finditer(regex, doc, re.DOTALL): key, val = m.group(1), replace_latex(m.group(2)).rstrip() if key not in self.fields_allowed_in_docs: print("Field %s is not recognized"%key) if key in self.fields_with_multiple_entry: d[key].append(val) else: d[key] = val self.elements = d if 'brief' not in d : d['brief']='' # if 'return' in d : print d['return'] # print doc # print raw_doc # print d['param'] # Final adjustement if 'brief' not in d : d['brief']='' if 'example' not in d : # take the default filename= "%s.cpp"%(CL.fully_qualified_name(node).replace("::",'/')) filename = os.path.join(global_vars.examples_root, filename) if os.path.exists(filename): d['example'] = filename if 'include' not in d : ns = CL.get_namespace_list(node) d['include'] = '/'.join(ns) + '.hpp'
def keep_cls(self, c): """ The filter to keep a class/struct or an enum : if we a namespace list, it must be in it. if we have an explicit self.classes : c must be into it if target_file_only it has to be in the file given to c++2py """ if CL.is_template(c) or ("ignore_in_python" in CL.get_annotations(c)): return False if self.namespaces: qualified_ns = CL.get_namespace(c) if not any((x in qualified_ns) for x in self.namespaces) : return False if self.classes: return c.spelling in self.classes or CL.fully_qualified(c) in self.classes return (c.location.file.name == self.filename) if self.target_file_only else True
def keep_cls(self, c): """ The filter to keep a class/struct or an enum : if we a namespace list, it must be in it. if we have an explicit self.classes : c must be into it else it has to be in the file given to c++2py """ if CL.is_template(c) or ("ignore_in_python" in CL.get_annotations(c)): return False if self.namespaces: ns = CL.get_namespace(c) if not any((x in ns) for x in self.namespaces): return False if self.classes: return c.spelling in self.classes or CL.fully_qualified( c) in self.classes return c.location.file.name == self.filename
def make_signature_for_desc(self, f, is_constructor = False, is_free_function = False): """Given a node of a function/methods, it makes the signature for desc file""" # first format the arguments def cls(t) : tname = util.decay(t) tname = tname.replace(' ','') for ns in self.namespace_to_factor : tname = re.sub(ns + '::','',tname) return tname if util.use_parameter_class(f) : r = '**%s'%cls(CL.get_params(f).next().type.spelling) else: plist = [ (cls(p.type.spelling), p.spelling, CL.get_param_default_value(p)) for p in CL.get_params(f)] r = ', '.join("%s %s"%(t, n) + (" = %s"%d.replace('"','\\"') if d else "") for t, n, d in plist ) if is_constructor: return "(%s)"%r else : f_name = f.spelling if not is_free_function else CL.fully_qualified(f) return ("%s %s (%s)"%(cls(f.result_type.spelling), f_name, r)).strip()
def keep_ns(n): """Given a namespace node n, shall we keep it ?""" ns = CL.fully_qualified(n) return ns in namespace
def keep_ns(self, n): ns = CL.fully_qualified(n) if 'std' in ns or 'boost' in ns or 'detail' in ns or 'impl' in ns: return False if len(self.namespaces) == 0: return True return any((ns in x) for x in self.namespaces)
def mkchdir_for_one_class(node): """c : AST node for a class A::B::C::clsname makes and cd into A/B/C """ mkchdir(*(CL.fully_qualified(node.referenced).split('::')[:-1]))
def run(self, output_directory): print "Generating the documentation ..." mkchdir(output_directory) classes = list(self.all_classes_gen()) # FIXME synopsis.class_list = classes synopsis.class_list_name = [n.spelling for n in classes] for c in classes: if not c.spelling.strip(): print "Skipping a class with an empty name !" continue print " ... class : " + c.spelling, CL.fully_qualified( c.referenced) # process the doc of the class cls_doc = self.process_doc_class(c) # all methods and constructors all_m = self.regroup_func_by_names(CL.get_methods( c, True)) # True : with inherited ? constructors = list(CL.get_constructors(c)) if constructors: all_m['constructor'] = constructors # all non member functions all_friend_functions = self.regroup_func_by_names( CL.get_friend_functions(c)) # process the doc doc_methods = dict( (n, [self.process_doc_function(f) for f in fs]) for (n, fs) in (all_m.items() + all_friend_functions.items())) # One directory for the class cur_dir = os.getcwd() mkchdir_for_one_class(c) # the file for the class r = render_cls(doc_class=self.process_doc_class(c), doc_methods=doc_methods, cls=c, all_m=all_m, all_friend_functions=all_friend_functions) safe_write(c.spelling, r) mkchdir(c.spelling) def render(mess, d): for f_name, f_overloads in all_m.items(): print " ...... %s %s" % (mess, f_name) r = render_fnt(doc_methods=doc_methods[f_name], parent_class=c, f_name=f_name, f_overloads=f_overloads) safe_write(f_name, r) render('method', all_m) render('non member function', all_friend_functions) os.chdir(cur_dir) all_functions = self.regroup_func_by_names(self.all_functions_gen()) docs = dict((n, [self.process_doc_function(f) for f in fs]) for (n, fs) in all_functions.items()) for f_name, f_overloads in all_functions.items(): print " ... function " + f_name cur_dir = os.getcwd() mkchdir_for_one_class(f_overloads[0]) print " ..... located: ", f_overloads[0].location.file.name r = render_fnt(doc_methods=docs[f_name], parent_class=None, f_name=f_name, f_overloads=f_overloads) safe_write(f_name, r) os.chdir(cur_dir) print "... done"
def keep_ns(self, n): ns = CL.fully_qualified(n) if any((x in ns) for x in self.namespaces_to_skip): return False return len(self.namespaces) == 0 or any( (ns in x) for x in self.namespaces)
def keep_ns(n): """Given a namespace node n, shall we keep it ?""" ns = CL.fully_qualified(n) return ns in namespace
def keep_ns(self, n): ns = CL.fully_qualified(n) if any((x in ns) for x in self.namespaces_to_skip) : return False return len(self.namespaces) == 0 or any((ns in x) for x in self.namespaces)