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 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.docfx_yaml.logger import get_logger, get_package_logger, get_warning_error_count, output_log_by_log_level
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
- # await(await asyncio.create_subprocess_exec(venv_exe, *pip_cmd)).wait()
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
- # await(await asyncio.create_subprocess_exec(executable, *pip_cmd)).wait()
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
- # await(await asyncio.create_subprocess_exec(executable, *pip_cmd)).wait()
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':
@@ -1,8 +1,10 @@
1
1
  import shutil
2
2
  from os import path
3
3
  import os
4
- import wheel.cli.unpack as wheel_cli_unpack
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
- wheel_cli_unpack.unpack(file_path, path.dirname(file_path))
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
- import asyncio
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
- if os.environ.get('LOG_LEVEL') == 'INFO':
36
- args = [
37
- "--module-first",
38
- "--no-headings",
39
- "--no-toc",
40
- "--implicit-namespaces",
41
- "-o",
42
- rst_path,
43
- subfolderPath,
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
- apidoc.main(args)
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
@@ -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.dev1929293
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=uhzznSKIF9Y-aslF42_y4BqlGfkDIwPlnhYT6IDuqLc,15004
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=7EmlodXVG0S5wnn0_VFPwPJ_3OHfJfGpN33SUL3HSRI,7233
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=bptweiUnlk_jtu1FxgqlqvHVOCfvoeAqemxli6ep0-o,1231
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=SGWS07Rn0sWlZsr_fdGIqLFHsgma4UvsghjzkNogFkc,2930
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=KM5SanFk67Kkd3oVKzNN-5KCAAiyNUUgnJl5mDs-3kw,4439
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=t4IqwDYp8dkbzS5-W0ChoeryzX0KAuq09bb5GhiU7f0,5497
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.dev1929293.dist-info/METADATA,sha256=LDqDxpPgSjI-Z-iTKM4bRTuRbiJDAwaCif99Nw9KnRY,600
4184
- py2docfx-0.1.9.dev1929293.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
4185
- py2docfx-0.1.9.dev1929293.dist-info/top_level.txt,sha256=5dH2uP81dczt_qQJ38wiZ-gzoVWasfiJALWRSjdbnYU,9
4186
- py2docfx-0.1.9.dev1929293.dist-info/RECORD,,
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,,