diff --git a/builder/builder-tools/generate_api_docs.py b/builder/builder-tools/generate_api_docs.py index d7a4fc7..a3d622a 100644 --- a/builder/builder-tools/generate_api_docs.py +++ b/builder/builder-tools/generate_api_docs.py @@ -9,19 +9,21 @@ sys.path.insert(0, os.path.realpath(os.path.join(current_dir, os.pardir, os.pard class DocsGenerator: def __init__(self, - links_raltive_path="", module_header="# Module {}", functions_header="## Module functions", class_header="## Class {}", - function_header="### {}" + function_header="### {}", + contents_table_header="# API documentation\n" + "> Please note, following documentation files were automatically generated from the source code\n" + "## Table of contents" ): - self.links_path = links_raltive_path self.module_header = module_header self.functions_header = functions_header self.class_header = class_header self.function_header = function_header + self.contents_table_header = contents_table_header - def get_full_markdown(self, module, links_path): + def _get_full_markdown(self, module, links_path): output = [self.module_header.format( "[{}]({})".format( module.__name__, @@ -33,12 +35,12 @@ class DocsGenerator: output.append(module.__doc__) output.append(self.functions_header) - output.extend(self.get_functions(module, links_path)) - output.extend(self.get_classes(module, links_path)) + output.extend(self._get_functions(module, links_path)) + output.extend(self._get_classes(module, links_path)) return output - def get_classes(self, item, links_path): + def _get_classes(self, item, links_path): output = list() for cls_name, cls in pydoc.inspect.getmembers(item, pydoc.inspect.isclass): if cls_name.startswith("_") or cls_name == "__class__": @@ -54,12 +56,12 @@ class DocsGenerator: )) ) output.append(pydoc.inspect.getdoc(cls) or '...') # Get the docstring - output.extend(self.get_functions(cls, links_path)) # Get the functions - output.extend(self.get_classes(cls, links_path)) # Recurse into any subclasses + output.extend(self._get_functions(cls, links_path)) # Get the functions + output.extend(self._get_classes(cls, links_path)) # Recurse into any subclasses output.append('\n') return output - def get_functions(self, item, links_path): + def _get_functions(self, item, links_path): output = [] for func_name, func in pydoc.inspect.getmembers(item, pydoc.inspect.isfunction): if func_name.startswith('_') and func_name != '__init__': @@ -83,23 +85,48 @@ class DocsGenerator: return output - def generate_docs(self, module_import_path, output_path): + @staticmethod + def _write_lines(path, lines): + with open(path, 'w') as f: + for line in lines: + f.write(line.replace("\n", os.linesep) + '\n') + + @staticmethod + def _get_relpath(path1: str, path2: str) -> str: + return os.path.sep.join( + os.path.relpath(path1, path2).split(os.path.sep)[1:] + ) + + def generate_doc(self, module_import_path: str, output_path: str) -> None: try: module = pydoc.safeimport(module_import_path) if module is None: logging.error("Module not found") - return + raise FileExistsError("Module not found") + except pydoc.ErrorDuringImport as e: logging.error(f"Error while trying to import {module_import_path}: {e}") + raise e else: + relpath = self._get_relpath(module.__file__, output_path) + docs = self._get_full_markdown(module, relpath.replace(os.path.sep, "/")) + self._write_lines(output_path, docs) + + def generate_docs(self, modules: list, output_dir: str, contents_name="SUMMARY") -> None: + contents_table = [self.contents_table_header] + contents_path = os.path.realpath(os.path.join(output_dir, f"{contents_name}.md")) + for module in modules: + name = module[module.rfind('.') + 1::] + path = os.path.realpath(os.path.join(output_dir, f"{name}.md")) + self.generate_doc(module, path) + relpath = os.path.sep.join( - os.path.relpath(module.__file__, output_path).split(os.path.sep)[1:] + os.path.relpath(path, contents_path).split(os.path.sep)[1:] ) - docs = self.get_full_markdown(module, relpath.replace(os.path.sep, "/")) - with open(output_path, 'w') as f: - for line in docs: - f.write(line.replace("\n", os.linesep) + '\n') + contents_table.append(f"* [{name}]({relpath})") + + self._write_lines(contents_path, contents_table) if __name__ == '__main__': @@ -108,7 +135,5 @@ if __name__ == '__main__': "drone.modules.client_core", ] gen = DocsGenerator() - for module in modules_list: - name = module[module.rfind('.') + 1::] - gen.generate_docs(module, os.path.realpath( - os.path.join(current_dir, os.pardir, os.pardir, "docs", "en", "api", f"{name}.md"))) + doc_path = os.path.realpath(os.path.join(current_dir, os.pardir, os.pardir, "docs", "en", "api")) + gen.generate_docs(modules_list, doc_path) diff --git a/docs/en/api/SUMMARY.md b/docs/en/api/SUMMARY.md new file mode 100644 index 0000000..53d0479 --- /dev/null +++ b/docs/en/api/SUMMARY.md @@ -0,0 +1,5 @@ +# API documentation +> Please note, following documentation files were automatically generated from the source code +## Table of contents +* [messaging](messaging.md) +* [client_core](client_core.md)