eng/scripts/build_api_docs.py (99 lines of code) (raw):

#!/usr/bin/python3 """ build_api_docs.py Script to generate Jazzy documentation. """ import datetime import glob from jinja2 import Template import logging import os import subprocess import sys import yaml import time logging.getLogger().setLevel(logging.WARNING) def _log_error_and_quit(msg, out = None, err = None, code = 1): """ Log an error message and exit. """ warning_color = "\033[91m" end_color = "\033[0m" if err: logging.error(f"{err}") elif out: logging.error(f"{out}") logging.error(f"{warning_color}{msg} ({code}){end_color}") sys.exit(code) def _log_warning(msg): """ Log a warning message. """ warning_color = "\033[93m" end_color = "\033[0m" logging.warning(f"{warning_color}{msg}{end_color}") def _run(command, **kwargs): process = subprocess.Popen(command.split() if not kwargs.get("shell", False) else command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) stdout, stderr = process.communicate() return (stdout.decode("utf-8"), stderr.decode("utf-8")) def _clone_github_repo(path, *, ref = None, pod_install = True): # clone the repo into the build folder so it can easily be removed repo_name = os.path.split(path)[-1] branch_arg = f"--branch {ref}" if ref else "" clone_dir = f"build/{repo_name}" if os.path.exists(clone_dir): _run(f"rm -rf {clone_dir}") _run(f"git clone {path} build/{repo_name} --depth 1 {branch_arg} --single-branch") if pod_install: try: # find the podfile and run pod install podfile_path = glob.glob(os.path.abspath(os.path.join(".", "build", repo_name, "**", "Podfile")))[0] podfile_dir = os.path.split(podfile_path)[0] stdout, stderr = _run(f"pod install --project-directory={podfile_dir}") print(stdout) except: _log_warning("Podfile not found. Attempting to generate docs without pod install...") if __name__ == "__main__": usage = f"usage: python {os.path.split(__file__)[1]} ( NAME ... | all)" args = sys.argv[1:] if not args: _log_error_and_quit(usage) if "-h" in args or "--help" in args: print(usage) sys.exit(1) if "all" in args: paths = glob.glob(os.path.join("jazzy", "*.yml")) else: paths = [f"jazzy/{x}.yml" for x in args] for path in paths: try: if not os.path.exists(path): logging.warning(f"No config found for {path}. Skipping.") continue with open(path, "r") as config_file: contents = yaml.safe_load(config_file) github_url = contents.get("github_url", None) ref = contents.get("ref", None) copy_only_mode = ref is not None if not github_url.endswith("/azure-sdk-for-ios"): print(f"Cloning repo: {github_url}...") _clone_github_repo(path=github_url, ref=ref, pod_install=(not copy_only_mode)) print(f"Generating docs for: {path}...") if not copy_only_mode: stdout, stderr = _run(f"jazzy --config {path}") else: time.sleep(5) output = "build/" + contents.get("output", None) input_dir = "build/" + os.path.split(github_url)[-1] print(f"Copying {input_dir} to {output}...") stdout, stderr = _run(f"mkdir -p {output}") stdout, stderr = _run(f"mv {input_dir}/* {output}", shell=True) if "RuntimeError" in stderr: logging.error(f"==BEGIN STDERR==.\n{stderr}\n==END STDERR==\nError generating docs.") else: print(stdout) except Exception as err: if "No such file or directory: 'jazzy'" in str(err): logging.error("error: Jazzy not installed. Download from https://github.com/realm/jazzy") else: logging.error(f"error: {err}") # load template and render index print("Generating index...") module_names = sorted([os.path.split(x)[-1][:-4] for x in paths]) index_template_path = os.path.abspath(os.path.join(".", "jazzy", "index_template.html")) with open(index_template_path) as infile: template = Template(infile.read()) rendered = template.render( copyright_year=datetime.date.today().year, navigation=module_names ) # write index to file index_path = os.path.abspath(os.path.join(".", "jazzy", "index.html")) with open(index_path, "w") as outfile: outfile.write(rendered) sys.exit(0)