Skip to content

Commit 416775d

Browse files
committed
fix: Make google-cloud-storage import lazy in skill utils
Change-Id: Id86475d867e31e3f8d3ee1429f2b8a7b8c53da34
1 parent 7e38fc8 commit 416775d

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

src/google/adk/skills/_utils.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import zipfile
2525

2626
from google.auth import credentials as auth
27-
from google.cloud import storage
2827
from pydantic import ValidationError
2928
import yaml
3029

@@ -407,6 +406,14 @@ def _list_skills_in_gcs_dir(
407406
Returns:
408407
Dictionary mapping skill IDs to their frontmatter.
409408
"""
409+
try:
410+
from google.cloud import storage
411+
except ImportError as e:
412+
raise ImportError(
413+
"google-cloud-storage is required to list skills in GCS. Install it"
414+
" with `pip install google-cloud-storage` or `pip install google-adk[gcp]`."
415+
) from e
416+
410417
client = storage.Client(project=project_id, credentials=credentials)
411418
bucket = client.bucket(bucket_name)
412419

@@ -466,6 +473,13 @@ def _load_skill_from_gcs_dir(
466473
ValueError: If SKILL.md is invalid or the skill name does not match
467474
the directory name.
468475
"""
476+
try:
477+
from google.cloud import storage
478+
except ImportError as e:
479+
raise ImportError(
480+
"google-cloud-storage is required to load skills from GCS. Install it"
481+
" with `pip install google-cloud-storage` or `pip install google-adk[gcp]`."
482+
) from e
469483

470484
client = storage.Client(project=project_id, credentials=credentials)
471485
bucket = client.bucket(bucket_name)

tests/unittests/skills/test__utils.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
"""Unit tests for skill utilities."""
1616

17+
import builtins
1718
import io
19+
import sys
1820
from unittest import mock
1921
import zipfile
2022

@@ -363,3 +365,33 @@ def test__load_skill_from_zip_bytes():
363365
assert skill.instructions == "Body instructions"
364366
assert skill.resources.get_reference("ref1.md") == "ref1 content"
365367
assert skill.resources.get_script("script1.sh").src == "echo hello"
368+
369+
370+
def test__list_skills_in_gcs_dir_import_error():
371+
"""Tests list_skills_in_gcs_dir raises ImportError when storage missing."""
372+
real_import = builtins.__import__
373+
374+
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
375+
if name == "google.cloud" and "storage" in (fromlist or ()):
376+
raise ImportError("No module named 'google.cloud.storage'")
377+
return real_import(name, globals, locals, fromlist, level)
378+
379+
with mock.patch("builtins.__import__", mock_import):
380+
with pytest.raises(ImportError, match="google-cloud-storage is required"):
381+
_list_skills_in_gcs_dir("my-bucket", "skills/")
382+
383+
384+
def test__load_skill_from_gcs_dir_import_error():
385+
"""Tests load_skill_from_gcs_dir raises ImportError when storage missing."""
386+
real_import = builtins.__import__
387+
388+
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
389+
if name == "google.cloud" and "storage" in (fromlist or ()):
390+
raise ImportError("No module named 'google.cloud.storage'")
391+
return real_import(name, globals, locals, fromlist, level)
392+
393+
with mock.patch("builtins.__import__", mock_import):
394+
with pytest.raises(ImportError, match="google-cloud-storage is required"):
395+
_load_skill_from_gcs_dir("my-bucket", "skills/my-skill/")
396+
397+

0 commit comments

Comments
 (0)