diff --git a/src/google/adk/cli/utils/gcp_utils.py b/src/google/adk/cli/utils/gcp_utils.py index a5a8ebb6de..663fe86b49 100644 --- a/src/google/adk/cli/utils/gcp_utils.py +++ b/src/google/adk/cli/utils/gcp_utils.py @@ -22,12 +22,12 @@ from typing import List from typing import Optional from typing import Tuple +from typing import cast import google.auth import google.auth.exceptions from google.auth.transport.requests import AuthorizedSession from google.auth.transport.requests import Request -from google.cloud import resourcemanager_v3 import requests _VERTEX_AI_ENDPOINT = "https://{location}-aiplatform.googleapis.com/v1beta1" @@ -89,7 +89,7 @@ def _call_vertex_express_api( raise ValueError(f"Unsupported method: {method}") response.raise_for_status() - return response.json() + return cast(Dict[str, Any], response.json()) def retrieve_express_project( @@ -162,10 +162,10 @@ def list_gcp_projects(limit: int = 20) -> List[Tuple[str, str]]: A list of (project_id, name) tuples. """ try: - client = resourcemanager_v3.ProjectsClient() + client = _create_projects_client() search_results = client.search_projects() - projects = [] + projects: List[Tuple[str, str]] = [] for project in search_results: if len(projects) >= limit: break @@ -175,3 +175,9 @@ def list_gcp_projects(limit: int = 20) -> List[Tuple[str, str]]: return projects except Exception: return [] + + +def _create_projects_client() -> Any: + from google.cloud import resourcemanager_v3 + + return resourcemanager_v3.ProjectsClient() diff --git a/tests/unittests/cli/utils/test_gcp_utils.py b/tests/unittests/cli/utils/test_gcp_utils.py index 824bc81b2f..87e5e31089 100644 --- a/tests/unittests/cli/utils/test_gcp_utils.py +++ b/tests/unittests/cli/utils/test_gcp_utils.py @@ -140,12 +140,10 @@ def test_sign_up_express(self, mock_auth_default, mock_session_cls): }, ) - @mock.patch( - "google.adk.cli.utils.gcp_utils.resourcemanager_v3.ProjectsClient" - ) - def test_list_gcp_projects(self, mock_client_cls): + @mock.patch("google.adk.cli.utils.gcp_utils._create_projects_client") + def test_list_gcp_projects(self, mock_create_projects_client): mock_client = mock.Mock() - mock_client_cls.return_value = mock_client + mock_create_projects_client.return_value = mock_client mock_project1 = mock.Mock() mock_project1.project_id = "p1" @@ -162,6 +160,18 @@ def test_list_gcp_projects(self, mock_client_cls): self.assertEqual(projects[0], ("p1", "Project 1")) self.assertEqual(projects[1], ("p2", "p2")) + @mock.patch( + "google.adk.cli.utils.gcp_utils._create_projects_client", + side_effect=ModuleNotFoundError("google.cloud"), + ) + def test_list_gcp_projects_missing_resource_manager_dependency( + self, mock_create_projects_client + ): + projects = gcp_utils.list_gcp_projects() + + self.assertEqual(projects, []) + mock_create_projects_client.assert_called_once() + if __name__ == "__main__": unittest.main()