Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 60 additions & 2 deletions .generator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import subprocess
import sys
import tempfile
import textwrap
import yaml
from datetime import datetime
from pathlib import Path
Expand Down Expand Up @@ -223,12 +224,68 @@ def _prepare_new_library_config(library_config: Dict) -> Dict:
return library_config


def _update_docs_index_rst(output: str, new_library_config: Dict):
"""Creates or updates the docs/index.rst file for a library.

If the file does not exist, it will be created. If it exists, a new
API reference section will be appended.

Args:
output(str): Path to the directory where code should be generated.
new_library_config(Dict): The configuration of the new library.
"""
library_id = _get_library_id(new_library_config)
# a library can have multiple apis, but we'll use the first one to get the version
api_version = Path(new_library_config["apis"][0]["path"]).name.replace("_", "-")
docs_dir = Path(output) / "packages" / library_id / "docs"
os.makedirs(docs_dir, exist_ok=True)
index_rst_path = docs_dir / "index.rst"

new_api_reference = textwrap.dedent(f"""\
API Reference
-------------
.. toctree::
:maxdepth: 2

{api_version}/services
{api_version}/types
""")

if not index_rst_path.exists():
content = textwrap.dedent(f"""\
.. include:: README.rst

.. include:: multiprocessing.rst

{new_api_reference}

Changelog
---------

For a list of all ``{library_id}`` releases:

.. toctree::
:maxdepth: 2

CHANGELOG
""")
_write_text_file(str(index_rst_path), content)
else:
content = _read_text_file(str(index_rst_path))
# a changelog is guaranteed to exist
changelog_section = "Changelog\n---------"
parts = content.split(changelog_section)
# insert api reference before the changelog
# The prepended newline is important for formatting.
content = parts[0] + "\n" + new_api_reference + changelog_section + parts[1]
_write_text_file(str(index_rst_path), content)

def handle_configure(
librarian: str = LIBRARIAN_DIR,
source: str = SOURCE_DIR,
repo: str = REPO_DIR,
input: str = INPUT_DIR,
output: str = OUTPUT_DIR
output: str = OUTPUT_DIR,
):
"""Onboards a new library by completing its configuration.

Expand Down Expand Up @@ -259,13 +316,14 @@ def handle_configure(
# configure-request.json contains the library definitions.
request_data = _read_json_file(f"{librarian}/{CONFIGURE_REQUEST_FILE}")
new_library_config = _get_new_library_config(request_data)

_update_global_changelog(
f"{repo}/CHANGELOG.md",
f"{output}/CHANGELOG.md",
[new_library_config],
)
prepared_config = _prepare_new_library_config(new_library_config)
_update_docs_index_rst(output, new_library_config)

# Write the new library configuration to configure-response.json.
_write_json_file(f"{librarian}/configure-response.json", prepared_config)
Expand Down
49 changes: 49 additions & 0 deletions .generator/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
_stage_gapic_library,
_stage_proto_only_library,
_update_changelog_for_library,
_update_docs_index_rst,
_update_global_changelog,
_update_version_for_library,
_verify_library_dist_name,
Expand Down Expand Up @@ -1514,3 +1515,51 @@ def test_stage_gapic_library(mocker):
mock_shutil_copytree.assert_called_once_with(
tmp_dir, staging_dir, dirs_exist_ok=True
)


class TestUpdateDocsIndexRst:
@pytest.fixture
def mock_new_library_config(self):
return {
"id": "google-cloud-test",
"apis": [{"path": "google/cloud/test/v1"}],
}

def test_creates_new_file_when_not_exists(
self, mocker, mock_new_library_config
):
mocker.patch("os.makedirs")
mock_path_exists = mocker.patch("pathlib.Path.exists", return_value=False)
mock_write_text_file = mocker.patch("cli._write_text_file")

_update_docs_index_rst("output", mock_new_library_config)

mock_path_exists.assert_called_once()
mock_write_text_file.assert_called_once()
# Verify that the content contains the expected sections
written_content = mock_write_text_file.call_args[0][1]
assert "API Reference" in written_content
assert "v1/services" in written_content
assert "Changelog" in written_content

def test_updates_existing_file(self, mocker, mock_new_library_config):
mocker.patch("os.makedirs")
mock_path_exists = mocker.patch("pathlib.Path.exists", return_value=True)
mock_read_text_file = mocker.patch(
"cli._read_text_file",
return_value=".. include:: README.rst\n\nChangelog\n---------",
)
mock_write_text_file = mocker.patch("cli._write_text_file")

_update_docs_index_rst("output", mock_new_library_config)

mock_path_exists.assert_called_once()
mock_read_text_file.assert_called_once()
mock_write_text_file.assert_called_once()
# Verify that the new API reference is inserted before the changelog
written_content = mock_write_text_file.call_args[0][1]
assert "API Reference" in written_content
assert "v1/services" in written_content
assert written_content.find("API Reference") < written_content.find(
"Changelog"
)
Loading
Loading