diff --git a/pyproject.toml b/pyproject.toml index 43ee273184..b698916d00 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,7 @@ dependencies = [ "packaging>=21", "pydantic>=2.12,<3", "python-dotenv>=1,<2", + "python-multipart>=0.0.9", # go/keep-sorted start "pyyaml>=6.0.2,<7", "requests>=2.32.4,<3", diff --git a/src/google/adk/cli/utils/evals.py b/src/google/adk/cli/utils/evals.py index ff3c148637..3359d0f886 100644 --- a/src/google/adk/cli/utils/evals.py +++ b/src/google/adk/cli/utils/evals.py @@ -15,6 +15,7 @@ from __future__ import annotations import os +from typing import TYPE_CHECKING from pydantic import alias_generators from pydantic import BaseModel @@ -22,10 +23,12 @@ from ...evaluation.eval_case import Invocation from ...evaluation.evaluation_generator import EvaluationGenerator -from ...evaluation.gcs_eval_set_results_manager import GcsEvalSetResultsManager -from ...evaluation.gcs_eval_sets_manager import GcsEvalSetsManager from ...sessions.session import Session +if TYPE_CHECKING: + from ...evaluation.gcs_eval_set_results_manager import GcsEvalSetResultsManager + from ...evaluation.gcs_eval_sets_manager import GcsEvalSetsManager + class GcsEvalManagers(BaseModel): model_config = ConfigDict( @@ -68,6 +71,9 @@ def create_gcs_eval_managers_from_uri( ValueError: If the eval_storage_uri is not supported. """ if eval_storage_uri.startswith('gs://'): + from ...evaluation.gcs_eval_set_results_manager import GcsEvalSetResultsManager + from ...evaluation.gcs_eval_sets_manager import GcsEvalSetsManager + gcs_bucket = eval_storage_uri.split('://')[1] eval_sets_manager = GcsEvalSetsManager( bucket_name=gcs_bucket, project=os.environ['GOOGLE_CLOUD_PROJECT'] diff --git a/tests/unittests/cli/utils/test_evals.py b/tests/unittests/cli/utils/test_evals.py index 84214859c5..33383da19f 100644 --- a/tests/unittests/cli/utils/test_evals.py +++ b/tests/unittests/cli/utils/test_evals.py @@ -25,11 +25,11 @@ @mock.patch.dict(os.environ, {'GOOGLE_CLOUD_PROJECT': 'test-project'}) @mock.patch( - 'google.adk.cli.utils.evals.GcsEvalSetResultsManager', + 'google.adk.evaluation.gcs_eval_set_results_manager.GcsEvalSetResultsManager', autospec=True, ) @mock.patch( - 'google.adk.cli.utils.evals.GcsEvalSetsManager', + 'google.adk.evaluation.gcs_eval_sets_manager.GcsEvalSetsManager', autospec=True, ) def test_create_gcs_eval_managers_from_uri_success( @@ -61,3 +61,15 @@ def test_create_gcs_eval_managers_from_uri_success( def test_create_gcs_eval_managers_from_uri_failure(): with pytest.raises(ValueError): evals.create_gcs_eval_managers_from_uri('unsupported-uri') + + +def test_evals_module_does_not_import_gcs_at_module_level(): + """GCS classes should be lazy-imported, not at module level.""" + import inspect + + source = inspect.getsource(evals) + # The top-level imports should not contain direct GCS imports + # (they should be behind TYPE_CHECKING or inside functions) + module_globals = vars(evals) + assert 'GcsEvalSetResultsManager' not in module_globals + assert 'GcsEvalSetsManager' not in module_globals