Skip to content

Commit c1e5e1c

Browse files
authored
chore(python): autogenerate docs/index.rst (#1114)
* chore(python): autogenerate docs/index.rst * set default path to owl-bot-staging * optimize code using glob * move the default_version to the front of the list * Drop redundant default_version argument * remove unused imports * read default_version from .repo-metadata.json * exclude docs/index.rst if default_version is not specified * check for versions kwarg * only generate docs/index.rst if default_version is specified * lint * fix build * fix build * consolidate the duplicated detect_versions function * remove unused import * remove unused imports * update comments * remove unused import * run black
1 parent b0535a7 commit c1e5e1c

5 files changed

Lines changed: 190 additions & 79 deletions

File tree

synthtool/gcp/common.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,15 @@ def py_library(self, **kwargs) -> Path:
209209
# kwargs["metadata"] is required to load values from .repo-metadata.json
210210
if "metadata" not in kwargs:
211211
kwargs["metadata"] = {}
212-
# rename variable to accomodate existing synth.py files
212+
213+
# load common repo meta information (metadata that's not language specific).
214+
self._load_generic_metadata(kwargs["metadata"])
215+
216+
# initialize default_version if it doesn't exist in kwargs["metadata"]['repo']
217+
if "default_version" not in kwargs["metadata"]["repo"]:
218+
kwargs["metadata"]["repo"]["default_version"] = ""
219+
220+
# rename variable to accommodate existing owlbot.py files
213221
if "system_test_dependencies" in kwargs:
214222
kwargs["system_test_local_dependencies"] = kwargs[
215223
"system_test_dependencies"
@@ -237,6 +245,13 @@ def py_library(self, **kwargs) -> Path:
237245
if "samples" not in kwargs:
238246
self.excludes += ["samples/AUTHORING_GUIDE.md", "samples/CONTRIBUTING.md"]
239247

248+
# Don't add `docs/index.rst` if `versions` is not provided or `default_version` is empty
249+
if (
250+
"versions" not in kwargs
251+
or not kwargs["metadata"]["repo"]["default_version"]
252+
):
253+
self.excludes += ["docs/index.rst"]
254+
240255
# Assume the python-docs-samples Dockerfile is used for samples by default
241256
if "custom_samples_dockerfile" not in kwargs:
242257
kwargs["custom_samples_dockerfile"] = False
@@ -323,6 +338,69 @@ def _load_generic_metadata(self, metadata: Dict):
323338
metadata["repo"] = _load_repo_metadata()
324339

325340

341+
def detect_versions(
342+
path: str = "./src",
343+
default_version: Optional[str] = None,
344+
default_first: Optional[bool] = None,
345+
) -> List[str]:
346+
"""
347+
Detects the versions a library has, based on distinct folders
348+
within path. This is based on the fact that our GAPIC libraries are
349+
structured as follows:
350+
351+
src/v1
352+
src/v1beta
353+
src/v1alpha
354+
355+
With folder names mapping directly to versions.
356+
357+
Returns: a list of the sorted subdirectories; for the example above:
358+
['v1', 'v1alpha', 'v1beta']
359+
If the `default_version` argument is not provided, the `default_version`
360+
will be read from `.repo-metadata.json`, if it exists.
361+
If `default_version` is available, the `default_version` is moved to
362+
at the front or the end of the sorted list depending on the value of `default_first`.
363+
The `default_version` will be first in the list when `default_first` is `True`.
364+
"""
365+
366+
versions = []
367+
368+
if not default_version:
369+
try:
370+
# Get the `default_version` from ``.repo-metadata.json`.
371+
default_version = json.load(open(".repo-metadata.json", "rt")).get(
372+
"default_version"
373+
)
374+
except FileNotFoundError:
375+
pass
376+
377+
# Sort the sub directories alphabetically.
378+
sub_dirs = sorted([p.name for p in Path(path).glob("*v[1-9]*")])
379+
380+
if sub_dirs:
381+
# if `default_version` is not specified, return the sorted directories.
382+
if not default_version:
383+
versions = sub_dirs
384+
else:
385+
# The subdirectory with the same suffix as the default_version
386+
# will be the default client.
387+
default_client = next(
388+
iter([d for d in sub_dirs if d.endswith(default_version)]), None
389+
)
390+
391+
# start with all the versions except for the default client
392+
versions = [d for d in sub_dirs if not d.endswith(default_version)]
393+
394+
if default_client:
395+
# If `default_first` is true, the default_client will be first
396+
# in the list.
397+
if default_first:
398+
versions = [default_client] + versions
399+
else:
400+
versions += [default_client]
401+
return versions
402+
403+
326404
def decamelize(value: str):
327405
""" parser to convert fooBar.js to Foo Bar. """
328406
if not value:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.. include:: README.rst
2+
3+
.. include:: multiprocessing.rst
4+
{% if versions|length > 1 %}
5+
This package includes clients for multiple versions of {{ metadata['repo']['name_pretty'] }}.
6+
By default, you will get version ``{{ versions | first }}``.
7+
{% endif %}
8+
{% for version in versions %}
9+
API Reference
10+
-------------
11+
.. toctree::
12+
:maxdepth: 2
13+
14+
{{ version }}/services
15+
{{ version }}/types
16+
{% endfor %}
17+
{%- if migration_guide_version %}
18+
Migration Guide
19+
---------------
20+
21+
See the guide below for instructions on migrating to the {{ migration_guide_version }} release of this library.
22+
23+
.. toctree::
24+
:maxdepth: 2
25+
26+
UPGRADING
27+
{% endif %}
28+
Changelog
29+
---------
30+
31+
For a list of all ``{{ metadata['repo']['distribution_name'] }}`` releases:
32+
33+
.. toctree::
34+
:maxdepth: 2
35+
36+
changelog

synthtool/languages/node.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import json
1616
from jinja2 import FileSystemLoader, Environment
1717
from pathlib import Path
18-
import os
1918
import re
2019
from synthtool import _tracked_paths, gcp, shell, transforms
2120
from synthtool.gcp import samples, snippets
@@ -214,36 +213,6 @@ def compile_protos(hide_output=False):
214213
shell.run(["npx", "compileProtos", "src"], hide_output=hide_output)
215214

216215

217-
def detect_versions(
218-
path: str = "./src", default_version: Optional[str] = None
219-
) -> List[str]:
220-
"""
221-
Detects the versions a library has, based on distinct folders
222-
within path. This is based on the fact that our GAPIC libraries are
223-
structured as follows:
224-
225-
src/v1
226-
src/v1beta
227-
src/v1alpha
228-
229-
With folder names mapping directly to versions.
230-
231-
Returns: a list of the subdirectories; for the example above:
232-
['v1', 'v1alpha', 'v1beta']
233-
If specified, the default_version is guaranteed to be listed last.
234-
Otherwise, the list is sorted alphabetically.
235-
"""
236-
versions = []
237-
if os.path.isdir(path):
238-
for directory in os.listdir(path):
239-
if os.path.isdir(os.path.join(path, directory)):
240-
versions.append(directory)
241-
versions.sort()
242-
if default_version is not None:
243-
versions = [v for v in versions if v != default_version] + [default_version]
244-
return versions
245-
246-
247216
def compile_protos_hermetic(hide_output=False):
248217
"""
249218
Compiles protos into .json, .js, and .d.ts files using

tests/test_common.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import json
1516
import os
1617
import tempfile
1718
from pathlib import Path
@@ -20,7 +21,7 @@
2021
from pytest import raises
2122

2223
import synthtool as s
23-
from synthtool.gcp.common import _get_default_branch_name, decamelize
24+
from synthtool.gcp.common import _get_default_branch_name, decamelize, detect_versions
2425

2526
from . import util
2627

@@ -159,3 +160,76 @@ def test_py_samples_multiple_override_content():
159160
with open("README.md") as f:
160161
result = f.read()
161162
assert "Last Example" in result
163+
164+
165+
def test_detect_versions_src():
166+
temp_dir = Path(tempfile.mkdtemp())
167+
src_dir = temp_dir / "src"
168+
for v in ("v1", "v2", "v3"):
169+
os.makedirs(src_dir / v)
170+
171+
with util.chdir(temp_dir):
172+
versions = detect_versions()
173+
assert ["v1", "v2", "v3"] == versions
174+
175+
176+
def test_detect_versions_staging():
177+
temp_dir = Path(tempfile.mkdtemp())
178+
staging_dir = temp_dir / "owl-bot-staging"
179+
for v in ("v1", "v2", "v3"):
180+
os.makedirs(staging_dir / v)
181+
182+
versions = detect_versions(staging_dir)
183+
assert ["v1", "v2", "v3"] == versions
184+
185+
186+
def test_detect_versions_dir_not_found():
187+
temp_dir = Path(tempfile.mkdtemp())
188+
189+
versions = detect_versions(temp_dir / "does-not-exist")
190+
assert [] == versions
191+
192+
193+
def test_detect_versions_with_default_version():
194+
temp_dir = Path(tempfile.mkdtemp())
195+
src_dir = temp_dir / "src"
196+
vs = ("v1", "v2", "v3")
197+
for v in vs:
198+
os.makedirs(src_dir / v)
199+
200+
with util.chdir(temp_dir):
201+
versions = detect_versions(default_version="v1")
202+
assert ["v2", "v3", "v1"] == versions
203+
versions = detect_versions(default_version="v2")
204+
assert ["v1", "v3", "v2"] == versions
205+
versions = detect_versions(default_version="v3")
206+
assert ["v1", "v2", "v3"] == versions
207+
208+
209+
def test_detect_versions_with_default_version_from_metadata():
210+
temp_dir = Path(tempfile.mkdtemp())
211+
default_dir = temp_dir / "src"
212+
for v in ("api_v1", "api_v2", "api_v3"):
213+
os.makedirs(default_dir / v)
214+
215+
with util.chdir(temp_dir):
216+
# Set default_version to "api_v1"
217+
test_json = {"default_version": "api_v1"}
218+
with open(".repo-metadata.json", "w") as metadata:
219+
json.dump(test_json, metadata)
220+
versions = detect_versions(default_first=True)
221+
assert ["api_v1", "api_v2", "api_v3"] == versions
222+
223+
# Set default_version to "api_v2"
224+
test_json = {"default_version": "api_v2"}
225+
with open(".repo-metadata.json", "w") as metadata:
226+
json.dump(test_json, metadata)
227+
versions = detect_versions(default_first=True)
228+
assert ["api_v2", "api_v1", "api_v3"] == versions
229+
230+
# Set default_version to "api_v3"
231+
test_json = {"default_version": "api_v3"}
232+
with open(".repo-metadata.json", "w") as metadata:
233+
json.dump(test_json, metadata)
234+
versions = detect_versions(default_first=True)
235+
assert ["api_v3", "api_v1", "api_v2"] == versions

tests/test_node.py

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
# limitations under the License.
1414

1515
import filecmp
16-
import os
1716
import pathlib
18-
import tempfile
1917
from pathlib import Path
2018
from unittest import TestCase
2119
from unittest.mock import patch
@@ -272,47 +270,3 @@ def patch(library: Path):
272270
assert "import * as v2" in staging_text
273271
assert "export * as v2" not in staging_text
274272
assert "export * as v2" in text
275-
276-
277-
def test_detect_versions_src():
278-
temp_dir = Path(tempfile.mkdtemp())
279-
src_dir = temp_dir / "src"
280-
for v in ("v1", "v2", "v3"):
281-
os.makedirs(src_dir / v)
282-
283-
with util.chdir(temp_dir):
284-
versions = node.detect_versions()
285-
assert ["v1", "v2", "v3"] == versions
286-
287-
288-
def test_detect_versions_staging():
289-
temp_dir = Path(tempfile.mkdtemp())
290-
staging_dir = temp_dir / "owl-bot-staging"
291-
for v in ("v1", "v2", "v3"):
292-
os.makedirs(staging_dir / v)
293-
294-
versions = node.detect_versions(staging_dir)
295-
assert ["v1", "v2", "v3"] == versions
296-
297-
298-
def test_detect_versions_dir_not_found():
299-
temp_dir = Path(tempfile.mkdtemp())
300-
301-
versions = node.detect_versions(temp_dir / "does-not-exist")
302-
assert [] == versions
303-
304-
305-
def test_detect_versions_with_default():
306-
temp_dir = Path(tempfile.mkdtemp())
307-
src_dir = temp_dir / "src"
308-
vs = ("v1", "v2", "v3")
309-
for v in vs:
310-
os.makedirs(src_dir / v)
311-
312-
with util.chdir(temp_dir):
313-
versions = node.detect_versions(default_version="v1")
314-
assert ["v2", "v3", "v1"] == versions
315-
versions = node.detect_versions(default_version="v2")
316-
assert ["v1", "v3", "v2"] == versions
317-
versions = node.detect_versions(default_version="v3")
318-
assert ["v1", "v2", "v3"] == versions

0 commit comments

Comments
 (0)