| |
|
|
| import os |
|
|
|
|
| def generate_api_docs(base_path, output_dir, package_name, exclude_list=None): |
| """ |
| Automatically generates .rst files for Sphinx API documentation. |
| |
| Args: |
| base_path (str): The root directory of the Python package (e.g., 'biomni'). |
| output_dir (str): The directory where the .rst files will be generated (e.g., 'source/api'). |
| package_name (str): The name of the Python package. |
| exclude_list (list): A list of paths (directories or files) to exclude from documentation. |
| Paths should be relative to the base_path. |
| """ |
| if exclude_list is None: |
| exclude_list = [] |
|
|
| if not os.path.exists(output_dir): |
| os.makedirs(output_dir) |
|
|
| |
| for root, dirs, files in os.walk(base_path): |
| |
| dirs[:] = [d for d in dirs if os.path.join(os.path.relpath(root, base_path), d) not in exclude_list] |
|
|
| for file in files: |
| file_path_relative = os.path.relpath(os.path.join(root, file), base_path) |
|
|
| |
| if file_path_relative in exclude_list: |
| print(f"Skipping excluded file: {file_path_relative}") |
| continue |
|
|
| if file.endswith(".py") and file != "__init__.py": |
| |
| rel_path = os.path.relpath(root, base_path) |
| module_name = f"{package_name}.{rel_path.replace(os.path.sep, '.')}.{os.path.splitext(file)[0]}" |
|
|
| |
| if module_name.startswith(f"{package_name}.{package_name}."): |
| module_name = f"{package_name}.{module_name[len(f'{package_name}.{package_name}.') :]}" |
|
|
| |
| output_path_dir = os.path.join(output_dir, rel_path) |
| if not os.path.exists(output_path_dir): |
| os.makedirs(output_path_dir) |
|
|
| |
| output_file = os.path.join(output_path_dir, f"{os.path.splitext(file)[0]}.rst") |
|
|
| |
| rst_content = f"""{module_name} |
| {"=" * len(module_name)} |
| |
| .. automodule:: {module_name} |
| :members: |
| :undoc-members: |
| :show-inheritance: |
| """ |
| |
| with open(output_file, "w", encoding="utf-8") as f: |
| f.write(rst_content) |
| print(f"Generated {output_file}") |
|
|
|
|
| def create_index_rst(output_dir, package_name): |
| """ |
| Creates or updates the main index file that lists all generated .rst files. |
| """ |
| output_dir = os.path.join(output_dir, "../") |
| index_path = os.path.join(output_dir, "index.rst") |
| rst_files = [] |
|
|
| |
| for root, _dirs, files in os.walk(output_dir): |
| for file in files: |
| if file.endswith(".rst") and file != "index.rst": |
| rel_path = os.path.relpath(os.path.join(root, file), output_dir) |
| rst_files.append(os.path.splitext(rel_path)[0]) |
|
|
| rst_files.sort() |
|
|
| index_content = f"""{package_name} API Reference |
| {"=" * (len(package_name) + len(" API Reference"))} |
| |
| .. toctree:: |
| :maxdepth: 2 |
| :caption: API Contents: |
| |
| """ |
| for file in rst_files: |
| index_content += f" {file}\n" |
|
|
| with open(index_path, "w", encoding="utf-8") as f: |
| f.write(index_content) |
| print(f"Updated {index_path} with module links.") |
|
|
| |
| |
| |
|
|
|
|
| if __name__ == "__main__": |
| package_to_document = "../biomni" |
| api_docs_path = "./source/api" |
| package_name = "biomni" |
|
|
| os.makedirs(api_docs_path, exist_ok=True) |
|
|
| exclude_list = [ |
| "llm.py", |
| "env_desc.py", |
| "version.py", |
| "tool/tool_description", |
| "tool/example_mcp_tools", |
| ] |
|
|
| generate_api_docs(package_to_document, api_docs_path, package_name, exclude_list) |
| create_index_rst(api_docs_path, package_name) |
|
|
| print("\nAPI documentation source files have been generated.") |
| print("Now run 'make html' from your project's root directory to build the documentation.") |
|
|