File: run_sphinx_apidoc.py

package info (click to toggle)
python-azure 20250603%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 851,724 kB
  • sloc: python: 7,362,925; ansic: 804; javascript: 287; makefile: 195; sh: 145; xml: 109
file content (139 lines) | stat: -rw-r--r-- 5,210 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python

# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# This script is used to execute pylint within a tox environment. Depending on which package is being executed against,
# a failure may be suppressed.

from subprocess import check_call, CalledProcessError
import argparse
import os
import logging
from prep_sphinx_env import should_build_docs
import sys
import shutil
from pathlib import Path

from ci_tools.parsing import ParsedSetup

logging.getLogger().setLevel(logging.INFO)

root_dir = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", ".."))
generate_mgmt_script = os.path.join(root_dir, "doc/sphinx/generate_doc.py")

def is_mgmt_package(pkg_name):
    return pkg_name != "azure-mgmt-core" and ("mgmt" in pkg_name or "cognitiveservices" in pkg_name)

def copy_existing_docs(source, target):
    for file in os.listdir(source):
        logging.info("Copying {}".format(file))
        shutil.copy(os.path.join(source, file), target)

def sphinx_apidoc(working_directory: str, namespace: str) -> None:
    working_doc_folder = os.path.join(args.working_directory, "unzipped", "doc")
    command_array = [
            "sphinx-apidoc",
            "--no-toc",
            "--module-first",
            "-o",
            os.path.join(args.working_directory, "unzipped/docgen"),   # This is the output folder
            os.path.join(args.working_directory, "unzipped/"),         # This is the input folder
            os.path.join(args.working_directory, "unzipped/test*"),    # Starting here this, is excluded
            os.path.join(args.working_directory, "unzipped/example*"),
            os.path.join(args.working_directory, "unzipped/sample*"),
            os.path.join(args.working_directory, "unzipped/setup.py"),
        ]

    try:
        # if a `doc` folder exists, just leverage the sphinx sources found therein.
        if os.path.exists(working_doc_folder):
            logging.info("Copying files into sphinx source folder.")
            copy_existing_docs(working_doc_folder, os.path.join(args.working_directory, "unzipped/docgen"))

        # otherwise, we will run sphinx-apidoc to generate the sources
        else:
            logging.info("Sphinx api-doc command: {}".format(command_array))
            check_call(
                command_array
            )
            # We need to clean "azure.rst", and other RST before the main namespaces, as they are never
            # used and will log as a warning later by sphinx-build, which is blocking strict_sphinx
            base_path = Path(os.path.join(args.working_directory, "unzipped/docgen/"))
            namespace = namespace.rpartition('.')[0]
            while namespace:
                rst_file_to_delete = base_path / f"{namespace}.rst"
                logging.info(f"Removing {rst_file_to_delete}")
                rst_file_to_delete.unlink()
                namespace = namespace.rpartition('.')[0]
    except CalledProcessError as e:
        logging.error(
            "sphinx-apidoc failed for path {} exited with error {}".format(
                args.working_directory, e.returncode
            )
        )
        exit(1)

def mgmt_apidoc(working_directory: str, target_folder: str):
    command_array = [
        sys.executable,
        generate_mgmt_script,
        "-p",
        target_folder,
        "-o",
        working_directory,
        "--verbose",
        ]

    try:
        logging.info("Command to generate management sphinx sources: {}".format(command_array))

        check_call(
            command_array
        )
    except CalledProcessError as e:
        logging.error(
            "script failed for path {} exited with error {}".format(
                args.working_directory, e.returncode
            )
        )
        exit(1)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Run sphinx-apidoc against target folder. Handles management generation if necessary."
    )

    parser.add_argument(
        "-w",
        "--workingdir",
        dest="working_directory",
        help="The unzipped package directory on disk. Usually {distdir}/unzipped/",
        required=True,
    )

    parser.add_argument(
        "-r",
        "--root",
        dest="package_root",
        help="",
        required=True,
    )

    args = parser.parse_args()

    target_dir = os.path.abspath(args.working_directory)
    package_dir = os.path.abspath(args.package_root)
    output_directory = os.path.join(target_dir, "unzipped/docgen")

    pkg_details = ParsedSetup.from_path(package_dir)

    if should_build_docs(pkg_details.name):
        if is_mgmt_package(pkg_details.name):
            mgmt_apidoc(output_directory, pkg_details.folder)
        else:
            sphinx_apidoc(args.working_directory, pkg_details.namespace)
    else:
        logging.info("Skipping sphinx source generation for {}".format(pkg_details.name))