Skip to content

Commit 0ee368f

Browse files
committed
feat: populate library version in config
1 parent dafc0fd commit 0ee368f

File tree

2 files changed

+105
-6
lines changed

2 files changed

+105
-6
lines changed

.generator/cli.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,14 +186,50 @@ def _get_new_library_config(request_data: Dict) -> Dict:
186186
return library_config
187187
return {}
188188

189+
def _get_library_version(library_id: str, repo: str) -> str:
190+
"""Gets the library version from its gapic_version.py file.
189191
190-
def _prepare_new_library_config(library_config: Dict) -> Dict:
192+
Args:
193+
library_id(str): The id of the library.
194+
repo(str): The path to the repository.
195+
196+
Returns:
197+
str: The version of the library.
198+
"""
199+
library_path = Path(f"{repo}/packages/{library_id}")
200+
gapic_version_files = list(library_path.rglob("**/gapic_version.py"))
201+
if not gapic_version_files:
202+
raise ValueError(f"Could not find gapic_version.py for {library_id}")
203+
204+
content = _read_text_file(gapic_version_files[0])
205+
match = re.search(r"__version__\s*=\s*[\"']([^\"']+)[\"']", content)
206+
if not match:
207+
raise ValueError(f"Could not extract version from {gapic_version_files[0]}")
208+
return match.group(1)
209+
210+
211+
def _add_new_library_version(
212+
library_config: Dict, library_id: str, repo: str
213+
) -> None:
214+
"""Adds the library version to the configuration if it's not present.
215+
216+
Args:
217+
library_config(Dict): The library configuration.
218+
library_id(str): The id of the library.
219+
repo(str): The path to the repository.
220+
"""
221+
if len(library_config["version"]) == 0:
222+
library_config["version"] = _get_library_version(library_id, repo)
223+
224+
225+
def _prepare_new_library_config(library_config: Dict, repo: str) -> Dict:
191226
"""
192227
Prepares the new library's configuration by removing temporary keys and
193228
adding default values.
194229
195230
Args:
196231
library_config (Dict): The raw library configuration.
232+
repo (str): The path to the repository.
197233
198234
Returns:
199235
Dict: The prepared library configuration.
@@ -209,6 +245,7 @@ def _prepare_new_library_config(library_config: Dict) -> Dict:
209245
_add_new_library_preserve_regex(library_config, library_id)
210246
_add_new_library_remove_regex(library_config, library_id)
211247
_add_new_library_tag_format(library_config)
248+
_add_new_library_version(library_config, library_id, repo)
212249

213250
return library_config
214251

@@ -246,7 +283,7 @@ def handle_configure(
246283
# configure-request.json contains the library definitions.
247284
request_data = _read_json_file(f"{librarian}/{CONFIGURE_REQUEST_FILE}")
248285
new_library_config = _get_new_library_config(request_data)
249-
prepared_config = _prepare_new_library_config(new_library_config)
286+
prepared_config = _prepare_new_library_config(new_library_config, repo)
250287

251288
# Write the new library configuration to configure-response.json.
252289
_write_json_file(f"{librarian}/configure-response.json", prepared_config)

.generator/test_cli.py

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@
4444
_get_library_dist_name,
4545
_get_library_id,
4646
_get_libraries_to_prepare_for_release,
47+
_get_library_version,
4748
_get_new_library_config,
4849
_get_previous_version,
50+
_add_new_library_version,
4951
_prepare_new_library_config,
5052
_process_changelog,
5153
_process_version_file,
@@ -171,6 +173,7 @@ def mock_configure_request_data():
171173
{
172174
"id": "google-cloud-language",
173175
"apis": [{"path": "google/cloud/language/v1", "status": "new"}],
176+
"version": "",
174177
}
175178
]
176179
}
@@ -317,17 +320,19 @@ def test_get_new_library_config_empty_input():
317320
assert config == {}
318321

319322

320-
def test_prepare_new_library_config():
323+
def test_prepare_new_library_config(mocker):
321324
"""Tests the preparation of a new library's configuration."""
325+
mocker.patch("cli._get_library_version", return_value="1.2.3")
322326
raw_config = {
323327
"id": "google-cloud-language",
324328
"apis": [{"path": "google/cloud/language/v1", "status": "new"}],
325329
"source_roots": None,
326330
"preserve_regex": None,
327331
"remove_regex": None,
332+
"version": "",
328333
}
329334

330-
prepared_config = _prepare_new_library_config(raw_config)
335+
prepared_config = _prepare_new_library_config(raw_config, "repo")
331336

332337
# Check that status is removed
333338
assert "status" not in prepared_config["apis"][0]
@@ -336,20 +341,23 @@ def test_prepare_new_library_config():
336341
assert "packages/google-cloud-language/CHANGELOG.md" in prepared_config["preserve_regex"]
337342
assert prepared_config["remove_regex"] == ["packages/google-cloud-language"]
338343
assert prepared_config["tag_format"] == "{{id}}-v{{version}}"
344+
assert prepared_config["version"] == "1.2.3"
339345

340346

341-
def test_prepare_new_library_config_preserves_existing_values():
347+
def test_prepare_new_library_config_preserves_existing_values(mocker):
342348
"""Tests that existing values in the config are not overwritten."""
349+
mocker.patch("cli._get_library_version", return_value="1.2.3")
343350
raw_config = {
344351
"id": "google-cloud-language",
345352
"apis": [{"path": "google/cloud/language/v1", "status": "new"}],
346353
"source_roots": ["packages/google-cloud-language-custom"],
347354
"preserve_regex": ["custom/regex"],
348355
"remove_regex": ["custom/remove"],
349356
"tag_format": "custom-format-{{version}}",
357+
"version": "4.5.6",
350358
}
351359

352-
prepared_config = _prepare_new_library_config(raw_config)
360+
prepared_config = _prepare_new_library_config(raw_config, "repo")
353361

354362
# Check that status is removed
355363
assert "status" not in prepared_config["apis"][0]
@@ -358,6 +366,60 @@ def test_prepare_new_library_config_preserves_existing_values():
358366
assert prepared_config["preserve_regex"] == ["custom/regex"]
359367
assert prepared_config["remove_regex"] == ["custom/remove"]
360368
assert prepared_config["tag_format"] == "custom-format-{{version}}"
369+
assert prepared_config["version"] == "4.5.6"
370+
371+
372+
def test_get_library_version_success(mocker):
373+
"""Tests successful extraction of a version from a file."""
374+
mock_rglob = mocker.patch(
375+
"pathlib.Path.rglob", return_value=[pathlib.Path("repo/gapic_version.py")]
376+
)
377+
mocker.patch("cli._read_text_file", return_value='__version__ = "1.2.3"')
378+
version = _get_library_version("google-cloud-language", "repo")
379+
assert version == "1.2.3"
380+
mock_rglob.assert_called_once_with("**/gapic_version.py")
381+
382+
383+
def test_get_library_version_no_file(mocker):
384+
"""Tests failure when gapic_version.py is not found."""
385+
mocker.patch("pathlib.Path.rglob", return_value=[])
386+
with pytest.raises(ValueError, match="Could not find gapic_version.py"):
387+
_get_library_version("google-cloud-language", "repo")
388+
389+
390+
def test_get_library_version_no_version_in_file(mocker):
391+
"""Tests failure when the version string is not in the file."""
392+
mocker.patch(
393+
"pathlib.Path.rglob", return_value=[pathlib.Path("repo/gapic_version.py")]
394+
)
395+
mocker.patch("cli._read_text_file", return_value="some_other_content = 'foo'")
396+
with pytest.raises(ValueError, match="Could not extract version"):
397+
_get_library_version("google-cloud-language", "repo")
398+
399+
400+
def test_add_new_library_version_populates_version(mocker):
401+
"""Tests that the version is populated if it's missing."""
402+
mock_get_version = mocker.patch("cli._get_library_version", return_value="1.2.3")
403+
config = {"version": ""}
404+
_add_new_library_version(config, "google-cloud-language", "repo")
405+
assert config["version"] == "1.2.3"
406+
mock_get_version.assert_called_once_with("google-cloud-language", "repo")
407+
408+
409+
def test_add_new_library_version_preserves_version():
410+
"""Tests that an existing version is preserved."""
411+
config = {"version": "4.5.6"}
412+
_add_new_library_version(config, "google-cloud-language", "repo")
413+
assert config["version"] == "4.5.6"
414+
415+
416+
def test_add_new_library_version_populates_missing_key(mocker):
417+
"""Tests that the version is populated if the key is missing."""
418+
mock_get_version = mocker.patch("cli._get_library_version", return_value="1.2.3")
419+
config = {} # No 'version' key
420+
_add_new_library_version(config, "google-cloud-language", "repo")
421+
assert config["version"] == "1.2.3"
422+
mock_get_version.assert_called_once_with("google-cloud-language", "repo")
361423

362424

363425
def test_get_library_id_success():

0 commit comments

Comments
 (0)