diff --git a/docs/documentation_report.py b/docs/documentation_report.py new file mode 100644 index 0000000000..8dcd289754 --- /dev/null +++ b/docs/documentation_report.py @@ -0,0 +1,215 @@ +import ast +import os +from collections import defaultdict + +from bs4 import BeautifulSoup + + +class ParentNodeVisitor(ast.NodeVisitor): + def __init__(self): + self.parent = None + + def visit(self, node): + previous_parent = self.parent + self.parent = node + for child in ast.iter_child_nodes(node): + child.parent = node + self.visit(child) + self.parent = previous_parent + + +class DocAnalyzer: + def __init__(self, source_dir, docs_dir): + self.source_dir = source_dir + self.docs_dir = docs_dir + self.source_items = defaultdict(dict) + self.doc_items = set() + + def analyze_source(self): + for root, _, files in os.walk(self.source_dir): + for file in files: + if file.endswith(".py"): + module_name = os.path.splitext(file)[0] + with open(os.path.join(root, file)) as f: + tree = ast.parse(f.read()) + visitor = ParentNodeVisitor() + visitor.visit(tree) + for node in ast.walk(tree): + if isinstance(node, (ast.FunctionDef, ast.ClassDef)): + item_name = node.name + parent_class = None + if ( + isinstance(node, ast.FunctionDef) + and hasattr(node, "parent") + and isinstance(node.parent, ast.ClassDef) + ): + parent_class = node.parent.name + item_name = f"{parent_class}.{node.name}" + full_name = f"{module_name}.{item_name}" + self.source_items[module_name][full_name] = { + "type": ( + "function" + if isinstance(node, ast.FunctionDef) + else "class" + ), + "internal": node.name.startswith("_"), + "has_docstring": ast.get_docstring(node) + is not None, + "parent_class": parent_class, + } + + def analyze_docs(self): + for root, _, files in os.walk(self.docs_dir): + for file in files: + if file.endswith(".html"): + with open(os.path.join(root, file)) as f: + soup = BeautifulSoup(f, "html.parser") + + # Find all class definitions + for class_def in soup.find_all("dl", class_="py class"): + class_name = class_def.find( + "dt", class_="sig sig-object py" + )["id"] + self.doc_items.add(class_name) + + # Find all method definitions within the class + for method_def in class_def.find_all( + "dl", class_="py method" + ): + method_name = method_def.find( + "dt", class_="sig sig-object py" + )["id"] + self.doc_items.add(method_name) + + # Find all function definitions + for func_def in soup.find_all("dl", class_="py function"): + func_name = func_def.find("dt", class_="sig sig-object py")[ + "id" + ] + self.doc_items.add(func_name) + + # Find all property definitions + for prop_def in soup.find_all("dl", class_="py property"): + prop_name = prop_def.find("dt", class_="sig sig-object py")[ + "id" + ] + self.doc_items.add(prop_name) + + def generate_html_report(self): + html = """ + +
+ + + +Name | +Type | +Has Docstring | +In Sphinx | +
---|