1""" 2Manifest Revisions Table 3======================== 4 5This extension allows to render a table containing the revisions of the projects 6present in a manifest file. 7 8Usage 9***** 10 11This extension introduces a new directive: ``manifest-projects-table``. It can 12be used in the code as:: 13 14 .. manifest-projects-table:: 15 :filter: active 16 17where the ``:filter:`` option can have the following values: active, inactive, all. 18 19Options 20******* 21 22- ``manifest_projects_table_manifest``: Path to the manifest file. 23 24Copyright (c) Nordic Semiconductor ASA 2022 25Copyright (c) Intel Corp 2023 26SPDX-License-Identifier: Apache-2.0 27""" 28 29import re 30from typing import Any 31 32from docutils import nodes 33from docutils.parsers.rst import directives 34from sphinx.application import Sphinx 35from sphinx.util.docutils import SphinxDirective 36from west.manifest import Manifest 37 38__version__ = "0.1.0" 39 40 41class ManifestProjectsTable(SphinxDirective): 42 """Manifest revisions table.""" 43 44 option_spec = { 45 "filter": directives.unchanged, 46 } 47 48 @staticmethod 49 def rev_url(base_url: str, rev: str) -> str: 50 """Return URL for a revision. 51 52 Notes: 53 Revision format is assumed to be a git hash or a tag. URL is 54 formatted assuming a GitHub base URL. 55 56 Args: 57 base_url: Base URL of the repository. 58 rev: Revision. 59 60 Returns: 61 URL for the revision. 62 """ 63 64 if re.match(r"^[0-9a-f]{40}$", rev): 65 return f"{base_url}/commit/{rev}" 66 67 return f"{base_url}/releases/tag/{rev}" 68 69 def run(self) -> list[nodes.Element]: 70 active_filter = self.options.get("filter", None) 71 72 manifest = Manifest.from_file(self.env.config.manifest_projects_table_manifest) 73 projects = [] 74 for project in manifest.projects: 75 if project.name == "manifest": 76 continue 77 if ( 78 active_filter == "active" 79 and manifest.is_active(project) 80 or active_filter == "inactive" 81 and not manifest.is_active(project) 82 or active_filter == "all" 83 or active_filter is None 84 ): 85 projects.append(project) 86 87 # build table 88 table = nodes.table() 89 90 tgroup = nodes.tgroup(cols=2) 91 tgroup += nodes.colspec(colwidth=1) 92 tgroup += nodes.colspec(colwidth=1) 93 table += tgroup 94 95 thead = nodes.thead() 96 tgroup += thead 97 98 row = nodes.row() 99 thead.append(row) 100 101 entry = nodes.entry() 102 entry += nodes.paragraph(text="Project") 103 row += entry 104 entry = nodes.entry() 105 entry += nodes.paragraph(text="Revision") 106 row += entry 107 108 rows = [] 109 for project in projects: 110 row = nodes.row() 111 rows.append(row) 112 113 entry = nodes.entry() 114 entry += nodes.paragraph(text=project.name) 115 row += entry 116 entry = nodes.entry() 117 par = nodes.paragraph() 118 par += nodes.reference( 119 project.revision, 120 project.revision, 121 internal=False, 122 refuri=ManifestProjectsTable.rev_url(project.url, project.revision), 123 ) 124 entry += par 125 row += entry 126 127 tbody = nodes.tbody() 128 tbody.extend(rows) 129 tgroup += tbody 130 131 return [table] 132 133 134def setup(app: Sphinx) -> dict[str, Any]: 135 app.add_config_value("manifest_projects_table_manifest", None, "env") 136 137 directives.register_directive("manifest-projects-table", ManifestProjectsTable) 138 139 return { 140 "version": __version__, 141 "parallel_read_safe": True, 142 "parallel_write_safe": True, 143 } 144