175 lines
5.2 KiB
Python
175 lines
5.2 KiB
Python
import importlib
|
|
import logging
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Dict, List, Optional
|
|
|
|
# Configure logging
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
|
|
logger = logging.getLogger("sphinx-build")
|
|
|
|
# Add source directory to path
|
|
docs_dir = Path(__file__).parent
|
|
project_root = docs_dir.parent.parent
|
|
sys.path.insert(0, str(project_root / "src"))
|
|
|
|
# Project information
|
|
project = "pipecat-ai"
|
|
copyright = "2024, Daily"
|
|
author = "Daily"
|
|
|
|
# General configuration
|
|
extensions = [
|
|
"sphinx.ext.autodoc",
|
|
"sphinx.ext.napoleon",
|
|
"sphinx.ext.viewcode",
|
|
"sphinx.ext.intersphinx",
|
|
"sphinx.ext.coverage",
|
|
]
|
|
|
|
# Napoleon settings
|
|
napoleon_google_docstring = True
|
|
napoleon_numpy_docstring = False
|
|
napoleon_include_init_with_doc = True
|
|
|
|
# AutoDoc settings
|
|
autodoc_default_options = {
|
|
"members": True,
|
|
"member-order": "bysource",
|
|
"special-members": "__init__",
|
|
"undoc-members": True,
|
|
"exclude-members": "__weakref__",
|
|
"no-index": True,
|
|
"show-inheritance": True,
|
|
}
|
|
|
|
# HTML output settings
|
|
html_theme = "sphinx_rtd_theme"
|
|
html_static_path = ["_static"]
|
|
autodoc_typehints = "description"
|
|
html_show_sphinx = False
|
|
|
|
|
|
def get_installed_services() -> Dict[str, Optional[str]]:
|
|
"""Scan for installed pipecat services and return their status.
|
|
Returns a dictionary of service names and their import status/error message.
|
|
"""
|
|
services_dir = project_root / "src" / "pipecat" / "services"
|
|
services_status = {}
|
|
|
|
if not services_dir.exists():
|
|
logger.warning(f"Services directory not found: {services_dir}")
|
|
return services_status
|
|
|
|
for item in services_dir.iterdir():
|
|
if item.is_dir() and not item.name.startswith("_") and not item.name == "to_be_updated":
|
|
service_name = item.name
|
|
try:
|
|
module = importlib.import_module(f"pipecat.services.{service_name}")
|
|
services_status[service_name] = None # None indicates success
|
|
logger.info(f"Found service: {service_name} at {module.__file__}")
|
|
except ImportError as e:
|
|
services_status[service_name] = str(e)
|
|
logger.warning(f"Failed to import {service_name}: {e}")
|
|
|
|
return services_status
|
|
|
|
|
|
def generate_services_rst() -> str:
|
|
"""Generate RST content for services section."""
|
|
services = get_installed_services()
|
|
|
|
# Sort services into successful and failed imports
|
|
successful = [name for name, status in services.items() if status is None]
|
|
failed = [(name, status) for name, status in services.items() if status is not None]
|
|
|
|
rst_content = [
|
|
"Services",
|
|
"~~~~~~~~",
|
|
"",
|
|
"Successfully Detected Services:",
|
|
"",
|
|
]
|
|
|
|
for service in sorted(successful):
|
|
rst_content.append(f"* :mod:`pipecat.services.{service}`")
|
|
|
|
if failed:
|
|
rst_content.extend(
|
|
[
|
|
"",
|
|
"Services with Import Issues:",
|
|
"",
|
|
]
|
|
)
|
|
for service, error in sorted(failed):
|
|
rst_content.append(f"* {service} (Import failed: {error})")
|
|
|
|
return "\n".join(rst_content)
|
|
|
|
|
|
def setup(app):
|
|
"""Generate API documentation during Sphinx build."""
|
|
from sphinx.ext.apidoc import main
|
|
|
|
docs_dir = Path(__file__).parent
|
|
project_root = docs_dir.parent.parent
|
|
output_dir = str(docs_dir / "api")
|
|
source_dir = str(project_root / "src" / "pipecat")
|
|
|
|
# Clean existing files
|
|
if Path(output_dir).exists():
|
|
import shutil
|
|
|
|
shutil.rmtree(output_dir)
|
|
logger.info(f"Cleaned existing documentation in {output_dir}")
|
|
|
|
logger.info(f"Generating API documentation...")
|
|
logger.info(f"Output directory: {output_dir}")
|
|
logger.info(f"Source directory: {source_dir}")
|
|
|
|
# Get installed services
|
|
services = get_installed_services()
|
|
logger.info(f"Found {len(services)} services")
|
|
for service, status in services.items():
|
|
if status is None:
|
|
logger.info(f"Service available: {service}")
|
|
else:
|
|
logger.warning(f"Service import failed: {service} - {status}")
|
|
|
|
excludes = [
|
|
str(project_root / "src/pipecat/processors/gstreamer"),
|
|
str(project_root / "src/pipecat/transports/network"),
|
|
str(project_root / "src/pipecat/transports/services"),
|
|
str(project_root / "src/pipecat/transports/local"),
|
|
str(project_root / "src/pipecat/services/to_be_updated"),
|
|
"**/test_*.py",
|
|
"**/tests/*.py",
|
|
]
|
|
|
|
try:
|
|
main(
|
|
[
|
|
"-f",
|
|
"-e",
|
|
"-M",
|
|
"--no-toc",
|
|
"--separate",
|
|
"--module-first",
|
|
"-o",
|
|
output_dir,
|
|
source_dir,
|
|
]
|
|
+ excludes
|
|
)
|
|
|
|
logger.info("API documentation generated successfully!")
|
|
|
|
# Generate services index file
|
|
services_index = Path(output_dir) / "services_index.rst"
|
|
services_index.write_text(generate_services_rst())
|
|
logger.info(f"Generated services index at {services_index}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error generating API documentation: {e}", exc_info=True)
|