def get_fun_info(self, fun_name, swig_generated_param_names): fun_info = self.collected_info["funcs"].get(fun_name) if not fun_info: # def get_all_functions(xml_tree, name=None): fnodes = doxygen_utils.get_toplevel_functions(self.xml_tree, name=fun_name) nfnodes = len(fnodes) if nfnodes > 0: if nfnodes > 1: print("Warning: more than 1 function doc found for '%s'; picking first" % fun_name) fd = fun_doc_t() fd.traverse(fnodes[0], swig_generated_param_names) if fd.is_valid(): fun_info = [] fd.append_lines(fun_info) return fun_info
parser.add_argument("-b", "--bc695", default=False, action="store_true") parser.add_argument("-x", "--xml-doc-directory", required=True) args = parser.parse_args() this_dir, _ = os.path.split(__file__) sys.path.append(this_dir) import doxygen_utils typemaps = [] # generate typemaps that will have to be injected for additional checks xml_tree = doxygen_utils.load_xml_for_module(args.xml_doc_directory, args.module, or_dummy=False) if xml_tree is not None: all_functions = doxygen_utils.get_toplevel_functions(xml_tree) for fun_node in all_functions: fun_name = doxygen_utils.get_single_child_element_text_contents( fun_node, "name") params = [] def reg_param(*args): params.append(args) doxygen_utils.for_each_param(fun_node, reg_param) def relevant_and_non_null(ptyp, desc): if ptyp.strip().startswith("qstring"): return False return (desc or "").lower().find("not be null") > -1
parser.add_argument("-l", "--lifecycle-aware", default=False, action="store_true") parser.add_argument("-v", "--verbose", default=False, action="store_true") parser.add_argument("-b", "--bc695", default=False, action="store_true") parser.add_argument("-x", "--xml-doc-directory", required=True) args = parser.parse_args() this_dir, _ = os.path.split(__file__) sys.path.append(this_dir) import doxygen_utils typemaps = [] # generate typemaps that will have to be injected for additional checks xml_tree = doxygen_utils.load_xml_for_module(args.xml_doc_directory, args.module, or_dummy=False) if xml_tree is not None: all_functions = doxygen_utils.get_toplevel_functions(xml_tree) for fun_node in all_functions: fun_name = doxygen_utils.get_single_child_element_text_contents(fun_node, "name") params = [] def reg_param(*args): params.append(args) doxygen_utils.for_each_param(fun_node, reg_param) def relevant_and_non_null(ptyp, desc): if ptyp.strip().startswith("qstring"): return False return (desc or "").lower().find("not be null") > -1 for name, ptyp, desc in params: if relevant_and_non_null(ptyp, desc): # generate 'check' typemap signature = []
def generate_function_pydoc(self, class_name=None): out = [] line = self.copy(out) fun_name = get_fun_name(line) class_info = self.get_class_info(class_name) if class_name else None if args.debug_function: global selective_debug_status selective_debug_status = fun_name == args.debug_function #verb("generate_function_pydoc: fun_name: '%s'" % fun_name) line = self.copy(out) doc_start_line_idx = len(out) if line.find(DOCSTR_MARKER) > -1: # Opening docstring line; determine indentation level indent = get_indent_string(line) docstring_line_nr = 0 while True: line = self.next() if docstring_line_nr == 0: line = self.maybe_fix_swig_generated_docstring_prototype( fun_name, line) if line.find(DOCSTR_MARKER) > -1: # Closing docstring line pydoc_lines = out[doc_start_line_idx:] swig_generated_param_names = self.extract_swig_generated_param_names( fun_name, pydoc_lines) if class_name is None: pywraps_fi = self.collected_pywraps_pydoc["funcs"].get( fun_name) else: pywraps_fi = class_info["methods"].get( fun_name) if class_info else [] if pywraps_fi: # documentation coming from pywraps takes precedence. dbg("'pywraps/'-originating comment takes precedence (%s)" % str(pywraps_fi)) found = pywraps_fi if pydoc_lines: l0 = pydoc_lines[0].lstrip() if l0.startswith(fun_name): found = [l0] + found else: found = [] # no documentation coming from pywraps. # Merge SWiG-generated documentation, and the # SDK-provided bits generated_fi = generated_func_info_t(pydoc_lines) if generated_fi.original_comment: dbg("SWiG-generated comment found (%s)" % str(pydoc_lines)) found = pydoc_lines else: sdk_fi = SDK_func_info_t() fnodes = [] if class_name is None: fnodes = doxygen_utils.get_toplevel_functions( self.xml_tree, name=fun_name) else: if class_name.endswith("_Hooks"): enums = hooks_utils.get_hooks_enumerators( self.xml_dir, class_name) for enum in enums: if enum["name"] == fun_name: sdk_fi.import_from_hooks_enumerator( enum, swig_generated_param_names) else: refid, udt_xml_tree = doxygen_utils.load_xml_for_udt( self.xml_dir, self.xml_tree, udt_name=class_name) if udt_xml_tree: fnodes = doxygen_utils.get_udt_methods( udt_xml_tree, refid, name=fun_name) for fnode in fnodes: sdk_fi.traverse(fnode, swig_generated_param_names) if sdk_fi.brief: found.extend(sdk_fi.brief) found.append("") if sdk_fi.detailed: found.extend(sdk_fi.detailed) found.append("") # We'll look in all SDK signatures (i.e., we don't # do proper signature matching) and patch all params # in all generated signatures information. Hopefully # this will be good enough. for sdk_match in sdk_fi.matches: for p in sdk_match.params: dbg("Handling param '%s'" % p) if p.name: pline = "@param %s" % p.name subsequent_indent = len(pline) + 2 if p.desc: pline = "%s: %s" % (pline, p.desc) if p.ptyp: pline = "%s (C++: %s)" % (pline, p.ptyp) for sig in generated_fi.signatures: sig.replace_param( p.original_name, p.name, pline, subsequent_indent) if sdk_match.returns: rline = "@return: %s" % sdk_match.returns.desc for sig in generated_fi.signatures: sig.append_return( rline, len("@return: ")) if sdk_match.retvals: for retval_value, retval_desc in sdk_match.retvals: rvline_pfx = "@retval: %s - " % retval_value rvline = "%s%s" % (rvline_pfx, retval_desc) for sig in generated_fi.signatures: sig.append_retval( rvline, len(rvline_pfx)) # Append the (modified) signatures for sig in generated_fi.signatures: add_lines_block(found, sig.get_lines()) found = doxygen_utils.remove_empty_header_or_footer_lines( found) if found: verb("fix_%s: found info for %s" % ("method" if class_name else "fun", fun_name)) while len(out) > doc_start_line_idx: out.pop() add_lines_block(out, apply_indent(found, indent)) # # apply possible additional patches # fun_patches = self.patches.get(fun_name, {}) example = fun_patches.get("+example", None) if example: ex_lines = list( map(lambda l: "Python> %s" % l, example.split("\n"))) out.extend( list( map(lambda l: indent + l, ["", "Example:"] + ex_lines))) repl_text = fun_patches.get("repl_text", None) if repl_text: from_text, to_text = repl_text for i in range(doc_start_line_idx, len(out)): out[i] = out[i].replace(from_text, to_text) out.append(line) break else: out.append(line) docstring_line_nr += 1 return out