docs: add API guide page about IDF Tools

This commit is contained in:
Ivan Grokhotkov
2020-01-17 19:38:50 +03:00
parent c1ab87b580
commit 1cd6f67679
9 changed files with 369 additions and 12 deletions
+112 -12
View File
@@ -56,6 +56,11 @@ import functools
import copy
from collections import OrderedDict, namedtuple
try:
import typing # noqa: F401
except ImportError:
pass
try:
from urllib.request import urlretrieve
except ImportError:
@@ -137,9 +142,9 @@ EXPORT_KEY_VALUE = 'key-value'
global_quiet = False
global_non_interactive = False
global_idf_path = None
global_idf_tools_path = None
global_tools_json = None
global_idf_path = None # type: typing.Optional[str]
global_idf_tools_path = None # type: typing.Optional[str]
global_tools_json = None # type: typing.Optional[str]
def fatal(text, *args):
@@ -356,7 +361,7 @@ class IDFToolVersion(object):
def add_download(self, platform_name, url, size, sha256):
self.downloads[platform_name] = IDFToolDownload(platform_name, url, size, sha256)
def get_download_for_platform(self, platform_name):
def get_download_for_platform(self, platform_name): # type: (str) -> IDFToolDownload
if platform_name in PLATFORM_FROM_NAME.keys():
platform_name = PLATFORM_FROM_NAME[platform_name]
if platform_name in self.downloads.keys():
@@ -368,6 +373,9 @@ class IDFToolVersion(object):
def compatible_with_platform(self, platform_name=PYTHON_PLATFORM):
return self.get_download_for_platform(platform_name) is not None
def get_supported_platforms(self): # type: () -> typing.Set[str]
return set(self.downloads.keys())
OPTIONS_LIST = ['version_cmd',
'version_regex',
@@ -392,7 +400,7 @@ class IDFTool(object):
strip_container_dirs=0):
self.name = name
self.description = description
self.versions = OrderedDict()
self.versions = OrderedDict() # type: typing.Dict[str, IDFToolVersion]
self.version_in_path = None
self.versions_installed = []
if version_regex_replace is None:
@@ -403,7 +411,7 @@ class IDFTool(object):
self._platform = CURRENT_PLATFORM
self._update_current_options()
def copy_for_platform(self, platform):
def copy_for_platform(self, platform): # type: (str) -> IDFTool
result = copy.deepcopy(self)
result._platform = platform
result._update_current_options()
@@ -422,18 +430,18 @@ class IDFTool(object):
assert(type(version) is IDFToolVersion)
self.versions[version.version] = version
def get_path(self):
def get_path(self): # type: () -> str
return os.path.join(global_idf_tools_path, 'tools', self.name)
def get_path_for_version(self, version):
def get_path_for_version(self, version): # type: (str) -> str
assert(version in self.versions)
return os.path.join(self.get_path(), version)
def get_export_paths(self, version):
def get_export_paths(self, version): # type: (str) -> typing.List[str]
tool_path = self.get_path_for_version(version)
return [os.path.join(tool_path, *p) for p in self._current_options.export_paths]
def get_export_vars(self, version):
def get_export_vars(self, version): # type: (str) -> typing.Dict[str]
"""
Get the dictionary of environment variables to be exported, for the given version.
Expands:
@@ -448,7 +456,7 @@ class IDFTool(object):
result[k] = v_repl
return result
def check_version(self, extra_paths=None):
def check_version(self, extra_paths=None): # type: (typing.Optional[typing.List[str]]) -> str
"""
Execute the tool, optionally prepending extra_paths to PATH,
extract the version string and return it as a result.
@@ -481,6 +489,12 @@ class IDFTool(object):
def compatible_with_platform(self):
return any([v.compatible_with_platform() for v in self.versions.values()])
def get_supported_platforms(self): # type: () -> typing.Set[str]
result = set()
for v in self.versions.values():
result.update(v.get_supported_platforms())
return result
def get_recommended_version(self):
recommended_versions = [k for k, v in self.versions.items()
if v.status == IDFToolVersion.STATUS_RECOMMENDED
@@ -792,7 +806,7 @@ class IDFTool(object):
return tool_json
def load_tools_info():
def load_tools_info(): # type: () -> typing.Dict[str, IDFTool]
"""
Load tools metadata from tools.json, return a dictionary: tool name - tool info
"""
@@ -1267,6 +1281,87 @@ def action_validate(args):
# on failure, this will raise an exception with a fairly verbose diagnostic message
def action_gen_doc(args):
f = args.output
tools_info = load_tools_info()
def print_out(text):
f.write(text + '\n')
print_out(".. |zwsp| unicode:: U+200B")
print_out(" :trim:")
print_out("")
idf_gh_url = "https://github.com/espressif/esp-idf"
for tool_name, tool_obj in tools_info.items():
info_url = tool_obj.options.info_url
if idf_gh_url + "/tree" in info_url:
info_url = re.sub(idf_gh_url + r"/tree/\w+/(.*)", r":idf:`\1`", info_url)
license_url = "https://spdx.org/licenses/" + tool_obj.options.license
print_out("""
.. _tool-{name}:
{name}
{underline}
{description}
.. include:: idf-tools-notes.inc
:start-after: tool-{name}-notes
:end-before: ---
License: `{license} <{license_url}>`_
More info: {info_url}
.. list-table::
:widths: 10 10 80
:header-rows: 1
* - Platform
- Required
- Download
""".rstrip().format(name=tool_name,
underline=args.heading_underline_char * len(tool_name),
description=tool_obj.description,
license=tool_obj.options.license,
license_url=license_url,
info_url=info_url))
for platform_name in sorted(tool_obj.get_supported_platforms()):
platform_tool = tool_obj.copy_for_platform(platform_name)
install_type = platform_tool.get_install_type()
if install_type == IDFTool.INSTALL_NEVER:
continue
elif install_type == IDFTool.INSTALL_ALWAYS:
install_type_str = "required"
elif install_type == IDFTool.INSTALL_ON_REQUEST:
install_type_str = "optional"
else:
raise NotImplementedError()
version = platform_tool.get_recommended_version()
version_obj = platform_tool.versions[version]
download_obj = version_obj.get_download_for_platform(platform_name)
# Note: keep the list entries indented to the same number of columns
# as the list header above.
print_out("""
* - {}
- {}
- {}
.. rst-class:: tool-sha256
SHA256: {}
""".strip('\n').format(platform_name, install_type_str, download_obj.url, download_obj.sha256))
print_out('')
print_out('')
def main(argv):
parser = argparse.ArgumentParser()
@@ -1328,6 +1423,11 @@ def main(argv):
subparsers.add_parser('validate', help='Validate tools.json against schema file')
gen_doc = subparsers.add_parser('gen-doc', help='Write the list of tools as a documentation page')
gen_doc.add_argument('--output', type=argparse.FileType('w'), default=sys.stdout,
help='Output file name')
gen_doc.add_argument('--heading-underline-char', help='Character to use when generating RST sections', default='~')
args = parser.parse_args(argv)
if args.action is None: