Files
HCFS/hcfs-python/build_docs.py
2025-07-30 09:34:16 +10:00

292 lines
9.1 KiB
Python

#!/usr/bin/env python3
"""
HCFS Documentation Builder
Builds comprehensive documentation including:
- HTML documentation with Sphinx
- PDF documentation with rst2pdf and LaTeX
- OpenAPI/Swagger documentation
- SDK API documentation
"""
import os
import sys
import subprocess
import shutil
from pathlib import Path
import argparse
def run_command(cmd, cwd=None, check=True):
"""Run a shell command and return the result."""
print(f"Running: {cmd}")
result = subprocess.run(cmd, shell=True, cwd=cwd, check=check,
capture_output=True, text=True)
if result.stdout:
print(result.stdout)
if result.stderr:
print(result.stderr, file=sys.stderr)
return result
def setup_environment():
"""Set up the documentation build environment."""
print("Setting up documentation environment...")
# Change to docs directory
docs_dir = Path(__file__).parent / "docs"
os.chdir(docs_dir)
# Install documentation dependencies
run_command("pip install -r requirements.txt")
# Create necessary directories
(docs_dir / "_static").mkdir(exist_ok=True)
(docs_dir / "_templates").mkdir(exist_ok=True)
(docs_dir / "api" / "generated").mkdir(parents=True, exist_ok=True)
return docs_dir
def generate_api_docs(docs_dir):
"""Generate API documentation from Python source."""
print("Generating API documentation...")
# Generate API docs with sphinx-apidoc
hcfs_source = docs_dir.parent / "hcfs"
api_output = docs_dir / "api"
run_command(f"sphinx-apidoc -o {api_output} {hcfs_source} --force --separate")
print("API documentation generated successfully!")
def build_html_docs(docs_dir):
"""Build HTML documentation."""
print("Building HTML documentation...")
html_output = docs_dir / "_build" / "html"
# Clean previous build
if html_output.exists():
shutil.rmtree(html_output)
# Build HTML docs
run_command("make html")
print(f"HTML documentation built successfully in {html_output}")
return html_output
def build_pdf_docs(docs_dir):
"""Build PDF documentation using multiple methods."""
print("Building PDF documentation...")
pdf_output = docs_dir / "_build" / "pdf"
pdf_output.mkdir(parents=True, exist_ok=True)
# Method 1: Using rst2pdf (faster, simpler)
try:
print("Building PDF with rst2pdf...")
run_command("make pdf")
# Find and copy PDF file
pdf_files = list((docs_dir / "_build" / "pdf").glob("*.pdf"))
if pdf_files:
main_pdf = pdf_files[0]
final_pdf = pdf_output / "HCFS-Documentation.pdf"
shutil.copy2(main_pdf, final_pdf)
print(f"rst2pdf documentation: {final_pdf}")
except subprocess.CalledProcessError:
print("rst2pdf failed, trying LaTeX method...")
# Method 2: Using LaTeX (higher quality, slower)
try:
print("Building PDF with LaTeX...")
run_command("make latexpdf")
# Find and copy LaTeX PDF
latex_pdf = docs_dir / "_build" / "latex" / "HCFS.pdf"
if latex_pdf.exists():
final_latex_pdf = pdf_output / "HCFS-Documentation-LaTeX.pdf"
shutil.copy2(latex_pdf, final_latex_pdf)
print(f"LaTeX PDF documentation: {final_latex_pdf}")
except subprocess.CalledProcessError:
print("LaTeX PDF generation failed (this is normal if LaTeX is not installed)")
return pdf_output
def build_epub_docs(docs_dir):
"""Build EPUB documentation."""
print("Building EPUB documentation...")
try:
run_command("make epub")
epub_file = docs_dir / "_build" / "epub" / "HCFS.epub"
if epub_file.exists():
print(f"EPUB documentation: {epub_file}")
return epub_file
except subprocess.CalledProcessError:
print("EPUB generation failed")
return None
def validate_openapi_spec():
"""Validate the OpenAPI specification."""
print("Validating OpenAPI specification...")
openapi_file = Path(__file__).parent / "openapi.yaml"
if not openapi_file.exists():
print("Warning: OpenAPI specification not found")
return False
try:
# Try to validate with swagger-codegen if available
run_command(f"swagger-codegen validate -i {openapi_file}", check=False)
except FileNotFoundError:
print("swagger-codegen not found, skipping OpenAPI validation")
return True
def generate_coverage_report(docs_dir):
"""Generate documentation coverage report."""
print("Generating documentation coverage report...")
try:
run_command("make coverage")
coverage_file = docs_dir / "_build" / "coverage" / "python.txt"
if coverage_file.exists():
print(f"Documentation coverage report: {coverage_file}")
# Print summary
with open(coverage_file, 'r') as f:
content = f.read()
print("Documentation Coverage Summary:")
print("=" * 40)
print(content[-500:]) # Print last 500 characters
except subprocess.CalledProcessError:
print("Coverage report generation failed")
def create_deployment_package(docs_dir, html_output, pdf_output):
"""Create a deployment package with all documentation."""
print("Creating deployment package...")
deploy_dir = docs_dir.parent / "docs-deploy"
if deploy_dir.exists():
shutil.rmtree(deploy_dir)
deploy_dir.mkdir()
# Copy HTML documentation
html_deploy = deploy_dir / "html"
shutil.copytree(html_output, html_deploy)
# Copy PDF files
pdf_deploy = deploy_dir / "pdf"
pdf_deploy.mkdir()
for pdf_file in pdf_output.glob("*.pdf"):
shutil.copy2(pdf_file, pdf_deploy)
# Copy OpenAPI spec
openapi_file = docs_dir.parent / "openapi.yaml"
if openapi_file.exists():
shutil.copy2(openapi_file, deploy_dir / "openapi.yaml")
# Create index file
index_content = """<!DOCTYPE html>
<html>
<head>
<title>HCFS Documentation</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.section { margin: 20px 0; }
.link { display: block; margin: 5px 0; }
</style>
</head>
<body>
<h1>HCFS Documentation</h1>
<div class="section">
<h2>HTML Documentation</h2>
<a href="html/index.html" class="link">Browse HTML Documentation</a>
</div>
<div class="section">
<h2>PDF Documentation</h2>
<a href="pdf/HCFS-Documentation.pdf" class="link">Download PDF (rst2pdf)</a>
<a href="pdf/HCFS-Documentation-LaTeX.pdf" class="link">Download PDF (LaTeX)</a>
</div>
<div class="section">
<h2>API Reference</h2>
<a href="openapi.yaml" class="link">OpenAPI Specification (YAML)</a>
<a href="html/api/reference.html" class="link">API Reference (HTML)</a>
</div>
</body>
</html>"""
with open(deploy_dir / "index.html", 'w') as f:
f.write(index_content)
print(f"Deployment package created: {deploy_dir}")
return deploy_dir
def main():
"""Main documentation build process."""
parser = argparse.ArgumentParser(description="Build HCFS documentation")
parser.add_argument("--format", choices=["html", "pdf", "epub", "all"],
default="all", help="Documentation format to build")
parser.add_argument("--skip-api", action="store_true",
help="Skip API documentation generation")
parser.add_argument("--skip-validation", action="store_true",
help="Skip OpenAPI validation")
parser.add_argument("--deploy", action="store_true",
help="Create deployment package")
args = parser.parse_args()
print("HCFS Documentation Builder")
print("=" * 50)
# Setup environment
docs_dir = setup_environment()
# Generate API documentation
if not args.skip_api:
generate_api_docs(docs_dir)
# Validate OpenAPI spec
if not args.skip_validation:
validate_openapi_spec()
# Build documentation formats
html_output = None
pdf_output = None
epub_output = None
if args.format in ["html", "all"]:
html_output = build_html_docs(docs_dir)
if args.format in ["pdf", "all"]:
pdf_output = build_pdf_docs(docs_dir)
if args.format in ["epub", "all"]:
epub_output = build_epub_docs(docs_dir)
# Generate coverage report
generate_coverage_report(docs_dir)
# Create deployment package
if args.deploy and html_output:
create_deployment_package(docs_dir, html_output, pdf_output or docs_dir / "_build" / "pdf")
print("\nDocumentation build completed successfully!")
print("=" * 50)
if html_output:
print(f"HTML documentation: {html_output}/index.html")
if pdf_output:
print(f"PDF documentation: {pdf_output}")
if epub_output:
print(f"EPUB documentation: {epub_output}")
if __name__ == "__main__":
main()