1# Copyright 2018 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
15from pathlib import Path
16
17from synthtool import _tracked_paths
18from synthtool.gcp import artman
19from synthtool.log import logger
20from synthtool.sources import git
21
22DISCOVERY_ARTIFACT_MANAGER_URL: str = git.make_repo_clone_url(
23    "googleapis/discovery-artifact-manager"
24)
25
26
27class DiscoGAPICGenerator:
28    def __init__(self):
29        self._clone_discovery_artifact_manager()
30
31    def py_library(self, service: str, version: str, **kwargs) -> Path:
32        """
33        Generates the Python Library files using artman/GAPIC
34        returns a `Path` object
35        library: path to library. 'google/cloud/speech'
36        version: version of lib. 'v1'
37        """
38        return self._generate_code(service, version, "python", **kwargs)
39
40    def node_library(self, service: str, version: str, **kwargs) -> Path:
41        return self._generate_code(service, version, "nodejs", **kwargs)
42
43    nodejs_library = node_library
44
45    def ruby_library(self, service: str, version: str, **kwargs) -> Path:
46        return self._generate_code(service, version, "ruby", **kwargs)
47
48    def php_library(self, service: str, version: str, **kwargs) -> Path:
49        return self._generate_code(service, version, "php", **kwargs)
50
51    def java_library(self, service: str, version: str, **kwargs) -> Path:
52        return self._generate_code(service, version, "java", **kwargs)
53
54    def _generate_code(
55        self, service, version, language, config_path=None, artman_output_name=None
56    ):
57        # map the language to the artman argument and subdir of genfiles
58        GENERATE_FLAG_LANGUAGE = {
59            "python": ("python_gapic", "python"),
60            "nodejs": ("nodejs_gapic", "js"),
61            "ruby": ("ruby_gapic", "ruby"),
62            "php": ("php_gapic", "php"),
63            "java": ("java_discogapic", "java"),
64        }
65
66        if language not in GENERATE_FLAG_LANGUAGE:
67            raise ValueError("provided language unsupported")
68
69        gapic_language_arg, gen_language = GENERATE_FLAG_LANGUAGE[language]
70
71        if self.discovery_artifact_manager is None:
72            raise RuntimeError(
73                f"Unable to generate {config_path}, the googleapis repository"
74                "is unavailable."
75            )
76
77        # Run the code generator.
78        # $ artman --config path/to/artman_api.yaml generate python_gapic
79        if config_path is None:
80            config_path = (
81                Path("gapic/google") / service / f"artman_{service}_{version}.yaml"
82            )
83        elif Path(config_path).is_absolute():
84            config_path = Path(config_path).relative_to("/")
85        else:
86            config_path = Path("gapic/google") / service / Path(config_path)
87
88        if not (self.discovery_artifact_manager / config_path).exists():
89            raise FileNotFoundError(
90                f"Unable to find configuration yaml file: {config_path}."
91            )
92
93        logger.debug(f"Running generator for {config_path}.")
94        output_root = artman.Artman().run(
95            f"googleapis/artman:{artman.ARTMAN_VERSION}",
96            self.discovery_artifact_manager,
97            config_path,
98            gapic_language_arg,
99        )
100
101        # Expect the output to be in the artman-genfiles directory.
102        # example: /artman-genfiles/python/speech-v1
103        if artman_output_name is None:
104            artman_output_name = f"{service}-{version}"
105        genfiles = output_root / gen_language / artman_output_name
106
107        if not genfiles.exists():
108            raise FileNotFoundError(
109                f"Unable to find generated output of artman: {genfiles}."
110            )
111
112        logger.success(f"Generated code into {genfiles}.")
113
114        _tracked_paths.add(genfiles)
115        return genfiles
116
117    def _clone_discovery_artifact_manager(self):
118        logger.debug("Cloning discovery-artifact-manager.")
119        self.discovery_artifact_manager = git.clone(DISCOVERY_ARTIFACT_MANAGER_URL)
120