Files
mxpic_forge/docs/generate_handbook.py
T

166 lines
6.0 KiB
Python

# import os
# import shutil
# from pathlib import Path
# basic_md_info = "\
# .. mxpic_handbook documentation master file, created by\n\
# sphinx-quickstart on Sun May 3 16:05:57 2026.\n\
# You can adapt this file completely to your liking, but it should at least\n\
# contain the root `toctree` directive.\n\n\
# # Welcome to the automated documentation for the mxPIC silicon photonics library.\n\
# ```{toctree}\n\
# :maxdepth: 2\n\
# :caption: Components:\n\n\
# "
# def generate_myst_docs(src_dir: str, docs_api_dir: str) -> None:
# """
# Scans a Python package and generates MyST Markdown files for Sphinx autodoc.
# """
# src_path = Path(src_dir).resolve()
# api_path = Path(docs_api_dir).resolve()
# # Clean the old api directory to prevent dead links from deleted files
# if api_path.exists():
# # shutil.rmtree(api_path)
# pass
# else :
# api_path.mkdir(parents=True, exist_ok=True)
# package_name = src_path.name
# generated_files = []
# print(f"Scanning {package_name} for Python modules...")
# index_info = basic_md_info
# # Recursively find all .py files
# for py_file in src_path.rglob("*.py"):
# # Skip init files and private/internal scripts if desired
# if py_file.name == "__init__.py" or py_file.name.startswith("_"):
# continue
# # Convert file path to Python module format (e.g., mxpic.primitives.mzm)
# rel_path = py_file.relative_to(src_path.parent.parent)
# class_name = str(rel_path.with_suffix("")).replace(os.sep, ".")
# module_name = str(rel_path.with_suffix("")).replace(os.sep, "\\")
# index_md_name = str(rel_path.with_suffix("")).replace(os.sep, "/")
# # Create the markdown file
# md_filename = api_path / f"{module_name}.md"
# # MyST Markdown format using Sphinx autodoc directives
# content = f"# {module_name}\n \
# ```{{eval-rst}}\n \
# .. automodule:: {class_name}\n\
# :members:\n\
# :undoc-members:\n\
# :show-inheritance:\n\
# ```\n\
# "
# ## Building .md file for each .py file
# try :
# try : os.makedirs(name=str(md_filename.parent.resolve()))
# except : pass
# with open(file=str(md_filename.resolve()),mode="w") as md_file:
# md_file.write(content)
# print(f"Generated: {docs_api_dir}{module_name}.md")
# except Exception as e:
# print(e)
# ## Writing information into the index.md file
# index_info = index_info + f"{index_md_name}\n"
# with open(file=docs_api_dir+"index.md",mode="w") as md_file:
# md_file.write(index_info)
# if __name__ == "__main__":
# generate_myst_docs(src_dir="mxpic\\components\\",docs_api_dir="mxpic\\docs\\source\\")
import os
import sys
import importlib
import inspect
from pathlib import Path
def generate_markdown_handbook():
print("📝 Starting mxPIC Markdown Generation...")
# Define paths
src_root = Path("mxpic/components")
# This should point to where your Sphinx .md files are stored
docs_root = Path("docs/source/mxpic/components")
# We use absolute Sphinx paths for images (starts with / meaning docs/source root)
sphinx_image_root = "source/images/components"
success_count = 0
for py_file in src_root.rglob("*.py"):
if py_file.name == "__init__.py":
continue
# Convert path to module name (e.g., mxpic.components.primitives.beam_splitters)
rel_path = py_file.relative_to(src_root)
module_name = "mxpic.components." + str(rel_path.with_suffix("")).replace(os.sep, ".")
try:
module = importlib.import_module(module_name)
except Exception as e:
print(f"⚠️ Could not import {module_name}: {e}")
continue
# Find all classes defined inside this specific module
classes = []
for name, obj in inspect.getmembers(module, inspect.isclass):
if obj.__module__ == module_name:
classes.append(name)
# If the file has no classes, skip it
if not classes:
continue
# Define where to save the .md file
md_file_path = docs_root / rel_path.with_suffix(".md")
md_file_path.parent.mkdir(parents=True, exist_ok=True)
# --- WRITE THE MARKDOWN FILE ---
with open(md_file_path, "w", encoding="utf-8") as f:
# 1. Write the Module Header
f.write(f"# {module_name}\n\n")
# 2. Document any module-level docstrings (skipping classes)
f.write("```{eval-rst}\n")
f.write(f".. automodule:: {module_name}\n")
f.write(" :no-members:\n") # This prevents duplicating the classes!
f.write("```\n\n")
# 3. Loop through and write each class with its image
for class_name in classes:
f.write(f"## {class_name}\n\n")
# Point to the image path in Sphinx
# img_path = f"{sphinx_image_root}/{rel_path.parent.as_posix()}/{class_name}.png"
img_path = f"{class_name}.png"
f.write("```{eval-rst}\n")
# Insert the Sphinx image directive
f.write(f".. image:: {img_path}\n")
f.write(" :align: center\n")
f.write(" :width: 600px\n\n")
# Insert the specific class documentation
f.write(f".. autoclass:: {module_name}.{class_name}\n")
f.write(" :members:\n")
f.write(" :undoc-members:\n")
f.write(" :show-inheritance:\n")
f.write("```\n\n")
print(f"✅ Generated docs for: {module_name}")
success_count += 1
print(f"\n✨ Markdown generation complete! Updated {success_count} files.")
if __name__ == "__main__":
generate_markdown_handbook()