Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions src/google/adk/sessions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import importlib
from typing import TYPE_CHECKING

from ..utils._dependency import missing_extra
from .base_session_service import BaseSessionService
from .session import Session
from .state import State
Expand All @@ -39,6 +38,7 @@
]

_LAZY_MEMBERS: dict[str, str] = {
'DatabaseSessionService': 'database_session_service',
'InMemorySessionService': 'in_memory_session_service',
'VertexAiSessionService': 'vertex_ai_session_service',
}
Expand All @@ -48,12 +48,6 @@ def __getattr__(name: str) -> object:
if name in _LAZY_MEMBERS:
module = importlib.import_module(f'{__name__}.{_LAZY_MEMBERS[name]}')
return vars(module)[name]
if name == 'DatabaseSessionService':
try:
module = importlib.import_module(f'{__name__}.database_session_service')
except ImportError as e:
raise missing_extra('sqlalchemy', 'db') from e
return vars(module)['DatabaseSessionService']
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')


Expand Down
13 changes: 4 additions & 9 deletions src/google/adk/sessions/database_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@
from sqlalchemy.ext.asyncio import AsyncSession as DatabaseSessionFactory
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.pool import StaticPool
except ImportError:
pass
except ImportError as e:
from ..utils._dependency import missing_extra

raise missing_extra("sqlalchemy", "db") from e
from typing_extensions import override

from . import _session_util
Expand Down Expand Up @@ -316,13 +318,6 @@ def __init__(
ValueError: If neither or both db_url and db_engine are provided, or if
engine creation fails.
"""
try:
import sqlalchemy # noqa: F401
except ImportError as e:
from ..utils._dependency import missing_extra

raise missing_extra("sqlalchemy", "db") from e

if (db_url is None) == (db_engine is None):
raise ValueError(
"Exactly one of 'db_url' or 'db_engine' must be provided."
Expand Down
6 changes: 4 additions & 2 deletions src/google/adk/sessions/migration/_schema_check_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
from sqlalchemy import inspect
from sqlalchemy import text
from sqlalchemy.engine import make_url
except ImportError:
pass
except ImportError as e:
from ...utils._dependency import missing_extra

raise missing_extra("sqlalchemy", "db") from e

if TYPE_CHECKING:
from sqlalchemy.engine import Connection
Expand Down
27 changes: 27 additions & 0 deletions tests/unittests/test_optional_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,33 @@ def test_database_session_service_fails_on_creation():
assert "sqlalchemy" in str(exc_info.value)


def _import_without_sqlalchemy(module_name: str) -> None:
"""Imports module_name in an interpreter state where sqlalchemy is missing.

``importlib.import_module`` re-executes the module through the loader.
``from <package> import <submodule>`` would instead return the stale module
object the parent package still holds as an attribute.
"""
with mock.patch.dict("sys.modules", {"sqlalchemy": None}):
# Popped inside the patch so mock.patch.dict restores the entry on exit.
sys.modules.pop(module_name, None)
importlib.import_module(module_name)


def test_database_session_service_import_reports_missing_extra():
"""Verify importing the module without sqlalchemy names the extra."""
with pytest.raises(ImportError, match=r"google-adk\[db\]"):
_import_without_sqlalchemy("google.adk.sessions.database_session_service")


def test_schema_check_utils_import_reports_missing_extra():
"""Verify the schema check helper names the extra instead of half-loading."""
with pytest.raises(ImportError, match=r"google-adk\[db\]"):
_import_without_sqlalchemy(
"google.adk.sessions.migration._schema_check_utils"
)


def test_vertex_ai_session_service_fails_on_creation():
"""Verify that creating VertexAiSessionService without extra fails using mocks."""
try:
Expand Down
Loading