Skip to content

Commit 510a887

Browse files
authored
chore: refactor utility functions (#2557)
In this PR: - Code Refactor - Refactor pom generation functions to a separate file. - Refactor monorepo post processing functions to a separate file. - Refactor unit tests to separate files. - Expose CLI tool used in google-cloud-java - Generate root pom.xml - Generate gapic-libraries-bom/pom.xml To use these tools in google-cloud-java (through docker container): ``` python library_generation/cli/generate_monorepo_root_pom.py generate --repository-path=. python library_generation/cli/generate_monorepo_gapic_bom.py generate --repository-path=. --versions-file=./versions.txt ```
1 parent 30eb2a2 commit 510a887

11 files changed

+431
-222
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import click as click
15+
16+
from library_generation.utils.pom_generator import generate_gapic_bom
17+
from library_generation.utils.pom_generator import generate_root_pom
18+
19+
20+
@click.group(invoke_without_command=False)
21+
@click.pass_context
22+
@click.version_option(message="%(version)s")
23+
def main(ctx):
24+
pass
25+
26+
27+
@main.command()
28+
@click.option(
29+
"--repository-path",
30+
required=True,
31+
type=str,
32+
help="""
33+
Path to which the generated pom.xml goes.
34+
""",
35+
)
36+
@click.option(
37+
"--versions-file",
38+
required=True,
39+
type=str,
40+
help="""
41+
The file containing version of libraries.
42+
Throw FileNotFoundError if the file doesn't exist.
43+
""",
44+
)
45+
def generate(repository_path: str, versions_file: str) -> None:
46+
generate_gapic_bom(repository_path=repository_path, versions_file=versions_file)
47+
48+
49+
if __name__ == "__main__":
50+
main()
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import click as click
15+
from library_generation.utils.pom_generator import generate_root_pom
16+
17+
18+
@click.group(invoke_without_command=False)
19+
@click.pass_context
20+
@click.version_option(message="%(version)s")
21+
def main(ctx):
22+
pass
23+
24+
25+
@main.command()
26+
@click.option(
27+
"--repository-path",
28+
required=True,
29+
type=str,
30+
help="""
31+
Path to which the generated pom.xml goes.
32+
""",
33+
)
34+
def generate(repository_path: str) -> None:
35+
generate_root_pom(repository_path=repository_path)
36+
37+
38+
if __name__ == "__main__":
39+
main()

library_generation/generate_repo.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import os
1919
from library_generation.generate_composed_library import generate_composed_library
2020
from library_generation.model.generation_config import from_yaml
21+
from library_generation.utils.monorepo_postprocessor import monorepo_postprocessing
2122

2223

2324
@click.group(invoke_without_command=False)
@@ -112,7 +113,7 @@ def generate_from_yaml(
112113
if not config.is_monorepo:
113114
return
114115

115-
util.monorepo_postprocessing(
116+
monorepo_postprocessing(
116117
repository_path=repository_path, versions_file=repo_config.versions_file
117118
)
118119

library_generation/test/test_utils.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import unittest
15+
from difflib import unified_diff
16+
from pathlib import Path
17+
18+
from typing import List
19+
20+
21+
class FileComparator(unittest.TestCase):
22+
def compare_files(self, expect: str, actual: str):
23+
with open(expect, "r") as f:
24+
expected_lines = f.readlines()
25+
with open(actual, "r") as f:
26+
actual_lines = f.readlines()
27+
28+
diff = list(unified_diff(expected_lines, actual_lines))
29+
self.assertEqual(
30+
first=[], second=diff, msg="Unexpected file contents:\n" + "".join(diff)
31+
)
32+
33+
34+
def cleanup(files: List[str]):
35+
for file in files:
36+
path = Path(file).resolve()
37+
if path.is_file():
38+
path.unlink()
39+
elif path.is_dir():
40+
path.rmdir()

library_generation/test/unit_tests.py renamed to library_generation/test/utilities_unit_tests.py

Lines changed: 10 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,23 @@
2121
import io
2222
import contextlib
2323
from pathlib import Path
24-
from difflib import unified_diff
25-
26-
from typing import List
2724
from parameterized import parameterized
2825
from library_generation import utilities as util
2926
from library_generation.model.gapic_config import GapicConfig
3027
from library_generation.model.generation_config import GenerationConfig
3128
from library_generation.model.gapic_inputs import parse as parse_build_file
3229
from library_generation.model.generation_config import from_yaml
3330
from library_generation.model.library_config import LibraryConfig
31+
from library_generation.test.test_utils import FileComparator
32+
from library_generation.test.test_utils import cleanup
3433
from library_generation.utilities import find_versioned_proto_path
3534
from library_generation.utilities import get_file_paths
3635

3736
script_dir = os.path.dirname(os.path.realpath(__file__))
3837
resources_dir = os.path.join(script_dir, "resources")
3938
build_file = Path(os.path.join(resources_dir, "misc")).resolve()
4039
test_config_dir = Path(os.path.join(resources_dir, "test-config")).resolve()
40+
file_comparator = FileComparator()
4141
library_1 = LibraryConfig(
4242
api_shortname="baremetalsolution",
4343
name_pretty="Bare Metal Solution",
@@ -391,18 +391,6 @@ def test_remove_version_from_returns_self(self):
391391
"google/cloud/aiplatform", util.remove_version_from(proto_path)
392392
)
393393

394-
def test_get_version_from_returns_current(self):
395-
versions_file = f"{resources_dir}/misc/versions.txt"
396-
artifact = "gax-grpc"
397-
self.assertEqual(
398-
"2.33.1-SNAPSHOT", util.get_version_from(versions_file, artifact)
399-
)
400-
401-
def test_get_version_from_returns_released(self):
402-
versions_file = f"{resources_dir}/misc/versions.txt"
403-
artifact = "gax-grpc"
404-
self.assertEqual("2.34.0", util.get_version_from(versions_file, artifact, True))
405-
406394
def test_get_library_returns_library_name(self):
407395
self.assertEqual("bare-metal-solution", util.get_library_name(library_1))
408396

@@ -414,32 +402,32 @@ def test_generate_prerequisite_files_non_monorepo_success(self):
414402
num_libraries=1, library_type="GAPIC_COMBO"
415403
)
416404

417-
self.__compare_files(
405+
file_comparator.compare_files(
418406
f"{library_path}/.repo-metadata.json",
419407
f"{library_path}/.repo-metadata-non-monorepo-golden.json",
420408
)
421409
# since this is a single library, we treat this as HW repository,
422410
# meaning that the owlbot yaml will be inside a .github folder
423-
self.__compare_files(
411+
file_comparator.compare_files(
424412
f"{library_path}/.github/.OwlBot.yaml",
425413
f"{library_path}/.OwlBot-golden.yaml",
426414
)
427-
self.__compare_files(
415+
file_comparator.compare_files(
428416
f"{library_path}/owlbot.py", f"{library_path}/owlbot-golden.py"
429417
)
430418

431419
def test_generate_prerequisite_files_monorepo_success(self):
432420
library_path = self.__setup_prerequisite_files(num_libraries=2)
433421

434-
self.__compare_files(
422+
file_comparator.compare_files(
435423
f"{library_path}/.repo-metadata.json",
436424
f"{library_path}/.repo-metadata-monorepo-golden.json",
437425
)
438-
self.__compare_files(
426+
file_comparator.compare_files(
439427
f"{library_path}/.OwlBot.yaml",
440428
f"{library_path}/.OwlBot-golden.yaml",
441429
)
442-
self.__compare_files(
430+
file_comparator.compare_files(
443431
f"{library_path}/owlbot.py", f"{library_path}/owlbot-golden.py"
444432
)
445433

@@ -488,37 +476,6 @@ def test_prepare_repo_split_repo_success(self):
488476
library_path = sorted([Path(key).name for key in repo_config.libraries])
489477
self.assertEqual(["misc"], library_path)
490478

491-
def test_monorepo_postprocessing_valid_repository_success(self):
492-
repository_path = f"{resources_dir}/test_monorepo_postprocessing"
493-
versions_file = f"{repository_path}/versions.txt"
494-
files = [
495-
f"{repository_path}/pom.xml",
496-
f"{repository_path}/gapic-libraries-bom/pom.xml",
497-
]
498-
self.__cleanup(files)
499-
util.monorepo_postprocessing(
500-
repository_path=repository_path, versions_file=versions_file
501-
)
502-
self.__compare_files(
503-
expect=f"{repository_path}/pom-golden.xml",
504-
actual=f"{repository_path}/pom.xml",
505-
)
506-
self.__compare_files(
507-
expect=f"{repository_path}/gapic-libraries-bom/pom-golden.xml",
508-
actual=f"{repository_path}/gapic-libraries-bom/pom.xml",
509-
)
510-
511-
def __compare_files(self, expect: str, actual: str):
512-
with open(expect, "r") as f:
513-
expected_lines = f.readlines()
514-
with open(actual, "r") as f:
515-
actual_lines = f.readlines()
516-
517-
diff = list(unified_diff(expected_lines, actual_lines))
518-
self.assertEqual(
519-
first=[], second=diff, msg="Unexpected file contents:\n" + "".join(diff)
520-
)
521-
522479
def __setup_prerequisite_files(
523480
self, num_libraries: int, library_type: str = "GAPIC_AUTO"
524481
) -> str:
@@ -528,7 +485,7 @@ def __setup_prerequisite_files(
528485
f"{library_path}/.OwlBot.yaml",
529486
f"{library_path}/owlbot.py",
530487
]
531-
self.__cleanup(files)
488+
cleanup(files)
532489
config = self.__get_a_gen_config(num_libraries, library_type=library_type)
533490
proto_path = "google/cloud/baremetalsolution/v2"
534491
transport = "grpc"
@@ -593,15 +550,6 @@ def __get_a_gen_config(
593550
libraries=libraries,
594551
)
595552

596-
@staticmethod
597-
def __cleanup(files: List[str]):
598-
for file in files:
599-
path = Path(file).resolve()
600-
if path.is_file():
601-
path.unlink()
602-
elif path.is_dir():
603-
path.rmdir()
604-
605553

606554
if __name__ == "__main__":
607555
unittest.main()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
import unittest
16+
17+
from library_generation.test.test_utils import FileComparator
18+
from library_generation.test.test_utils import cleanup
19+
from library_generation.utils.monorepo_postprocessor import monorepo_postprocessing
20+
21+
script_dir = os.path.dirname(os.path.realpath(__file__))
22+
resources_dir = os.path.join(script_dir, "..", "resources")
23+
file_comparator = FileComparator()
24+
25+
26+
class MonorepoPostprocessorTest(unittest.TestCase):
27+
def test_monorepo_postprocessing_valid_repository_success(self):
28+
repository_path = f"{resources_dir}/test_monorepo_postprocessing"
29+
versions_file = f"{repository_path}/versions.txt"
30+
files = [
31+
f"{repository_path}/pom.xml",
32+
f"{repository_path}/gapic-libraries-bom/pom.xml",
33+
]
34+
cleanup(files)
35+
monorepo_postprocessing(
36+
repository_path=repository_path, versions_file=versions_file
37+
)
38+
file_comparator.compare_files(
39+
expect=f"{repository_path}/pom-golden.xml",
40+
actual=f"{repository_path}/pom.xml",
41+
)
42+
file_comparator.compare_files(
43+
expect=f"{repository_path}/gapic-libraries-bom/pom-golden.xml",
44+
actual=f"{repository_path}/gapic-libraries-bom/pom.xml",
45+
)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
import os
15+
import unittest
16+
17+
from library_generation.utils.pom_generator import get_version_from
18+
19+
script_dir = os.path.dirname(os.path.realpath(__file__))
20+
resources_dir = os.path.join(script_dir, "..", "resources")
21+
22+
23+
class PomGeneratorTest(unittest.TestCase):
24+
def test_get_version_from_returns_current(self):
25+
versions_file = f"{resources_dir}/misc/versions.txt"
26+
artifact = "gax-grpc"
27+
self.assertEqual("2.33.1-SNAPSHOT", get_version_from(versions_file, artifact))
28+
29+
def test_get_version_from_returns_released(self):
30+
versions_file = f"{resources_dir}/misc/versions.txt"
31+
artifact = "gax-grpc"
32+
self.assertEqual("2.34.0", get_version_from(versions_file, artifact, True))

0 commit comments

Comments
 (0)