From 3357f5fdcb39048ab3c5cebee3c30f9d3b83fb96 Mon Sep 17 00:00:00 2001 From: daavoo Date: Mon, 8 Sep 2025 11:16:55 +0200 Subject: [PATCH 1/2] fix(gemin): Implement `_verify_and_set_api_key`. In #401 we stopped overriding `Provider.__init__` and thus we started to rely again on the default `Provider._verify_and_set_api_key`. We need to provide a custom implementation that checks for both API key options instead of the plain string with a `/`. - Added `test_gemini_initialization_with_env_var_api_key` and `test_vertexai_initialization_with_env_var_api_key`. --- src/any_llm/providers/gemini/gemini.py | 18 +++++++++++------- tests/unit/providers/test_google_provider.py | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/any_llm/providers/gemini/gemini.py b/src/any_llm/providers/gemini/gemini.py index 136a7aea..74ac53b2 100644 --- a/src/any_llm/providers/gemini/gemini.py +++ b/src/any_llm/providers/gemini/gemini.py @@ -15,12 +15,16 @@ class GeminiProvider(GoogleProvider): PROVIDER_DOCUMENTATION_URL = "https://ai.google.dev/gemini-api/docs" ENV_API_KEY_NAME = "GEMINI_API_KEY/GOOGLE_API_KEY" - def _get_client(self, config: ClientConfig) -> "genai.Client": - """Get Gemini API client.""" - api_key = getattr(config, "api_key", None) or os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY") + def _verify_and_set_api_key(self, config: ClientConfig) -> ClientConfig: + # Standardized API key handling. Splitting into its own function so that providers + # Can easily override this method if they don't want verification (for instance, LMStudio) + if not config.api_key: + config.api_key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY") - if not api_key: - msg = "Google Gemini Developer API" - raise MissingApiKeyError(msg, "GEMINI_API_KEY/GOOGLE_API_KEY") + if not config.api_key: + raise MissingApiKeyError(self.PROVIDER_NAME, self.ENV_API_KEY_NAME) + return config - return genai.Client(api_key=api_key, **(config.client_args if config.client_args else {})) + def _get_client(self, config: ClientConfig) -> "genai.Client": + """Get Gemini API client.""" + return genai.Client(api_key=config.api_key, **(config.client_args if config.client_args else {})) diff --git a/tests/unit/providers/test_google_provider.py b/tests/unit/providers/test_google_provider.py index 03575b94..8db301ef 100644 --- a/tests/unit/providers/test_google_provider.py +++ b/tests/unit/providers/test_google_provider.py @@ -47,6 +47,21 @@ def mock_google_provider(): # type: ignore[no-untyped-def] yield mock_genai +@pytest.mark.parametrize("env_var", ["GEMINI_API_KEY", "GOOGLE_API_KEY"]) +def test_gemini_initialization_with_env_var_api_key(env_var: str) -> None: + """Test that the provider initializes correctly with API key from environment variable.""" + with patch.dict("os.environ", {env_var: "env-api-key"}, clear=True): + provider = GeminiProvider(ClientConfig()) + assert provider.config.api_key == "env-api-key" + + +def test_vertexai_initialization_with_env_var_api_key() -> None: + """Test that the VertexaiProvider initializes correctly with GOOGLE_PROJECT_ID from environment variable.""" + with patch.dict("os.environ", {"GOOGLE_PROJECT_ID": "env-project-id"}, clear=True): + provider = VertexaiProvider(ClientConfig()) + assert provider.config.api_key == "env-project-id" + + @pytest.mark.asyncio async def test_completion_with_system_instruction(google_provider_class: type[Provider]) -> None: """Test that completion works correctly with system_instruction.""" From 9719f4fc5c808a59b09a8f03f9c256f8d02dfcb3 Mon Sep 17 00:00:00 2001 From: daavoo Date: Mon, 8 Sep 2025 11:21:53 +0200 Subject: [PATCH 2/2] drop comment --- src/any_llm/providers/gemini/gemini.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/any_llm/providers/gemini/gemini.py b/src/any_llm/providers/gemini/gemini.py index 74ac53b2..7c71ab1e 100644 --- a/src/any_llm/providers/gemini/gemini.py +++ b/src/any_llm/providers/gemini/gemini.py @@ -16,8 +16,6 @@ class GeminiProvider(GoogleProvider): ENV_API_KEY_NAME = "GEMINI_API_KEY/GOOGLE_API_KEY" def _verify_and_set_api_key(self, config: ClientConfig) -> ClientConfig: - # Standardized API key handling. Splitting into its own function so that providers - # Can easily override this method if they don't want verification (for instance, LMStudio) if not config.api_key: config.api_key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY")