xref: /aosp_15_r20/external/protobuf/python/docs/generate_docs.py (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker#!/usr/bin/env python
2*1b3f573fSAndroid Build Coastguard Worker# Protocol Buffers - Google's data interchange format
3*1b3f573fSAndroid Build Coastguard Worker# Copyright 2008 Google Inc.  All rights reserved.
4*1b3f573fSAndroid Build Coastguard Worker# https://developers.google.com/protocol-buffers/
5*1b3f573fSAndroid Build Coastguard Worker#
6*1b3f573fSAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without
7*1b3f573fSAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are
8*1b3f573fSAndroid Build Coastguard Worker# met:
9*1b3f573fSAndroid Build Coastguard Worker#
10*1b3f573fSAndroid Build Coastguard Worker#   * Redistributions of source code must retain the above copyright
11*1b3f573fSAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer.
12*1b3f573fSAndroid Build Coastguard Worker#   * Redistributions in binary form must reproduce the above
13*1b3f573fSAndroid Build Coastguard Worker# copyright notice, this list of conditions and the following disclaimer
14*1b3f573fSAndroid Build Coastguard Worker# in the documentation and/or other materials provided with the
15*1b3f573fSAndroid Build Coastguard Worker# distribution.
16*1b3f573fSAndroid Build Coastguard Worker#   * Neither the name of Google Inc. nor the names of its
17*1b3f573fSAndroid Build Coastguard Worker# contributors may be used to endorse or promote products derived from
18*1b3f573fSAndroid Build Coastguard Worker# this software without specific prior written permission.
19*1b3f573fSAndroid Build Coastguard Worker#
20*1b3f573fSAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*1b3f573fSAndroid Build Coastguard Worker# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*1b3f573fSAndroid Build Coastguard Worker# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*1b3f573fSAndroid Build Coastguard Worker# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*1b3f573fSAndroid Build Coastguard Worker# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*1b3f573fSAndroid Build Coastguard Worker# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*1b3f573fSAndroid Build Coastguard Worker# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*1b3f573fSAndroid Build Coastguard Worker# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*1b3f573fSAndroid Build Coastguard Worker# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*1b3f573fSAndroid Build Coastguard Worker
32*1b3f573fSAndroid Build Coastguard Worker"""Script to generate a list of all modules to use in autosummary.
33*1b3f573fSAndroid Build Coastguard Worker
34*1b3f573fSAndroid Build Coastguard WorkerThis script creates a ReStructured Text file for each public module in the
35*1b3f573fSAndroid Build Coastguard Workerprotobuf Python package. The script also updates the table of contents in
36*1b3f573fSAndroid Build Coastguard Worker``docs/index.rst`` to point to these module references.
37*1b3f573fSAndroid Build Coastguard Worker
38*1b3f573fSAndroid Build Coastguard WorkerTo build the docs with Sphinx:
39*1b3f573fSAndroid Build Coastguard Worker
40*1b3f573fSAndroid Build Coastguard Worker1. Install the needed packages (``sphinx``, ``sphinxcontrib-napoleon`` for
41*1b3f573fSAndroid Build Coastguard Worker   Google-style docstring support). I've created a conda environment file to
42*1b3f573fSAndroid Build Coastguard Worker   make this easier:
43*1b3f573fSAndroid Build Coastguard Worker
44*1b3f573fSAndroid Build Coastguard Worker.. code:: bash
45*1b3f573fSAndroid Build Coastguard Worker
46*1b3f573fSAndroid Build Coastguard Worker   conda env create -f python/docs/environment.yml
47*1b3f573fSAndroid Build Coastguard Worker
48*1b3f573fSAndroid Build Coastguard Worker2. (Optional) Generate reference docs files and regenerate index:
49*1b3f573fSAndroid Build Coastguard Worker
50*1b3f573fSAndroid Build Coastguard Worker.. code:: bash
51*1b3f573fSAndroid Build Coastguard Worker
52*1b3f573fSAndroid Build Coastguard Worker   cd python/docs
53*1b3f573fSAndroid Build Coastguard Worker   python generate_docs.py
54*1b3f573fSAndroid Build Coastguard Worker
55*1b3f573fSAndroid Build Coastguard Worker3. Run Sphinx.
56*1b3f573fSAndroid Build Coastguard Worker
57*1b3f573fSAndroid Build Coastguard Worker.. code:: bash
58*1b3f573fSAndroid Build Coastguard Worker
59*1b3f573fSAndroid Build Coastguard Worker   make html
60*1b3f573fSAndroid Build Coastguard Worker"""
61*1b3f573fSAndroid Build Coastguard Worker
62*1b3f573fSAndroid Build Coastguard Workerimport pathlib
63*1b3f573fSAndroid Build Coastguard Workerimport re
64*1b3f573fSAndroid Build Coastguard Worker
65*1b3f573fSAndroid Build Coastguard Worker
66*1b3f573fSAndroid Build Coastguard WorkerDOCS_DIR = pathlib.Path(__file__).parent.resolve()
67*1b3f573fSAndroid Build Coastguard WorkerPYTHON_DIR = DOCS_DIR.parent
68*1b3f573fSAndroid Build Coastguard WorkerSOURCE_DIR = PYTHON_DIR / "google" / "protobuf"
69*1b3f573fSAndroid Build Coastguard WorkerSOURCE_POSIX = SOURCE_DIR.as_posix()
70*1b3f573fSAndroid Build Coastguard Worker
71*1b3f573fSAndroid Build Coastguard Worker# Modules which are always included:
72*1b3f573fSAndroid Build Coastguard WorkerINCLUDED_MODULES = (
73*1b3f573fSAndroid Build Coastguard Worker  "google.protobuf.internal.containers",
74*1b3f573fSAndroid Build Coastguard Worker)
75*1b3f573fSAndroid Build Coastguard Worker
76*1b3f573fSAndroid Build Coastguard Worker# Packages to ignore, including all modules (unless in INCLUDED_MODULES):
77*1b3f573fSAndroid Build Coastguard WorkerIGNORED_PACKAGES = (
78*1b3f573fSAndroid Build Coastguard Worker  "compiler",
79*1b3f573fSAndroid Build Coastguard Worker  "docs",
80*1b3f573fSAndroid Build Coastguard Worker  "internal",
81*1b3f573fSAndroid Build Coastguard Worker  "pyext",
82*1b3f573fSAndroid Build Coastguard Worker  "util",
83*1b3f573fSAndroid Build Coastguard Worker)
84*1b3f573fSAndroid Build Coastguard Worker
85*1b3f573fSAndroid Build Coastguard Worker# Ignored module stems in all packages (unless in INCLUDED_MODULES):
86*1b3f573fSAndroid Build Coastguard WorkerIGNORED_MODULES = (
87*1b3f573fSAndroid Build Coastguard Worker  "any_test_pb2",
88*1b3f573fSAndroid Build Coastguard Worker  "api_pb2",
89*1b3f573fSAndroid Build Coastguard Worker  "unittest",
90*1b3f573fSAndroid Build Coastguard Worker  "source_context_pb2",
91*1b3f573fSAndroid Build Coastguard Worker  "test_messages_proto3_pb2",
92*1b3f573fSAndroid Build Coastguard Worker  "test_messages_proto2",
93*1b3f573fSAndroid Build Coastguard Worker)
94*1b3f573fSAndroid Build Coastguard Worker
95*1b3f573fSAndroid Build Coastguard WorkerTOC_REGEX = re.compile(
96*1b3f573fSAndroid Build Coastguard Worker  r"\.\. START REFTOC.*\.\. END REFTOC\.\n",
97*1b3f573fSAndroid Build Coastguard Worker  flags=re.DOTALL,
98*1b3f573fSAndroid Build Coastguard Worker)
99*1b3f573fSAndroid Build Coastguard WorkerTOC_TEMPLATE = """.. START REFTOC, generated by generate_docs.py.
100*1b3f573fSAndroid Build Coastguard Worker.. toctree::
101*1b3f573fSAndroid Build Coastguard Worker
102*1b3f573fSAndroid Build Coastguard Worker   {toctree}
103*1b3f573fSAndroid Build Coastguard Worker
104*1b3f573fSAndroid Build Coastguard Worker.. END REFTOC.
105*1b3f573fSAndroid Build Coastguard Worker"""
106*1b3f573fSAndroid Build Coastguard Worker
107*1b3f573fSAndroid Build Coastguard WorkerAUTOMODULE_TEMPLATE = """.. DO NOT EDIT, generated by generate_docs.py.
108*1b3f573fSAndroid Build Coastguard Worker
109*1b3f573fSAndroid Build Coastguard Worker.. ifconfig:: build_env == 'readthedocs'
110*1b3f573fSAndroid Build Coastguard Worker
111*1b3f573fSAndroid Build Coastguard Worker   .. warning::
112*1b3f573fSAndroid Build Coastguard Worker
113*1b3f573fSAndroid Build Coastguard Worker      You are reading the documentation for the `latest committed changes
114*1b3f573fSAndroid Build Coastguard Worker      <https://github.com/protocolbuffers/protobuf/tree/main/python>`_ of
115*1b3f573fSAndroid Build Coastguard Worker      the `Protocol Buffers package for Python
116*1b3f573fSAndroid Build Coastguard Worker      <https://developers.google.com/protocol-buffers/docs/pythontutorial>`_.
117*1b3f573fSAndroid Build Coastguard Worker      Some features may not yet be released. Read the documentation for the
118*1b3f573fSAndroid Build Coastguard Worker      latest released package at `googleapis.dev
119*1b3f573fSAndroid Build Coastguard Worker      <https://googleapis.dev/python/protobuf/latest/>`_.
120*1b3f573fSAndroid Build Coastguard Worker
121*1b3f573fSAndroid Build Coastguard Worker{module}
122*1b3f573fSAndroid Build Coastguard Worker{underline}
123*1b3f573fSAndroid Build Coastguard Worker
124*1b3f573fSAndroid Build Coastguard Worker.. automodule:: {module}
125*1b3f573fSAndroid Build Coastguard Worker   :members:
126*1b3f573fSAndroid Build Coastguard Worker   :inherited-members:
127*1b3f573fSAndroid Build Coastguard Worker   :undoc-members:
128*1b3f573fSAndroid Build Coastguard Worker"""
129*1b3f573fSAndroid Build Coastguard Worker
130*1b3f573fSAndroid Build Coastguard Worker
131*1b3f573fSAndroid Build Coastguard Workerdef find_modules():
132*1b3f573fSAndroid Build Coastguard Worker  modules = []
133*1b3f573fSAndroid Build Coastguard Worker  for module_path in SOURCE_DIR.glob("**/*.py"):
134*1b3f573fSAndroid Build Coastguard Worker    # Determine the (dotted) relative package and module names.
135*1b3f573fSAndroid Build Coastguard Worker    package_path = module_path.parent.relative_to(PYTHON_DIR)
136*1b3f573fSAndroid Build Coastguard Worker    if package_path == SOURCE_DIR:
137*1b3f573fSAndroid Build Coastguard Worker      package_name = ""
138*1b3f573fSAndroid Build Coastguard Worker      module_name = module_path.stem
139*1b3f573fSAndroid Build Coastguard Worker    else:
140*1b3f573fSAndroid Build Coastguard Worker      package_name = package_path.as_posix().replace("/", ".")
141*1b3f573fSAndroid Build Coastguard Worker      module_name = package_name + "." + module_path.stem
142*1b3f573fSAndroid Build Coastguard Worker
143*1b3f573fSAndroid Build Coastguard Worker    # Filter: first, accept anything in the whitelist; then, reject anything
144*1b3f573fSAndroid Build Coastguard Worker    # at package level, then module name level.
145*1b3f573fSAndroid Build Coastguard Worker    if any(include == module_name for include in INCLUDED_MODULES):
146*1b3f573fSAndroid Build Coastguard Worker      pass
147*1b3f573fSAndroid Build Coastguard Worker    elif any(ignored in package_name for ignored in IGNORED_PACKAGES):
148*1b3f573fSAndroid Build Coastguard Worker      continue
149*1b3f573fSAndroid Build Coastguard Worker    elif any(ignored in module_path.stem for ignored in IGNORED_MODULES):
150*1b3f573fSAndroid Build Coastguard Worker      continue
151*1b3f573fSAndroid Build Coastguard Worker
152*1b3f573fSAndroid Build Coastguard Worker    if module_path.name == "__init__.py":
153*1b3f573fSAndroid Build Coastguard Worker      modules.append(package_name)
154*1b3f573fSAndroid Build Coastguard Worker    else:
155*1b3f573fSAndroid Build Coastguard Worker      modules.append(module_name)
156*1b3f573fSAndroid Build Coastguard Worker
157*1b3f573fSAndroid Build Coastguard Worker  return modules
158*1b3f573fSAndroid Build Coastguard Worker
159*1b3f573fSAndroid Build Coastguard Worker
160*1b3f573fSAndroid Build Coastguard Workerdef write_automodule(module):
161*1b3f573fSAndroid Build Coastguard Worker  contents = AUTOMODULE_TEMPLATE.format(module=module, underline="=" * len(module),)
162*1b3f573fSAndroid Build Coastguard Worker  automodule_path = DOCS_DIR.joinpath(*module.split(".")).with_suffix(".rst")
163*1b3f573fSAndroid Build Coastguard Worker  try:
164*1b3f573fSAndroid Build Coastguard Worker    automodule_path.parent.mkdir(parents=True)
165*1b3f573fSAndroid Build Coastguard Worker  except FileExistsError:
166*1b3f573fSAndroid Build Coastguard Worker    pass
167*1b3f573fSAndroid Build Coastguard Worker  with open(automodule_path, "w") as automodule_file:
168*1b3f573fSAndroid Build Coastguard Worker    automodule_file.write(contents)
169*1b3f573fSAndroid Build Coastguard Worker
170*1b3f573fSAndroid Build Coastguard Worker
171*1b3f573fSAndroid Build Coastguard Workerdef replace_toc(modules):
172*1b3f573fSAndroid Build Coastguard Worker  toctree = [module.replace(".", "/") for module in modules]
173*1b3f573fSAndroid Build Coastguard Worker  with open(DOCS_DIR / "index.rst", "r") as index_file:
174*1b3f573fSAndroid Build Coastguard Worker    index_contents = index_file.read()
175*1b3f573fSAndroid Build Coastguard Worker  toc = TOC_TEMPLATE.format(
176*1b3f573fSAndroid Build Coastguard Worker    toctree="\n   ".join(toctree)
177*1b3f573fSAndroid Build Coastguard Worker  )
178*1b3f573fSAndroid Build Coastguard Worker  index_contents = re.sub(TOC_REGEX, toc, index_contents)
179*1b3f573fSAndroid Build Coastguard Worker  with open(DOCS_DIR / "index.rst", "w") as index_file:
180*1b3f573fSAndroid Build Coastguard Worker    index_file.write(index_contents)
181*1b3f573fSAndroid Build Coastguard Worker
182*1b3f573fSAndroid Build Coastguard Worker
183*1b3f573fSAndroid Build Coastguard Workerdef main():
184*1b3f573fSAndroid Build Coastguard Worker  modules = list(sorted(find_modules()))
185*1b3f573fSAndroid Build Coastguard Worker  for module in modules:
186*1b3f573fSAndroid Build Coastguard Worker    print("Generating reference for {}".format(module))
187*1b3f573fSAndroid Build Coastguard Worker    write_automodule(module)
188*1b3f573fSAndroid Build Coastguard Worker  print("Generating index.rst")
189*1b3f573fSAndroid Build Coastguard Worker  replace_toc(modules)
190*1b3f573fSAndroid Build Coastguard Worker
191*1b3f573fSAndroid Build Coastguard Workerif __name__ == "__main__":
192*1b3f573fSAndroid Build Coastguard Worker    main()
193