32 """Script to generate a list of all modules to use in autosummary. 
   34 This script creates a ReStructured Text file for each public module in the 
   35 protobuf Python package. The script also updates the table of contents in 
   36 ``docs/index.rst`` to point to these module references. 
   38 To build the docs with Sphinx: 
   40 1. Install the needed packages (``sphinx``, ``sphinxcontrib-napoleon`` for 
   41    Google-style docstring support). I've created a conda environment file to 
   46    conda env create -f python/docs/environment.yml 
   48 2. (Optional) Generate reference docs files and regenerate index: 
   53    python generate_docs.py 
   66 DOCS_DIR = pathlib.Path(__file__).parent.resolve()
 
   67 PYTHON_DIR = DOCS_DIR.parent
 
   68 SOURCE_DIR = PYTHON_DIR / 
"google" / 
"protobuf" 
   69 SOURCE_POSIX = SOURCE_DIR.as_posix()
 
   73   "google.protobuf.internal.containers",
 
   91   "test_messages_proto3_pb2",
 
   92   "test_messages_proto2",
 
   95 TOC_REGEX = re.compile(
 
   96   r"\.\. START REFTOC.*\.\. END REFTOC\.\n",
 
   99 TOC_TEMPLATE = 
""".. START REFTOC, generated by generate_docs.py. 
  107 AUTOMODULE_TEMPLATE = 
""".. DO NOT EDIT, generated by generate_docs.py. 
  109 .. ifconfig:: build_env == 'readthedocs' 
  113       You are reading the documentation for the `latest committed changes 
  114       <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of 
  115       the `Protocol Buffers package for Python 
  116       <https://developers.google.com/protocol-buffers/docs/pythontutorial>`_. 
  117       Some features may not yet be released. Read the documentation for the 
  118       latest released package at `googleapis.dev 
  119       <https://googleapis.dev/python/protobuf/latest/>`_. 
  124 .. automodule:: {module} 
  133   for module_path 
in SOURCE_DIR.glob(
"**/*.py"):
 
  135     package_path = module_path.parent.relative_to(PYTHON_DIR)
 
  136     if package_path == SOURCE_DIR:
 
  138       module_name = module_path.stem
 
  140       package_name = package_path.as_posix().replace(
"/", 
".")
 
  141       module_name = package_name + 
"." + module_path.stem
 
  145     if any(include == module_name 
for include 
in INCLUDED_MODULES):
 
  147     elif any(ignored 
in package_name 
for ignored 
in IGNORED_PACKAGES):
 
  149     elif any(ignored 
in module_path.stem 
for ignored 
in IGNORED_MODULES):
 
  152     if module_path.name == 
"__init__.py":
 
  153       modules.append(package_name)
 
  155       modules.append(module_name)
 
  161   contents = AUTOMODULE_TEMPLATE.format(module=module, underline=
"=" * 
len(module),)
 
  162   automodule_path = DOCS_DIR.joinpath(*module.split(
".")).with_suffix(
".rst")
 
  164     automodule_path.parent.mkdir(parents=
True)
 
  165   except FileExistsError:
 
  167   with open(automodule_path, 
"w") 
as automodule_file:
 
  168     automodule_file.write(contents)
 
  172   toctree = [module.replace(
".", 
"/") 
for module 
in modules]
 
  173   with open(DOCS_DIR / 
"index.rst", 
"r") 
as index_file:
 
  174     index_contents = index_file.read()
 
  175   toc = TOC_TEMPLATE.format(
 
  176     toctree=
"\n   ".join(toctree)
 
  178   index_contents = re.sub(TOC_REGEX, toc, index_contents)
 
  179   with open(DOCS_DIR / 
"index.rst", 
"w") 
as index_file:
 
  180     index_file.write(index_contents)
 
  185   for module 
in modules:
 
  186     print(
"Generating reference for {}".
format(module))
 
  188   print(
"Generating index.rst")
 
  191 if __name__ == 
"__main__":