diff --git a/docs/conf.py b/docs/conf.py index d6a1c66f80..448b1cca25 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -43,6 +43,7 @@ "pw_docgen.sphinx.google_analytics", # Enables optional Google Analytics "pw_docgen.sphinx.kconfig", "pw_docgen.sphinx.module_metadata", + "pw_docgen.sphinx.modules_index", "pw_docgen.sphinx.pigweed_live", "pw_docgen.sphinx.pw_status_codes", "pw_docgen.sphinx.inlinesearch", diff --git a/docs/modules.rst b/docs/modules.rst index be783c7493..3195707c12 100644 --- a/docs/modules.rst +++ b/docs/modules.rst @@ -3,12 +3,13 @@ =================== Libraries (modules) =================== -Pigweed is a collection of embedded-focused and embedded-related :ref:`modules -`. Modules may contain code from multiple languages, -including C, C++, Go, Rust, Shell, Batch and Python. +.. The table that appears on the website version of this page +.. (https://pigweed.dev/modules.html) is auto-generated by +.. //pw_docgen/py/pw_docgen/sphinx/modules_index.py .. toctree:: :maxdepth: 1 + :hidden: docs/module_structure pw_alignment/docs diff --git a/pw_docgen/py/BUILD.gn b/pw_docgen/py/BUILD.gn index 0aee933fc1..3cb9a7baed 100644 --- a/pw_docgen/py/BUILD.gn +++ b/pw_docgen/py/BUILD.gn @@ -31,6 +31,7 @@ pw_python_package("py") { "pw_docgen/sphinx/inlinesearch/__init__.py", "pw_docgen/sphinx/kconfig.py", "pw_docgen/sphinx/module_metadata.py", + "pw_docgen/sphinx/modules_index.py", "pw_docgen/sphinx/pigweed_live.py", "pw_docgen/sphinx/pw_status_codes.py", "pw_docgen/sphinx/seed_metadata.py", diff --git a/pw_docgen/py/pw_docgen/sphinx/modules_index.py b/pw_docgen/py/pw_docgen/sphinx/modules_index.py new file mode 100644 index 0000000000..f7c95e3f5a --- /dev/null +++ b/pw_docgen/py/pw_docgen/sphinx/modules_index.py @@ -0,0 +1,93 @@ +# Copyright 2024 The Pigweed Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +"""Generates the modules index table on //docs/modules.rst.""" + +import json +import os +import sys + +from sphinx.application import Sphinx + + +with open(f'{os.environ["PW_ROOT"]}/PIGWEED_MODULES', 'r') as f: + # The complete, authoritative list of modules. + complete_pigweed_modules_list = f.read().splitlines() +with open(f'{os.environ["PW_ROOT"]}/docs/module_metadata.json', 'r') as f: + # Module metadata such as supported languages and status. + metadata = json.load(f) + + +def build_status_badge(status): + """Styles the module status as a clickable badge.""" + # This default value should never get used but it's a valid + # neutral styling in case something goes wrong and it leaks through. + badge_type = 'info' + if status == 'stable': + badge_type = 'primary' + elif status == 'unstable': + badge_type = 'secondary' + elif status == 'experimental': + badge_type = 'warning' + elif status == 'deprecated': + badge_type = 'danger' + else: + msg = f'[modules_index.py] error: invalid module status ("{status}")' + sys.exit(msg) + # Use bdg-ref-* to make the badge link to the glossary definition for + # "stable", "experimental", etc. + # https://sphinx-design.readthedocs.io/en/latest/badges_buttons.html + return f':bdg-{badge_type}:`{status}`' + + +def build_row(module_name: str): + """Builds a row of data for the table. Each module gets a row.""" + ref = f':ref:`module-{module_name}`' + if module_name not in metadata: + return f' "{ref}", "", "", ""\n' + tagline = metadata[module_name]['tagline'] + status = build_status_badge(metadata[module_name]['status']) + if 'languages' in metadata[module_name]: + languages = ', '.join(metadata[module_name]['languages']) + else: + languages = '' + return f' "{ref}", "{status}", "{tagline}", "{languages}"\n' + + +def generate_modules_index(_, docname: str, source: list[str]) -> None: + """Inserts the metadata table into //docs/modules.rst.""" + if docname != 'modules': # Only run this logic on //docs/modules.rst. + return + skip = ['docker'] # Items in //PIGWEED_MODULES that should be skipped. + # Transform //docs/module_metadata.json into a csv-table reST directive. + # https://docutils.sourceforge.io/docs/ref/rst/directives.html#csv-table-1 + content = '\n\n.. csv-table::\n' + content += ' :header: "Name", "Status", "Description", "Languages"\n\n' + # Loop through the complete, authoritative list (as opposed to the metadata) + # to guarantee that every module is listed on the modules index page. + for module in complete_pigweed_modules_list: + if module in skip: + continue + content += build_row(module) + # Modify the reST of //docs/modules.rst in-place. The auto-generated table + # is just appended to the reST source text. + source[0] += content + + +def setup(app: Sphinx) -> dict[str, bool]: + """Hooks this extension into Sphinx.""" + app.connect('source-read', generate_modules_index) + return { + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } diff --git a/pw_rpc_transport/docs.rst b/pw_rpc_transport/docs.rst index f599cfdbf2..9b97c23ad0 100644 --- a/pw_rpc_transport/docs.rst +++ b/pw_rpc_transport/docs.rst @@ -1,14 +1,14 @@ .. _module-pw_rpc_transport: -.. warning:: - This is an experimental module currently under development. APIs and - functionality may change at any time. - ================ pw_rpc_transport ================ The ``pw_rpc_transport`` provides a transport layer for ``pw_rpc``. +.. warning:: + This is an experimental module currently under development. APIs and + functionality may change at any time. + ``pw_rpc`` provides a system for defining and invoking remote procedure calls (RPCs) on a device. It does not include any transports for sending these RPC calls. On a real device there could be multiple ways of inter-process and/or