py2docfx 0.1.9.dev1929293__py3-none-any.whl → 0.1.9.dev1931282__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py2docfx/__main__.py +8 -265
- py2docfx/convert_prepare/arg_parser.py +211 -0
- py2docfx/convert_prepare/environment.py +5 -7
- py2docfx/convert_prepare/pack.py +13 -3
- py2docfx/convert_prepare/pip_utils.py +3 -23
- py2docfx/convert_prepare/sphinx_caller.py +11 -24
- py2docfx/convert_prepare/utils.py +41 -0
- py2docfx/docfx_yaml/logger.py +33 -2
- {py2docfx-0.1.9.dev1929293.dist-info → py2docfx-0.1.9.dev1931282.dist-info}/METADATA +1 -1
- {py2docfx-0.1.9.dev1929293.dist-info → py2docfx-0.1.9.dev1931282.dist-info}/RECORD +12 -10
- {py2docfx-0.1.9.dev1929293.dist-info → py2docfx-0.1.9.dev1931282.dist-info}/WHEEL +0 -0
- {py2docfx-0.1.9.dev1929293.dist-info → py2docfx-0.1.9.dev1931282.dist-info}/top_level.txt +0 -0
py2docfx/__main__.py
CHANGED
@@ -1,229 +1,22 @@
|
|
1
1
|
from __future__ import annotations # Avoid A | B annotation break under <= py3.9
|
2
2
|
import asyncio
|
3
|
-
import argparse
|
4
3
|
import logging
|
5
4
|
import os
|
6
|
-
import stat
|
7
5
|
import sys
|
8
|
-
import shutil
|
9
6
|
|
10
7
|
from py2docfx import PACKAGE_ROOT
|
11
|
-
from py2docfx.
|
8
|
+
from py2docfx.convert_prepare.arg_parser import parse_command_line_args
|
12
9
|
from py2docfx.convert_prepare.constants import SOURCE_REPO, TARGET_REPO, DIST_TEMP, LOG_FOLDER
|
13
10
|
from py2docfx.convert_prepare.generate_document import generate_document
|
14
11
|
from py2docfx.convert_prepare.get_source import YAML_OUTPUT_ROOT
|
15
12
|
from py2docfx.convert_prepare.post_process.merge_toc import merge_toc, move_root_toc_to_target
|
16
|
-
from py2docfx.convert_prepare.params import load_file_params, load_command_params
|
17
13
|
from py2docfx.convert_prepare.package_info import PackageInfo
|
14
|
+
from py2docfx.convert_prepare.utils import temp_folder_clean_up, prepare_out_dir
|
18
15
|
import py2docfx.convert_prepare.environment as py2docfxEnvironment
|
16
|
+
import py2docfx.docfx_yaml.logger as py2docfxLogger
|
19
17
|
|
20
18
|
os.chdir(PACKAGE_ROOT)
|
21
19
|
|
22
|
-
def get_parser() -> argparse.ArgumentParser:
|
23
|
-
parser = argparse.ArgumentParser(
|
24
|
-
description=(
|
25
|
-
"""A command line tool to run Sphinx with docfx-yaml extension,
|
26
|
-
transform python source code packages to yamls supported in docfx"""
|
27
|
-
)
|
28
|
-
)
|
29
|
-
|
30
|
-
parser.add_argument(
|
31
|
-
"-o"
|
32
|
-
"--output-root-folder",
|
33
|
-
default=None,
|
34
|
-
dest="output_root",
|
35
|
-
help="The output folder storing generated documents, use cwd if not assigned",
|
36
|
-
)
|
37
|
-
parser.add_argument(
|
38
|
-
"--github-token",
|
39
|
-
default=None,
|
40
|
-
dest="github_token",
|
41
|
-
help="Allow pipeline to clone Github source code repo",
|
42
|
-
)
|
43
|
-
parser.add_argument(
|
44
|
-
"--ado-token",
|
45
|
-
default=None,
|
46
|
-
dest="ado_token",
|
47
|
-
help="Allow pipeline to clone Azure DevOps source code repo",
|
48
|
-
)
|
49
|
-
parser.add_argument(
|
50
|
-
"-f",
|
51
|
-
"--param-file-path",
|
52
|
-
dest="param_file_path",
|
53
|
-
help="The json file contains package infomation",
|
54
|
-
)
|
55
|
-
parser.add_argument(
|
56
|
-
"-j",
|
57
|
-
"--param-json",
|
58
|
-
default=None,
|
59
|
-
dest="param_json",
|
60
|
-
help="The json string contains package infomation",
|
61
|
-
)
|
62
|
-
parser.add_argument(
|
63
|
-
"-t",
|
64
|
-
"--install-type",
|
65
|
-
action="store",
|
66
|
-
dest="install_type",
|
67
|
-
choices=["pypi", "source_code", "dist_file"],
|
68
|
-
help="""The type of source package, can be pip package, github repo or a distribution
|
69
|
-
file accessible in public""",
|
70
|
-
)
|
71
|
-
parser.add_argument(
|
72
|
-
"-n",
|
73
|
-
"--package-name",
|
74
|
-
default=None,
|
75
|
-
dest="package_name",
|
76
|
-
help="The name of source package, required if INSTALL_TYPE==pypi",
|
77
|
-
)
|
78
|
-
parser.add_argument(
|
79
|
-
"-v",
|
80
|
-
"--version",
|
81
|
-
default=None,
|
82
|
-
dest="version",
|
83
|
-
help="The version of source package, if not assigned, will use latest version",
|
84
|
-
)
|
85
|
-
parser.add_argument(
|
86
|
-
"-i",
|
87
|
-
"--extra-index-url",
|
88
|
-
default=None,
|
89
|
-
dest="extra_index_url",
|
90
|
-
help="Extra index of pip to download source package",
|
91
|
-
)
|
92
|
-
parser.add_argument(
|
93
|
-
"--url",
|
94
|
-
default=None,
|
95
|
-
dest="url",
|
96
|
-
help="""Valid when INSTALL_TYPE==source_code, url of the repo to
|
97
|
-
clone which contains SDK package source code.""",
|
98
|
-
)
|
99
|
-
parser.add_argument(
|
100
|
-
"--branch",
|
101
|
-
default=None,
|
102
|
-
dest="branch",
|
103
|
-
help="""Valid when INSTALL_TYPE==source_code, branch of the repo to clone which
|
104
|
-
contains SDK package source code.""",
|
105
|
-
)
|
106
|
-
parser.add_argument(
|
107
|
-
"--editable",
|
108
|
-
default=False,
|
109
|
-
dest="editable",
|
110
|
-
help="""Install a project in editable mode.""",
|
111
|
-
)
|
112
|
-
parser.add_argument(
|
113
|
-
"--folder",
|
114
|
-
default=None,
|
115
|
-
dest="folder",
|
116
|
-
help="""Valid when INSTALL_TYPE==source_code, relative folder path inside the repo
|
117
|
-
containing SDK package source code.""",
|
118
|
-
)
|
119
|
-
parser.add_argument(
|
120
|
-
"--prefer-source-distribution",
|
121
|
-
dest="prefer_source_distribution",
|
122
|
-
action="store_true",
|
123
|
-
help="""Valid when INSTALL_TYPE==pypi, a flag which add --prefer-binary
|
124
|
-
option to pip commands when getting package source.""",
|
125
|
-
)
|
126
|
-
parser.add_argument(
|
127
|
-
"--location",
|
128
|
-
default=None,
|
129
|
-
dest="location",
|
130
|
-
help="""Valid when INSTALL_TYPE==dist_file, the url of distribution file
|
131
|
-
containing source package.""",
|
132
|
-
)
|
133
|
-
parser.add_argument(
|
134
|
-
"--build-in-subpackage",
|
135
|
-
action="store_true",
|
136
|
-
dest="build_in_subpackage",
|
137
|
-
help="""When package has lot of big subpackages and each doesn't depend on others
|
138
|
-
enable to fasten build""",
|
139
|
-
)
|
140
|
-
parser.add_argument(
|
141
|
-
"exclude_path",
|
142
|
-
default=[],
|
143
|
-
nargs="*",
|
144
|
-
help="""A list containing relative paths to the root of the package of files/directories
|
145
|
-
excluded when generating documents, should follow fnmatch-style.""",
|
146
|
-
)
|
147
|
-
|
148
|
-
parser.add_argument(
|
149
|
-
"--verbose",
|
150
|
-
action="store_true",
|
151
|
-
help="""Increase output verbosity. Cannot be used together with --show-warning""",
|
152
|
-
)
|
153
|
-
|
154
|
-
parser.add_argument(
|
155
|
-
"--show-warning",
|
156
|
-
action="store_true",
|
157
|
-
help="""Show warning message. Cannot be used together with --verbose""",
|
158
|
-
)
|
159
|
-
return parser
|
160
|
-
|
161
|
-
|
162
|
-
def parse_command_line_args(argv) -> (
|
163
|
-
list[PackageInfo], list[PackageInfo], str, str, str | os.PathLike, bool, bool):
|
164
|
-
parser = get_parser()
|
165
|
-
args = parser.parse_args(argv)
|
166
|
-
|
167
|
-
github_token = args.github_token
|
168
|
-
ado_token = args.ado_token
|
169
|
-
output_root = args.output_root
|
170
|
-
verbose = args.verbose
|
171
|
-
show_warning = args.show_warning
|
172
|
-
|
173
|
-
if args.param_file_path:
|
174
|
-
(package_info_list, required_packages) = load_file_params(args.param_file_path)
|
175
|
-
return (list(package_info_list), list(required_packages), github_token,
|
176
|
-
ado_token, output_root, verbose, show_warning)
|
177
|
-
elif args.param_json:
|
178
|
-
(package_info_list, required_packages) = load_command_params(args.param_json)
|
179
|
-
return (package_info_list, required_packages, github_token,
|
180
|
-
ado_token, output_root, verbose, show_warning)
|
181
|
-
else:
|
182
|
-
package_info = PackageInfo()
|
183
|
-
if not args.install_type:
|
184
|
-
PackageInfo.report_error("install_type", args.install_type)
|
185
|
-
package_info.install_type = PackageInfo.InstallType[
|
186
|
-
args.install_type.upper()
|
187
|
-
]
|
188
|
-
|
189
|
-
package_info.name = args.package_name
|
190
|
-
package_info.version = args.version
|
191
|
-
package_info.extra_index_url = args.extra_index_url
|
192
|
-
package_info.editable = args.editable
|
193
|
-
package_info.prefer_source_distribution = (
|
194
|
-
args.prefer_source_distribution
|
195
|
-
)
|
196
|
-
package_info.build_in_subpackage = args.build_in_subpackage
|
197
|
-
package_info.exclude_path = args.exclude_path
|
198
|
-
|
199
|
-
if (
|
200
|
-
package_info.install_type == PackageInfo.InstallType.PYPI
|
201
|
-
and not package_info.name
|
202
|
-
):
|
203
|
-
PackageInfo.report_error("name", "None")
|
204
|
-
|
205
|
-
if package_info.install_type == PackageInfo.InstallType.SOURCE_CODE:
|
206
|
-
package_info.url = args.url
|
207
|
-
package_info.branch = args.branch
|
208
|
-
package_info.folder = args.folder
|
209
|
-
if not package_info.url:
|
210
|
-
if not package_info.folder:
|
211
|
-
msg = "When install_type is source_code, folder or url should be provided"
|
212
|
-
raise ValueError(msg)
|
213
|
-
else:
|
214
|
-
msg = f"Read source code from local folder: {package_info.folder}"
|
215
|
-
logging.info(msg)
|
216
|
-
|
217
|
-
if package_info.install_type == PackageInfo.InstallType.DIST_FILE:
|
218
|
-
package_info.location = args.location
|
219
|
-
if not package_info.location:
|
220
|
-
PackageInfo.report_error(
|
221
|
-
"location",
|
222
|
-
"None",
|
223
|
-
condition="When install_type is dist_file",
|
224
|
-
)
|
225
|
-
return ([package_info], [], github_token, ado_token, output_root, verbose, show_warning)
|
226
|
-
|
227
20
|
async def donwload_package_generate_documents(
|
228
21
|
package_info_list: list[PackageInfo],
|
229
22
|
output_root: str | os.PathLike | None,
|
@@ -245,7 +38,7 @@ async def donwload_package_generate_documents(
|
|
245
38
|
for idx, package in enumerate(package_info_list):
|
246
39
|
os.environ['PROCESSING_PACKAGE_NAME'] = package.name
|
247
40
|
package_number = start_num + idx
|
248
|
-
py2docfx_logger = get_package_logger(__name__)
|
41
|
+
py2docfx_logger = py2docfxLogger.get_package_logger(__name__)
|
249
42
|
msg = f"Processing package {package.name}, env_prepare_tasks: {len(env_prepare_tasks)}"
|
250
43
|
py2docfx_logger.info(msg)
|
251
44
|
|
@@ -295,56 +88,6 @@ async def donwload_package_generate_documents(
|
|
295
88
|
if env_remove_tasks[idx] != None and not env_remove_tasks[idx].done():
|
296
89
|
await env_remove_tasks[idx]
|
297
90
|
|
298
|
-
def prepare_out_dir(output_root: str | os.PathLike) -> os.PathLike | None:
|
299
|
-
# prepare output_root\DOC_FOLDER_NAME (if folder contains files, raise exception)
|
300
|
-
if output_root:
|
301
|
-
if os.path.exists(output_root):
|
302
|
-
if os.path.isfile(output_root):
|
303
|
-
raise ValueError(f"""output-root-folder is a path of file,
|
304
|
-
output-root-folder value: {output_root}""")
|
305
|
-
else:
|
306
|
-
if len(os.listdir(output_root)) > 0:
|
307
|
-
raise ValueError(f"""output-root-folder isn't empty,
|
308
|
-
output-root-folder value: {output_root}""")
|
309
|
-
return output_root
|
310
|
-
else:
|
311
|
-
os.makedirs(output_root)
|
312
|
-
return output_root
|
313
|
-
else:
|
314
|
-
return None
|
315
|
-
|
316
|
-
def on_rm_error( func, path, exc_info):
|
317
|
-
# path contains the path of the file that couldn't be removed
|
318
|
-
# let's just assume that it's read-only and unlink it.
|
319
|
-
os.chmod(path, stat.S_IWRITE)
|
320
|
-
os.unlink(path)
|
321
|
-
|
322
|
-
def remove_folder(folder: str | os.PathLike) -> None:
|
323
|
-
try:
|
324
|
-
shutil.rmtree(folder)
|
325
|
-
except PermissionError:
|
326
|
-
shutil.rmtree(folder, ignore_errors=False, onerror=on_rm_error)
|
327
|
-
if os.path.exists(folder):
|
328
|
-
raise ValueError(f"Failed to remove folder {folder}")
|
329
|
-
|
330
|
-
def temp_folder_clean_up(folder_list: list[str | os.PathLike]) -> None:
|
331
|
-
for folder in folder_list:
|
332
|
-
if os.path.exists(folder):
|
333
|
-
remove_folder(folder)
|
334
|
-
|
335
|
-
def decide_global_log_level(verbose: bool, show_warning: bool) -> None:
|
336
|
-
if verbose and show_warning:
|
337
|
-
raise ValueError("Cannot use --verbose and --show-warning at the same time")
|
338
|
-
if verbose:
|
339
|
-
os.environ['LOG_LEVEL'] = 'INFO'
|
340
|
-
return
|
341
|
-
if show_warning:
|
342
|
-
os.environ['LOG_LEVEL'] = 'WARNING'
|
343
|
-
return
|
344
|
-
|
345
|
-
# Default log level
|
346
|
-
os.environ['LOG_LEVEL'] = 'ERROR'
|
347
|
-
|
348
91
|
def main(argv) -> int:
|
349
92
|
# TODO: may need to purge pip cache
|
350
93
|
(package_info_list,
|
@@ -356,9 +99,9 @@ def main(argv) -> int:
|
|
356
99
|
clean_up_folder_list = [py2docfxEnvironment.VENV_DIR, DIST_TEMP, SOURCE_REPO, TARGET_REPO, LOG_FOLDER]
|
357
100
|
temp_folder_clean_up(clean_up_folder_list)
|
358
101
|
|
359
|
-
decide_global_log_level(verbose, show_warning)
|
102
|
+
py2docfxLogger.decide_global_log_level(verbose, show_warning)
|
360
103
|
|
361
|
-
py2docfx_logger = get_logger(__name__)
|
104
|
+
py2docfx_logger = py2docfxLogger.get_logger(__name__)
|
362
105
|
|
363
106
|
msg = "Adding yaml extension to path"
|
364
107
|
py2docfx_logger.info(msg)
|
@@ -375,8 +118,8 @@ def main(argv) -> int:
|
|
375
118
|
py2docfx_logger.error(msg)
|
376
119
|
raise
|
377
120
|
|
378
|
-
warning_count, error_count = get_warning_error_count()
|
379
|
-
output_log_by_log_level()
|
121
|
+
warning_count, error_count = py2docfxLogger.get_warning_error_count()
|
122
|
+
py2docfxLogger.output_log_by_log_level()
|
380
123
|
print(f"Warning count: {warning_count}, Error count: {error_count}")
|
381
124
|
logging.shutdown()
|
382
125
|
return 0
|
@@ -0,0 +1,211 @@
|
|
1
|
+
import argparse
|
2
|
+
import logging
|
3
|
+
import os
|
4
|
+
|
5
|
+
from py2docfx.convert_prepare.params import load_file_params, load_command_params
|
6
|
+
from py2docfx.convert_prepare.package_info import PackageInfo
|
7
|
+
|
8
|
+
def get_parser() -> argparse.ArgumentParser:
|
9
|
+
parser = argparse.ArgumentParser(
|
10
|
+
description=(
|
11
|
+
"""A command line tool to run Sphinx with docfx-yaml extension,
|
12
|
+
transform python source code packages to yamls supported in docfx"""
|
13
|
+
)
|
14
|
+
)
|
15
|
+
|
16
|
+
parser.add_argument(
|
17
|
+
"-o"
|
18
|
+
"--output-root-folder",
|
19
|
+
default=None,
|
20
|
+
dest="output_root",
|
21
|
+
help="The output folder storing generated documents, use cwd if not assigned",
|
22
|
+
)
|
23
|
+
parser.add_argument(
|
24
|
+
"--github-token",
|
25
|
+
default=None,
|
26
|
+
dest="github_token",
|
27
|
+
help="Allow pipeline to clone Github source code repo",
|
28
|
+
)
|
29
|
+
parser.add_argument(
|
30
|
+
"--ado-token",
|
31
|
+
default=None,
|
32
|
+
dest="ado_token",
|
33
|
+
help="Allow pipeline to clone Azure DevOps source code repo",
|
34
|
+
)
|
35
|
+
parser.add_argument(
|
36
|
+
"-f",
|
37
|
+
"--param-file-path",
|
38
|
+
dest="param_file_path",
|
39
|
+
help="The json file contains package infomation",
|
40
|
+
)
|
41
|
+
parser.add_argument(
|
42
|
+
"-j",
|
43
|
+
"--param-json",
|
44
|
+
default=None,
|
45
|
+
dest="param_json",
|
46
|
+
help="The json string contains package infomation",
|
47
|
+
)
|
48
|
+
parser.add_argument(
|
49
|
+
"-t",
|
50
|
+
"--install-type",
|
51
|
+
action="store",
|
52
|
+
dest="install_type",
|
53
|
+
choices=["pypi", "source_code", "dist_file"],
|
54
|
+
help="""The type of source package, can be pip package, github repo or a distribution
|
55
|
+
file accessible in public""",
|
56
|
+
)
|
57
|
+
parser.add_argument(
|
58
|
+
"-n",
|
59
|
+
"--package-name",
|
60
|
+
default=None,
|
61
|
+
dest="package_name",
|
62
|
+
help="The name of source package, required if INSTALL_TYPE==pypi",
|
63
|
+
)
|
64
|
+
parser.add_argument(
|
65
|
+
"-v",
|
66
|
+
"--version",
|
67
|
+
default=None,
|
68
|
+
dest="version",
|
69
|
+
help="The version of source package, if not assigned, will use latest version",
|
70
|
+
)
|
71
|
+
parser.add_argument(
|
72
|
+
"-i",
|
73
|
+
"--extra-index-url",
|
74
|
+
default=None,
|
75
|
+
dest="extra_index_url",
|
76
|
+
help="Extra index of pip to download source package",
|
77
|
+
)
|
78
|
+
parser.add_argument(
|
79
|
+
"--url",
|
80
|
+
default=None,
|
81
|
+
dest="url",
|
82
|
+
help="""Valid when INSTALL_TYPE==source_code, url of the repo to
|
83
|
+
clone which contains SDK package source code.""",
|
84
|
+
)
|
85
|
+
parser.add_argument(
|
86
|
+
"--branch",
|
87
|
+
default=None,
|
88
|
+
dest="branch",
|
89
|
+
help="""Valid when INSTALL_TYPE==source_code, branch of the repo to clone which
|
90
|
+
contains SDK package source code.""",
|
91
|
+
)
|
92
|
+
parser.add_argument(
|
93
|
+
"--editable",
|
94
|
+
default=False,
|
95
|
+
dest="editable",
|
96
|
+
help="""Install a project in editable mode.""",
|
97
|
+
)
|
98
|
+
parser.add_argument(
|
99
|
+
"--folder",
|
100
|
+
default=None,
|
101
|
+
dest="folder",
|
102
|
+
help="""Valid when INSTALL_TYPE==source_code, relative folder path inside the repo
|
103
|
+
containing SDK package source code.""",
|
104
|
+
)
|
105
|
+
parser.add_argument(
|
106
|
+
"--prefer-source-distribution",
|
107
|
+
dest="prefer_source_distribution",
|
108
|
+
action="store_true",
|
109
|
+
help="""Valid when INSTALL_TYPE==pypi, a flag which add --prefer-binary
|
110
|
+
option to pip commands when getting package source.""",
|
111
|
+
)
|
112
|
+
parser.add_argument(
|
113
|
+
"--location",
|
114
|
+
default=None,
|
115
|
+
dest="location",
|
116
|
+
help="""Valid when INSTALL_TYPE==dist_file, the url of distribution file
|
117
|
+
containing source package.""",
|
118
|
+
)
|
119
|
+
parser.add_argument(
|
120
|
+
"--build-in-subpackage",
|
121
|
+
action="store_true",
|
122
|
+
dest="build_in_subpackage",
|
123
|
+
help="""When package has lot of big subpackages and each doesn't depend on others
|
124
|
+
enable to fasten build""",
|
125
|
+
)
|
126
|
+
parser.add_argument(
|
127
|
+
"exclude_path",
|
128
|
+
default=[],
|
129
|
+
nargs="*",
|
130
|
+
help="""A list containing relative paths to the root of the package of files/directories
|
131
|
+
excluded when generating documents, should follow fnmatch-style.""",
|
132
|
+
)
|
133
|
+
|
134
|
+
parser.add_argument(
|
135
|
+
"--verbose",
|
136
|
+
action="store_true",
|
137
|
+
help="""Increase output verbosity. Cannot be used together with --show-warning""",
|
138
|
+
)
|
139
|
+
|
140
|
+
parser.add_argument(
|
141
|
+
"--show-warning",
|
142
|
+
action="store_true",
|
143
|
+
help="""Show warning message. Cannot be used together with --verbose""",
|
144
|
+
)
|
145
|
+
return parser
|
146
|
+
|
147
|
+
|
148
|
+
def parse_command_line_args(argv) -> (
|
149
|
+
list[PackageInfo], list[PackageInfo], str, str, str | os.PathLike, bool, bool):
|
150
|
+
parser = get_parser()
|
151
|
+
args = parser.parse_args(argv)
|
152
|
+
|
153
|
+
github_token = args.github_token
|
154
|
+
ado_token = args.ado_token
|
155
|
+
output_root = args.output_root
|
156
|
+
verbose = args.verbose
|
157
|
+
show_warning = args.show_warning
|
158
|
+
|
159
|
+
if args.param_file_path:
|
160
|
+
(package_info_list, required_packages) = load_file_params(args.param_file_path)
|
161
|
+
return (list(package_info_list), list(required_packages), github_token,
|
162
|
+
ado_token, output_root, verbose, show_warning)
|
163
|
+
elif args.param_json:
|
164
|
+
(package_info_list, required_packages) = load_command_params(args.param_json)
|
165
|
+
return (package_info_list, required_packages, github_token,
|
166
|
+
ado_token, output_root, verbose, show_warning)
|
167
|
+
else:
|
168
|
+
package_info = PackageInfo()
|
169
|
+
if not args.install_type:
|
170
|
+
PackageInfo.report_error("install_type", args.install_type)
|
171
|
+
package_info.install_type = PackageInfo.InstallType[
|
172
|
+
args.install_type.upper()
|
173
|
+
]
|
174
|
+
|
175
|
+
package_info.name = args.package_name
|
176
|
+
package_info.version = args.version
|
177
|
+
package_info.extra_index_url = args.extra_index_url
|
178
|
+
package_info.editable = args.editable
|
179
|
+
package_info.prefer_source_distribution = (
|
180
|
+
args.prefer_source_distribution
|
181
|
+
)
|
182
|
+
package_info.build_in_subpackage = args.build_in_subpackage
|
183
|
+
package_info.exclude_path = args.exclude_path
|
184
|
+
|
185
|
+
if (
|
186
|
+
package_info.install_type == PackageInfo.InstallType.PYPI
|
187
|
+
and not package_info.name
|
188
|
+
):
|
189
|
+
PackageInfo.report_error("name", "None")
|
190
|
+
|
191
|
+
if package_info.install_type == PackageInfo.InstallType.SOURCE_CODE:
|
192
|
+
package_info.url = args.url
|
193
|
+
package_info.branch = args.branch
|
194
|
+
package_info.folder = args.folder
|
195
|
+
if not package_info.url:
|
196
|
+
if not package_info.folder:
|
197
|
+
msg = "When install_type is source_code, folder or url should be provided"
|
198
|
+
raise ValueError(msg)
|
199
|
+
else:
|
200
|
+
msg = f"Read source code from local folder: {package_info.folder}"
|
201
|
+
logging.info(msg)
|
202
|
+
|
203
|
+
if package_info.install_type == PackageInfo.InstallType.DIST_FILE:
|
204
|
+
package_info.location = args.location
|
205
|
+
if not package_info.location:
|
206
|
+
PackageInfo.report_error(
|
207
|
+
"location",
|
208
|
+
"None",
|
209
|
+
condition="When install_type is dist_file",
|
210
|
+
)
|
211
|
+
return ([package_info], [], github_token, ado_token, output_root, verbose, show_warning)
|
@@ -2,11 +2,12 @@ import subprocess
|
|
2
2
|
import asyncio
|
3
3
|
import os
|
4
4
|
import sys
|
5
|
+
|
5
6
|
from py2docfx import PACKAGE_ROOT
|
6
7
|
from py2docfx.convert_prepare.package_info import PackageInfo
|
7
8
|
from py2docfx.convert_prepare.get_source import get_source
|
8
9
|
from py2docfx.convert_prepare import pip_utils
|
9
|
-
from py2docfx.docfx_yaml.logger import get_logger
|
10
|
+
from py2docfx.docfx_yaml.logger import get_logger, run_async_subprocess
|
10
11
|
|
11
12
|
REQUIREMENT_MODULES = ["setuptools", "sphinx==6.1.3", "pyyaml", "jinja2==3.0.3", "wheel"]
|
12
13
|
VENV_REQUIREMENT_MODULES = ["setuptools", "wheel"] # to support running setup.py in venv
|
@@ -47,8 +48,7 @@ def install_converter_requirements(executable: str):
|
|
47
48
|
async def install_venv_requirements(venv_num: int):
|
48
49
|
venv_exe = get_venv_exe(venv_num)
|
49
50
|
pip_cmd = ["-m", "pip", "install", "--upgrade"]+ VENV_REQUIREMENT_MODULES
|
50
|
-
|
51
|
-
await pip_utils.run_async_subprocess(venv_exe, pip_cmd)
|
51
|
+
await run_async_subprocess(venv_exe, pip_cmd)
|
52
52
|
|
53
53
|
def get_venv_path(venv_num: int) -> str:
|
54
54
|
return os.path.join(PACKAGE_ROOT, VENV_DIR, "venv"+str(venv_num))
|
@@ -85,8 +85,7 @@ def get_base_venv_sphinx_build_path() -> str:
|
|
85
85
|
|
86
86
|
async def install_converter_requirement_async(executable: str):
|
87
87
|
pip_cmd = PIP_INSTALL_COMMAND + PIP_INSTALL_VENV_COMMON_OPTIONS + REQUIREMENT_MODULES
|
88
|
-
|
89
|
-
await pip_utils.run_async_subprocess(executable, pip_cmd)
|
88
|
+
await run_async_subprocess(executable, pip_cmd)
|
90
89
|
|
91
90
|
async def install_required_packages(
|
92
91
|
executable: str, required_package_list: list[PackageInfo], github_token: str, ado_token: str):
|
@@ -96,8 +95,7 @@ async def install_required_packages(
|
|
96
95
|
# get_source(package, idx, vststoken=ado_token, githubtoken=github_token)
|
97
96
|
package_name, options = package.get_install_command()
|
98
97
|
pip_cmd = PIP_INSTALL_COMMAND + PIP_INSTALL_VENV_COMMON_OPTIONS + options + [package_name]
|
99
|
-
|
100
|
-
await pip_utils.run_async_subprocess(executable, pip_cmd)
|
98
|
+
await run_async_subprocess(executable, pip_cmd)
|
101
99
|
|
102
100
|
async def create_environment(venv_path: int):
|
103
101
|
if os.name == 'nt':
|
py2docfx/convert_prepare/pack.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
import shutil
|
2
2
|
from os import path
|
3
3
|
import os
|
4
|
-
import
|
4
|
+
import subprocess
|
5
|
+
import sys
|
5
6
|
|
7
|
+
from py2docfx.docfx_yaml.logger import get_package_logger, log_subprocess_ouput
|
6
8
|
|
7
9
|
def unpack_dist(dist_file):
|
8
10
|
if dist_file.endswith(".whl"):
|
@@ -22,8 +24,16 @@ def unpack_wheel(file_path):
|
|
22
24
|
"""
|
23
25
|
Transform a wheel file to a folder containing source code
|
24
26
|
"""
|
25
|
-
|
26
|
-
|
27
|
+
py2docfx_logger = get_package_logger(__name__)
|
28
|
+
command = [sys.executable,
|
29
|
+
'-m',
|
30
|
+
'wheel',
|
31
|
+
'unpack',
|
32
|
+
file_path,
|
33
|
+
'-d',
|
34
|
+
os.path.dirname(file_path)]
|
35
|
+
output = subprocess.run(command, check=True, capture_output=True, text=True)
|
36
|
+
log_subprocess_ouput(output, py2docfx_logger)
|
27
37
|
extract_folder = [file for file in os.listdir(path.dirname(file_path)) if path.isdir(path.join(path.dirname(file_path), file))][0]
|
28
38
|
data_folder = path.join(path.dirname(file_path), extract_folder, extract_folder + ".data")
|
29
39
|
if path.exists(data_folder):
|
@@ -1,8 +1,7 @@
|
|
1
1
|
import subprocess
|
2
|
-
|
3
|
-
import os
|
2
|
+
|
4
3
|
from py2docfx import PACKAGE_ROOT
|
5
|
-
from py2docfx.docfx_yaml.logger import get_logger, log_subprocess_ouput
|
4
|
+
from py2docfx.docfx_yaml.logger import get_logger, log_subprocess_ouput, run_async_subprocess
|
6
5
|
|
7
6
|
PYPI = "pypi"
|
8
7
|
|
@@ -50,23 +49,4 @@ def install_in_exe(exe_path, package_name, options):
|
|
50
49
|
|
51
50
|
async def install_in_exe_async(exe_path, package_name, options):
|
52
51
|
pip_cmd = ["-m", "pip", "install"]+ pip_install_common_options + options + [package_name]
|
53
|
-
await run_async_subprocess(exe_path, pip_cmd)
|
54
|
-
# await(await asyncio.create_subprocess_exec(exe_path, *pip_cmd)).wait()
|
55
|
-
|
56
|
-
async def run_async_subprocess(exe_path, cmd):
|
57
|
-
process = await asyncio.create_subprocess_exec(
|
58
|
-
exe_path, *cmd,
|
59
|
-
stdout=asyncio.subprocess.PIPE,
|
60
|
-
stderr=asyncio.subprocess.PIPE
|
61
|
-
)
|
62
|
-
stdout, stderr = await process.communicate()
|
63
|
-
py2docfx_logger = get_logger(__name__)
|
64
|
-
if process.returncode != 0:
|
65
|
-
msg = stderr.decode('utf-8')
|
66
|
-
if msg != None and msg != "":
|
67
|
-
py2docfx_logger.error(msg)
|
68
|
-
raise RuntimeError()
|
69
|
-
else:
|
70
|
-
msg = stdout.decode('utf-8')
|
71
|
-
if msg != None and msg != "":
|
72
|
-
py2docfx_logger.info(msg)
|
52
|
+
await run_async_subprocess(exe_path, pip_cmd)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
import os
|
2
2
|
import sys
|
3
|
-
from sphinx.application import Sphinx
|
4
|
-
import sphinx.ext.apidoc as apidoc
|
5
3
|
import subprocess
|
6
4
|
|
7
5
|
from py2docfx import PACKAGE_ROOT
|
@@ -32,29 +30,18 @@ def run_apidoc(rst_path, source_code_path, exclude_paths, package_info: PackageI
|
|
32
30
|
if os.path.isdir(subfolderPath):
|
33
31
|
msg = "<CI INFO>: Subfolder path {}.".format(subfolderPath)
|
34
32
|
py2docfx_logger.info(msg)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
]
|
45
|
-
else:
|
46
|
-
args = [
|
47
|
-
"-q",
|
48
|
-
"--module-first",
|
49
|
-
"--no-headings",
|
50
|
-
"--no-toc",
|
51
|
-
"--implicit-namespaces",
|
52
|
-
"-o",
|
53
|
-
rst_path,
|
54
|
-
subfolderPath
|
55
|
-
]
|
33
|
+
args = [
|
34
|
+
"--module-first",
|
35
|
+
"--no-headings",
|
36
|
+
"--no-toc",
|
37
|
+
"--implicit-namespaces",
|
38
|
+
"-o",
|
39
|
+
rst_path,
|
40
|
+
subfolderPath,
|
41
|
+
]
|
56
42
|
args.extend(exclude_paths)
|
57
|
-
|
43
|
+
output = subprocess.run([sys.executable, "-m", "sphinx.ext.apidoc"] + args, capture_output=True, text=True)
|
44
|
+
log_subprocess_ouput(output, py2docfx_logger)
|
58
45
|
if package_info.build_in_subpackage and subfolder == "azure":
|
59
46
|
subpackages_rst_record = move_rst_files_to_subfolder(
|
60
47
|
package_paths.doc_folder, package_info.name,
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import os
|
2
|
+
import shutil
|
3
|
+
import stat
|
4
|
+
|
5
|
+
def on_rm_error( func, path, exc_info):
|
6
|
+
# path contains the path of the file that couldn't be removed
|
7
|
+
# let's just assume that it's read-only and unlink it.
|
8
|
+
os.chmod(path, stat.S_IWRITE)
|
9
|
+
os.unlink(path)
|
10
|
+
|
11
|
+
def remove_folder(folder: str | os.PathLike) -> None:
|
12
|
+
try:
|
13
|
+
shutil.rmtree(folder)
|
14
|
+
except PermissionError as e:
|
15
|
+
if '.git' and '.idx' in str(e):
|
16
|
+
shutil.rmtree(folder, ignore_errors=False, onerror=on_rm_error)
|
17
|
+
if os.path.exists(folder):
|
18
|
+
raise RuntimeError(f"Failed to remove folder {folder}")
|
19
|
+
|
20
|
+
def temp_folder_clean_up(folder_list: list[str | os.PathLike]) -> None:
|
21
|
+
for folder in folder_list:
|
22
|
+
if os.path.exists(folder):
|
23
|
+
remove_folder(folder)
|
24
|
+
|
25
|
+
def prepare_out_dir(output_root: str | os.PathLike) -> os.PathLike | None:
|
26
|
+
# prepare output_root\DOC_FOLDER_NAME (if folder contains files, raise exception)
|
27
|
+
if output_root:
|
28
|
+
if os.path.exists(output_root):
|
29
|
+
if os.path.isfile(output_root):
|
30
|
+
raise ValueError(f"""output-root-folder is a path of file,
|
31
|
+
output-root-folder value: {output_root}""")
|
32
|
+
else:
|
33
|
+
if len(os.listdir(output_root)) > 0:
|
34
|
+
raise ValueError(f"""output-root-folder isn't empty,
|
35
|
+
output-root-folder value: {output_root}""")
|
36
|
+
return output_root
|
37
|
+
else:
|
38
|
+
os.makedirs(output_root)
|
39
|
+
return output_root
|
40
|
+
else:
|
41
|
+
return None
|
py2docfx/docfx_yaml/logger.py
CHANGED
@@ -1,7 +1,21 @@
|
|
1
|
+
import asyncio
|
1
2
|
import os
|
2
3
|
import logging
|
3
4
|
import subprocess
|
4
5
|
|
6
|
+
def decide_global_log_level(verbose: bool, show_warning: bool) -> None:
|
7
|
+
if verbose and show_warning:
|
8
|
+
raise ValueError("Cannot use --verbose and --show-warning at the same time")
|
9
|
+
if verbose:
|
10
|
+
os.environ['LOG_LEVEL'] = 'INFO'
|
11
|
+
return
|
12
|
+
if show_warning:
|
13
|
+
os.environ['LOG_LEVEL'] = 'WARNING'
|
14
|
+
return
|
15
|
+
|
16
|
+
# Default log level
|
17
|
+
os.environ['LOG_LEVEL'] = 'ERROR'
|
18
|
+
|
5
19
|
def get_log_level():
|
6
20
|
if os.environ.get('LOG_LEVEL') == 'WARNING':
|
7
21
|
return logging.WARNING
|
@@ -24,7 +38,6 @@ def setup_log_handlers(logger, log_file_name):
|
|
24
38
|
check_log_file_exists(log_file_name)
|
25
39
|
file_handler = logging.FileHandler(filename=log_file_name, mode='a')
|
26
40
|
file_handler.setFormatter(logging.Formatter('%(levelname)s - %(name)s - %(message)s'))
|
27
|
-
|
28
41
|
logger.addHandler(file_handler)
|
29
42
|
|
30
43
|
return logger
|
@@ -145,4 +158,22 @@ def output_log_by_log_level():
|
|
145
158
|
package_logs_folder = os.path.join("logs", "package_logs")
|
146
159
|
for log_file in os.listdir(package_logs_folder):
|
147
160
|
log_file_path = os.path.join(package_logs_folder, log_file)
|
148
|
-
print_out_log_by_log_level(parse_log(log_file_path), log_level)
|
161
|
+
print_out_log_by_log_level(parse_log(log_file_path), log_level)
|
162
|
+
|
163
|
+
async def run_async_subprocess(exe_path, cmd):
|
164
|
+
process = await asyncio.create_subprocess_exec(
|
165
|
+
exe_path, *cmd,
|
166
|
+
stdout=asyncio.subprocess.PIPE,
|
167
|
+
stderr=asyncio.subprocess.PIPE
|
168
|
+
)
|
169
|
+
stdout, stderr = await process.communicate()
|
170
|
+
py2docfx_logger = get_logger(__name__)
|
171
|
+
if process.returncode != 0:
|
172
|
+
msg = stderr.decode('utf-8')
|
173
|
+
if msg != None and msg != "":
|
174
|
+
py2docfx_logger.error(msg)
|
175
|
+
raise RuntimeError()
|
176
|
+
else:
|
177
|
+
msg = stdout.decode('utf-8')
|
178
|
+
if msg != None and msg != "":
|
179
|
+
py2docfx_logger.info(msg)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: py2docfx
|
3
|
-
Version: 0.1.9.
|
3
|
+
Version: 0.1.9.dev1931282
|
4
4
|
Summary: A package built based on Sphinx which download source code package and generate yaml files supported by docfx.
|
5
5
|
Author: Microsoft Corporation
|
6
6
|
License: MIT License
|
@@ -1,23 +1,25 @@
|
|
1
1
|
py2docfx/__init__.py,sha256=kPRhPGPC1JknDotkksG428c1iIgfFr_4_7Jm-llrowY,72
|
2
|
-
py2docfx/__main__.py,sha256=
|
2
|
+
py2docfx/__main__.py,sha256=MA5jRTbG6NH5ma7Ew8iSmaTp3YSTWoRhEwOiPX2chvs,5674
|
3
3
|
py2docfx/convert_prepare/__init__.py,sha256=XxtxrP0kmW3ZBHIAoxsPDEHzcgeC0WSnole8Lk6CjKs,11
|
4
|
+
py2docfx/convert_prepare/arg_parser.py,sha256=Wa1iK8a0Gb3QqaS4X7nUPGvh-7mWhuBS9IVbmnjC770,7606
|
4
5
|
py2docfx/convert_prepare/constants.py,sha256=RC5DqNkqWvx4hb91FrajZ1R9dBFLxcPyoEJ43jdm36E,102
|
5
|
-
py2docfx/convert_prepare/environment.py,sha256=
|
6
|
+
py2docfx/convert_prepare/environment.py,sha256=j2pQ7cfkxJDpw9kXL4VbVuq23B3fXMoc8EdIGmLX5YM,6985
|
6
7
|
py2docfx/convert_prepare/generate_conf.py,sha256=wqs6iyElzJarH-20_qEL9zvZvt5xfBMsGXSXPSZy6wg,2295
|
7
8
|
py2docfx/convert_prepare/generate_document.py,sha256=mNfJpLViIfzwRnjVwXmg5H5lVWzKJkUHeXTiJouA39o,2879
|
8
9
|
py2docfx/convert_prepare/get_source.py,sha256=6EMSLiDOfid4d7SDxweV_-TGV4McxhSxKQPJju2Mi4Y,5221
|
9
10
|
py2docfx/convert_prepare/git.py,sha256=OIoaX_0LG5ueY8zmUwrbxl_YyMxwLzgTp6g0uSkC2Y0,6617
|
10
11
|
py2docfx/convert_prepare/install_package.py,sha256=hATmgazcSX7k2n4jQXh9sQMyNUc1k1YqHv5K5UMALq4,262
|
11
|
-
py2docfx/convert_prepare/pack.py,sha256=
|
12
|
+
py2docfx/convert_prepare/pack.py,sha256=k8eme75VRhdsZOc9ox0zNORXP4kFhAiPiP4mUdNBwwU,1614
|
12
13
|
py2docfx/convert_prepare/package_info.py,sha256=2fDyalHtxhZQICehDK4zv7k69HE427c1MLEuHVnPzBU,7624
|
13
14
|
py2docfx/convert_prepare/package_info_extra_settings.py,sha256=u5B5e8hc0m9PA_-0kJzq1LtKn-xzZlucwXHTFy49mDg,1475
|
14
15
|
py2docfx/convert_prepare/params.py,sha256=PXMB8pLtb4XbfI322avA47q0AO-TyBE6kZf7FU8I6v4,1771
|
15
16
|
py2docfx/convert_prepare/paths.py,sha256=964RX81Qf__rzXgEATfqBNFCKTYVjLt9J7WCz2TnNdc,485
|
16
|
-
py2docfx/convert_prepare/pip_utils.py,sha256=
|
17
|
+
py2docfx/convert_prepare/pip_utils.py,sha256=GPWGUBcxW8JKreGwxZIAe9AWAI78aL1aFan8DvaAf1o,2228
|
17
18
|
py2docfx/convert_prepare/repo_info.py,sha256=6ASJlhBwf6vZTSENgrWCVlJjlJVhuBxzdQyWEdWAC4c,117
|
18
19
|
py2docfx/convert_prepare/source.py,sha256=6-A7oof3-WAQcQZZVpT9pKiFLH4CCIZeYqq0MN0O3gw,1710
|
19
|
-
py2docfx/convert_prepare/sphinx_caller.py,sha256=
|
20
|
+
py2docfx/convert_prepare/sphinx_caller.py,sha256=4hYjDQgwEaAkCl8V7q05sn4RmWJQA_QthtztV6l6K-w,4082
|
20
21
|
py2docfx/convert_prepare/subpackage.py,sha256=mXAi_07pXvnPkSLZfykDh_7VeFxfLy74pYlzhMO8N_Q,5183
|
22
|
+
py2docfx/convert_prepare/utils.py,sha256=TwfDjIqIx_nAoSeQ-LX30h_-d96WhPQcAu7P8N_tSjM,1618
|
21
23
|
py2docfx/convert_prepare/conf_templates/conf.py_t,sha256=8zxvY1WiG-z2aiSNDY0719C08QxZLXXEMwKfYSGN0ZE,3811
|
22
24
|
py2docfx/convert_prepare/conf_templates/root_doc.rst_t,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
25
|
py2docfx/convert_prepare/post_process/merge_toc.py,sha256=DPUvL6eS0Q4gcp_fdGgWQJeYmt0sa9voWnVe0O-2giM,1265
|
@@ -63,7 +65,7 @@ py2docfx/docfx_yaml/convert_enum.py,sha256=QH0OkZq8pFi_nAXem6ddkO_7TSsoY2tz7_wxI
|
|
63
65
|
py2docfx/docfx_yaml/convert_module.py,sha256=GptO1MRwaQ2Qbu724F0kCDDQQTZe7mWOtrOp3Rzgl-I,2259
|
64
66
|
py2docfx/docfx_yaml/convert_package.py,sha256=Ep7PmvoLInDvY6OU5dveR6iVwyzGRkW3q6lX7yGJ0JE,2109
|
65
67
|
py2docfx/docfx_yaml/directives.py,sha256=zVVuNM_6AU9G6sbqL1UAyHHgPe7bkBWbthXI-PO5ez0,879
|
66
|
-
py2docfx/docfx_yaml/logger.py,sha256=
|
68
|
+
py2docfx/docfx_yaml/logger.py,sha256=XIznVK30tjpcstpyjNuJM43gs0DkCRjmU_kaLhCxS8M,6547
|
67
69
|
py2docfx/docfx_yaml/miss_reference.py,sha256=Btoj9wAvA4u_wU7JHH0Cei3910N8a7MS34OUqJvXAd4,2443
|
68
70
|
py2docfx/docfx_yaml/nodes.py,sha256=tBDi35jLJArlobl07DKOkmH2qz7dudXLp_kTUfR_r2w,412
|
69
71
|
py2docfx/docfx_yaml/parameter_utils.py,sha256=zGSIQrUfbXf9PUK-W_1K83Uo5Zk797Zlze6aMurbHIA,8706
|
@@ -4180,7 +4182,7 @@ py2docfx/venv/venv1/Lib/site-packages/win32comext/taskscheduler/test/test_addtas
|
|
4180
4182
|
py2docfx/venv/venv1/Lib/site-packages/win32comext/taskscheduler/test/test_localsystem.py,sha256=08ojAS48W6RLsUbRD45j0SJhg_Y2NFHZT6qjT4Vrig0,75
|
4181
4183
|
py2docfx/venv/venv1/Scripts/pywin32_postinstall.py,sha256=u95n7QQUxpCjrZistYE-3gN451zXzopuJna8cXRQ4Jw,28115
|
4182
4184
|
py2docfx/venv/venv1/Scripts/pywin32_testall.py,sha256=-6yvZmd2lPQc4e8i6PgLsr_totF6mScvoq0Jqr0V2fM,3844
|
4183
|
-
py2docfx-0.1.9.
|
4184
|
-
py2docfx-0.1.9.
|
4185
|
-
py2docfx-0.1.9.
|
4186
|
-
py2docfx-0.1.9.
|
4185
|
+
py2docfx-0.1.9.dev1931282.dist-info/METADATA,sha256=l1MDPaHDr5FIdNgjvFLycZsIkIqACVVILJ2qfhdMGtU,600
|
4186
|
+
py2docfx-0.1.9.dev1931282.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
4187
|
+
py2docfx-0.1.9.dev1931282.dist-info/top_level.txt,sha256=5dH2uP81dczt_qQJ38wiZ-gzoVWasfiJALWRSjdbnYU,9
|
4188
|
+
py2docfx-0.1.9.dev1931282.dist-info/RECORD,,
|
File without changes
|
File without changes
|