Skip to content

Commit ceaa865

Browse files
mangod12claude
andcommitted
fix(cli): lazy-import GCS deps so adk web works without google-cloud-storage
The `DevServer` import chain unconditionally imported `gcs_eval_set_results_manager` and `gcs_eval_sets_manager` at module level, which require `google-cloud-storage`. This caused `adk web` to silently fall back to `ApiServer` on a fresh `pip install google-adk`, leaving the dev UI unreachable. Fix: move GCS imports behind `TYPE_CHECKING` for type annotations and lazy-import inside `create_gcs_eval_managers_from_uri()` where they are actually needed. Also add `python-multipart` to core dependencies since it is required for Builder UI endpoints in `adk web`. Fixes #5787 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 84fa984 commit ceaa865

3 files changed

Lines changed: 23 additions & 4 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ dependencies = [
4747
"packaging>=21",
4848
"pydantic>=2.12,<3",
4949
"python-dotenv>=1,<2",
50+
"python-multipart>=0.0.9",
5051
# go/keep-sorted start
5152
"pyyaml>=6.0.2,<7",
5253
"requests>=2.32.4,<3",

src/google/adk/cli/utils/evals.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,20 @@
1515
from __future__ import annotations
1616

1717
import os
18+
from typing import TYPE_CHECKING
1819

1920
from pydantic import alias_generators
2021
from pydantic import BaseModel
2122
from pydantic import ConfigDict
2223

2324
from ...evaluation.eval_case import Invocation
2425
from ...evaluation.evaluation_generator import EvaluationGenerator
25-
from ...evaluation.gcs_eval_set_results_manager import GcsEvalSetResultsManager
26-
from ...evaluation.gcs_eval_sets_manager import GcsEvalSetsManager
2726
from ...sessions.session import Session
2827

28+
if TYPE_CHECKING:
29+
from ...evaluation.gcs_eval_set_results_manager import GcsEvalSetResultsManager
30+
from ...evaluation.gcs_eval_sets_manager import GcsEvalSetsManager
31+
2932

3033
class GcsEvalManagers(BaseModel):
3134
model_config = ConfigDict(
@@ -68,6 +71,9 @@ def create_gcs_eval_managers_from_uri(
6871
ValueError: If the eval_storage_uri is not supported.
6972
"""
7073
if eval_storage_uri.startswith('gs://'):
74+
from ...evaluation.gcs_eval_set_results_manager import GcsEvalSetResultsManager
75+
from ...evaluation.gcs_eval_sets_manager import GcsEvalSetsManager
76+
7177
gcs_bucket = eval_storage_uri.split('://')[1]
7278
eval_sets_manager = GcsEvalSetsManager(
7379
bucket_name=gcs_bucket, project=os.environ['GOOGLE_CLOUD_PROJECT']

tests/unittests/cli/utils/test_evals.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525

2626
@mock.patch.dict(os.environ, {'GOOGLE_CLOUD_PROJECT': 'test-project'})
2727
@mock.patch(
28-
'google.adk.cli.utils.evals.GcsEvalSetResultsManager',
28+
'google.adk.evaluation.gcs_eval_set_results_manager.GcsEvalSetResultsManager',
2929
autospec=True,
3030
)
3131
@mock.patch(
32-
'google.adk.cli.utils.evals.GcsEvalSetsManager',
32+
'google.adk.evaluation.gcs_eval_sets_manager.GcsEvalSetsManager',
3333
autospec=True,
3434
)
3535
def test_create_gcs_eval_managers_from_uri_success(
@@ -61,3 +61,15 @@ def test_create_gcs_eval_managers_from_uri_success(
6161
def test_create_gcs_eval_managers_from_uri_failure():
6262
with pytest.raises(ValueError):
6363
evals.create_gcs_eval_managers_from_uri('unsupported-uri')
64+
65+
66+
def test_evals_module_does_not_import_gcs_at_module_level():
67+
"""GCS classes should be lazy-imported, not at module level."""
68+
import inspect
69+
70+
source = inspect.getsource(evals)
71+
# The top-level imports should not contain direct GCS imports
72+
# (they should be behind TYPE_CHECKING or inside functions)
73+
module_globals = vars(evals)
74+
assert 'GcsEvalSetResultsManager' not in module_globals
75+
assert 'GcsEvalSetsManager' not in module_globals

0 commit comments

Comments
 (0)