From 51e553c31fab234da0f28ce7191b7ddb4525d5e3 Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Sat, 4 Jul 2026 03:45:06 +0530 Subject: [PATCH 1/8] test: upgrade integration harnesses for dual-server execution --- .../toolbox-adk/integration.cloudbuild.yaml | 2 +- .../toolbox-adk/tests/integration/conftest.py | 72 +++++++++++++---- .../tests/integration/test_integration.py | 61 +++++++------- .../toolbox-core/integration.cloudbuild.yaml | 2 +- packages/toolbox-core/tests/conftest.py | 80 +++++++++++++++---- .../integration.cloudbuild.yaml | 2 +- packages/toolbox-langchain/tests/conftest.py | 74 +++++++++++++---- packages/toolbox-langchain/tests/test_e2e.py | 5 +- .../integration.cloudbuild.yaml | 2 +- packages/toolbox-llamaindex/tests/conftest.py | 72 +++++++++++++---- packages/toolbox-llamaindex/tests/test_e2e.py | 5 +- 11 files changed, 274 insertions(+), 103 deletions(-) diff --git a/packages/toolbox-adk/integration.cloudbuild.yaml b/packages/toolbox-adk/integration.cloudbuild.yaml index 8d8b5678f..353bad129 100644 --- a/packages/toolbox-adk/integration.cloudbuild.yaml +++ b/packages/toolbox-adk/integration.cloudbuild.yaml @@ -50,5 +50,5 @@ options: substitutions: _VERSION: '3.13' # Default values (can be overridden by triggers) - _TOOLBOX_VERSION: '1.5.0' + _TOOLBOX_VERSION: '1.6.0' _TOOLBOX_MANIFEST_VERSION: '34' diff --git a/packages/toolbox-adk/tests/integration/conftest.py b/packages/toolbox-adk/tests/integration/conftest.py index 7a0346c3a..78d96aa0f 100644 --- a/packages/toolbox-adk/tests/integration/conftest.py +++ b/packages/toolbox-adk/tests/integration/conftest.py @@ -25,7 +25,10 @@ from typing import Generator import google -import pytest_asyncio +import pytest + +TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" +TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" from google.auth import compute_engine from google.cloud import secretmanager, storage @@ -75,7 +78,8 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - return f"v{toolbox_version}/{os_system}/{arch}/toolbox" + ext = ".exe" if os_system == "windows" else "" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" def get_auth_token(client_id: str) -> str: @@ -92,17 +96,17 @@ def get_auth_token(client_id: str) -> str: #### Define Fixtures -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def project_id() -> str: return get_env_var("GOOGLE_CLOUD_PROJECT") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_version() -> str: return get_env_var("TOOLBOX_VERSION") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def tools_file_path(project_id: str) -> Generator[str]: """Provides a temporary file path containing the tools manifest.""" if os.environ.get("TEST_MOCK_GCP"): @@ -122,7 +126,7 @@ def tools_file_path(project_id: str) -> Generator[str]: os.remove(tools_file_path) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token1(project_id: str) -> str: if os.environ.get("TEST_MOCK_GCP"): return "mock-token-1" @@ -132,7 +136,7 @@ def auth_token1(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token2(project_id: str) -> str: if os.environ.get("TEST_MOCK_GCP"): return "mock-token-2" @@ -142,7 +146,7 @@ def auth_token2(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None]: """Starts the toolbox server as a subprocess.""" if os.environ.get("TEST_MOCK_GCP"): @@ -159,20 +163,30 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None # Make toolbox executable os.chmod("toolbox", 0o700) # Run toolbox binary - toolbox_server = subprocess.Popen( - ["./toolbox", "--tools-file", tools_file_path] + toolbox_server_1 = subprocess.Popen( + ["./toolbox", "--port", "5000", "--tools-file", tools_file_path] + ) + toolbox_server_2 = subprocess.Popen( + [ + "./toolbox", + "--port", + "5001", + "--tools-file", + tools_file_path, + "--enable-draft-specs", + ] ) # Wait for server to start # Retry logic with a timeout for _ in range(5): # retries time.sleep(2) - print("Checking if toolbox is successfully started...") - if toolbox_server.poll() is None: - print("Toolbox server started successfully.") + print("Checking if both toolbox servers are successfully started...") + if toolbox_server_1.poll() is None and toolbox_server_2.poll() is None: + print("Toolbox servers started successfully.") break else: - raise RuntimeError("Toolbox server failed to start after 5 retries.") + raise RuntimeError("Toolbox servers failed to start after 5 retries.") except subprocess.CalledProcessError as e: print(e.stderr.decode("utf-8")) print(e.stdout.decode("utf-8")) @@ -180,5 +194,31 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None yield # Clean up toolbox server - toolbox_server.terminate() - toolbox_server.wait(timeout=5) + toolbox_server_1.terminate() + toolbox_server_2.terminate() + toolbox_server_1.wait(timeout=5) + toolbox_server_2.wait(timeout=5) + + +@pytest.fixture( + params=[TOOLBOX_SERVER_URL_STABLE, TOOLBOX_SERVER_URL_DRAFT], scope="session" +) +def toolbox_server_url(request) -> str: + return request.param + + +@pytest.fixture(autouse=True) +def patch_toolbox_client_url(toolbox_server_url): + from toolbox_adk.toolset import ToolboxToolset + + original_init = ToolboxToolset.__init__ + + def new_init(self, server_url=TOOLBOX_SERVER_URL_STABLE, *args, **kwargs): + if server_url == TOOLBOX_SERVER_URL_STABLE: + server_url = toolbox_server_url + original_init(self, server_url, *args, **kwargs) + + from unittest.mock import patch + + with patch.object(ToolboxToolset, "__init__", new_init, create=True): + yield diff --git a/packages/toolbox-adk/tests/integration/test_integration.py b/packages/toolbox-adk/tests/integration/test_integration.py index 780b66d38..7592fc32a 100644 --- a/packages/toolbox-adk/tests/integration/test_integration.py +++ b/packages/toolbox-adk/tests/integration/test_integration.py @@ -32,6 +32,7 @@ from toolbox_core.protocol import Protocol from toolbox_adk import CredentialStrategy, ToolboxTool, ToolboxToolset +from .conftest import TOOLBOX_SERVER_URL_STABLE # Ensure TOOLBOX_VERSION is set for the fixture if "TOOLBOX_VERSION" not in os.environ: @@ -50,7 +51,7 @@ async def test_load_toolset_and_run(self): # Auth: TOOLBOX_IDENTITY for simplicity in this local test as we don't have ADK identity setup. toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", credentials=CredentialStrategy.toolbox_identity(), ) @@ -84,7 +85,7 @@ async def test_load_toolset_and_run(self): async def test_load_toolset_with_default_protocol(self): """Test initializing toolset with default protocol (MCP).""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", credentials=CredentialStrategy.toolbox_identity(), ) @@ -108,7 +109,7 @@ async def test_load_toolset_with_default_protocol(self): async def test_load_toolset_with_explicit_protocol(self): """Test initializing toolset with specific protocol (MCP_v20251125).""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", credentials=CredentialStrategy.toolbox_identity(), protocol=Protocol.MCP_v20251125, @@ -132,7 +133,7 @@ async def test_load_toolset_with_explicit_protocol(self): async def test_partial_loading_by_names(self): toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -152,7 +153,7 @@ async def test_partial_loading_by_names(self): async def test_bound_params_e2e(self): # Test binding param at toolset level toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-n-rows"], bound_params={"num_rows": "2"}, credentials=CredentialStrategy.toolbox_identity(), @@ -168,7 +169,7 @@ async def test_bound_params_e2e(self): async def test_3lo_flow_simulation(self): toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, # Load a specific tool that we know the arguments for tool_names=["get-n-rows"], credentials=CredentialStrategy.user_identity( @@ -265,7 +266,7 @@ async def test_3lo_flow_simulation(self): async def test_manual_token_integration(self): """Test the MANUAL_TOKEN strategy.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", credentials=CredentialStrategy.manual_token(token="fake-manual-token"), ) @@ -284,7 +285,7 @@ async def test_manual_credentials_integration(self): mock_creds.token = "fake-creds-token" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", credentials=CredentialStrategy.manual_credentials(credentials=mock_creds), ) @@ -297,7 +298,7 @@ async def test_manual_credentials_integration(self): async def test_api_key_integration(self): """Test the API_KEY strategy.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", credentials=CredentialStrategy.api_key(key="my-key", header_name="x-foo"), ) @@ -333,7 +334,7 @@ async def test_adk_integration_optional_params(self): # 3. Use in Toolset toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", credentials=strategy, ) @@ -357,7 +358,7 @@ async def test_header_collision(self): creds_token = "Bearer strategy-token" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name="my-toolset", additional_headers={"Authorization": manual_override}, credentials=CredentialStrategy.manual_token(token="strategy-token"), @@ -391,7 +392,7 @@ async def test_load_toolset_specific( ): """Load a specific toolset""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, toolset_name=toolset_name, credentials=CredentialStrategy.toolbox_identity(), ) @@ -406,7 +407,7 @@ async def test_load_toolset_specific( async def test_load_toolset_default(self): """Load the default toolset, i.e. all tools.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, credentials=CredentialStrategy.toolbox_identity(), ) try: @@ -429,7 +430,7 @@ async def test_load_toolset_default(self): async def test_run_tool(self): """Invoke a tool.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -451,7 +452,7 @@ async def test_run_tool(self): async def test_run_tool_missing_params(self): """Invoke a tool with missing params.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -470,7 +471,7 @@ async def test_run_tool_missing_params(self): async def test_run_tool_wrong_param_type(self): """Invoke a tool with wrong param type.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -494,7 +495,7 @@ class TestBindParams: async def test_bind_params(self): """Bind a param to an existing tool.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-n-rows"], bound_params={"num_rows": "3"}, credentials=CredentialStrategy.toolbox_identity(), @@ -516,7 +517,7 @@ async def test_bind_params(self): async def test_bind_params_callable(self): """Bind a callable param to an existing tool.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-n-rows"], bound_params={"num_rows": lambda: "3"}, credentials=CredentialStrategy.toolbox_identity(), @@ -542,7 +543,7 @@ class TestAuth: async def test_run_tool_unauth_with_auth(self, auth_token2: str): """Tests running a tool that doesn't require auth, with auth provided.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-row-by-id"], auth_token_getters={"my-test-auth": lambda: auth_token2}, credentials=CredentialStrategy.toolbox_identity(), @@ -559,7 +560,7 @@ async def test_run_tool_unauth_with_auth(self, auth_token2: str): async def test_run_multiple_tools_unauth_with_auth(self, auth_token2: str): """Tests running multiple tools that don't require auth, verifying formatting of tool lists.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-row-by-id", "search-rows"], auth_token_getters={"my-test-auth": lambda: auth_token2}, credentials=CredentialStrategy.toolbox_identity(), @@ -576,7 +577,7 @@ async def test_run_multiple_tools_unauth_with_auth(self, auth_token2: str): async def test_run_multiple_tools_partial_auth_usage(self, auth_token2: str): """Tests that when some tokens are used and some aren't across diverse tools, only the truly unused tokens appear in the error.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=[ "get-row-by-id-auth", "search-rows", @@ -601,7 +602,7 @@ async def test_run_tool_no_auth(self): """Tests running a tool requiring auth without providing auth.""" # Note: We load it without auth getters. Invocation should fail. toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-row-by-id-auth"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -621,7 +622,7 @@ async def test_run_tool_no_auth(self): async def test_run_tool_wrong_auth(self, auth_token2: str): """Tests running a tool with incorrect auth.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-row-by-id-auth"], auth_token_getters={"my-test-auth": lambda: auth_token2}, credentials=CredentialStrategy.toolbox_identity(), @@ -642,7 +643,7 @@ async def test_run_tool_wrong_auth(self, auth_token2: str): async def test_run_tool_auth(self, auth_token1: str): """Tests running a tool with correct auth.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-row-by-id-auth"], auth_token_getters={"my-test-auth": lambda: auth_token1}, credentials=CredentialStrategy.toolbox_identity(), @@ -664,7 +665,7 @@ async def get_token_asynchronously(): return auth_token1 toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["get-row-by-id-auth"], auth_token_getters={"my-test-auth": get_token_asynchronously}, credentials=CredentialStrategy.toolbox_identity(), @@ -690,7 +691,7 @@ class TestOptionalParams: async def test_run_tool_with_optional_params_omitted(self): """Invoke a tool providing only the required parameter.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["search-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -709,7 +710,7 @@ async def test_run_tool_with_optional_params_omitted(self): async def test_run_tool_with_all_valid_params(self): """Invoke a tool providing all parameters.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["search-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -729,7 +730,7 @@ async def test_run_tool_with_all_valid_params(self): async def test_run_tool_with_missing_required_param(self): """Invoke a tool without its required parameter.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["search-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -754,7 +755,7 @@ class TestMapParams: async def test_run_tool_with_map_params(self): """Invoke a tool with valid map parameters.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["process-data"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -785,7 +786,7 @@ async def test_run_tool_with_map_params(self): async def test_run_tool_with_wrong_map_value_type(self): """Invoke a tool with a map parameter having the wrong value type.""" toolset = ToolboxToolset( - server_url="http://localhost:5000", + server_url=TOOLBOX_SERVER_URL_STABLE, tool_names=["process-data"], credentials=CredentialStrategy.toolbox_identity(), ) diff --git a/packages/toolbox-core/integration.cloudbuild.yaml b/packages/toolbox-core/integration.cloudbuild.yaml index 17e388483..3dc6141ba 100644 --- a/packages/toolbox-core/integration.cloudbuild.yaml +++ b/packages/toolbox-core/integration.cloudbuild.yaml @@ -45,5 +45,5 @@ options: logging: CLOUD_LOGGING_ONLY substitutions: _VERSION: '3.13' - _TOOLBOX_VERSION: '1.5.0' + _TOOLBOX_VERSION: '1.6.0' _TOOLBOX_MANIFEST_VERSION: '34' diff --git a/packages/toolbox-core/tests/conftest.py b/packages/toolbox-core/tests/conftest.py index 338d031c0..45fc53305 100644 --- a/packages/toolbox-core/tests/conftest.py +++ b/packages/toolbox-core/tests/conftest.py @@ -25,7 +25,10 @@ from typing import Generator import google -import pytest_asyncio +import pytest + +TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" +TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" from google.auth import compute_engine from google.cloud import secretmanager, storage @@ -75,7 +78,8 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - return f"v{toolbox_version}/{os_system}/{arch}/toolbox" + ext = ".exe" if os_system == "windows" else "" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" def get_auth_token(client_id: str) -> str: @@ -92,17 +96,17 @@ def get_auth_token(client_id: str) -> str: #### Define Fixtures -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def project_id() -> str: return get_env_var("GOOGLE_CLOUD_PROJECT") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_version() -> str: return get_env_var("TOOLBOX_VERSION") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def tools_file_path(project_id: str) -> Generator[str]: """Provides a temporary file path containing the tools manifest.""" tools_manifest = access_secret_version( @@ -115,7 +119,7 @@ def tools_file_path(project_id: str) -> Generator[str]: os.remove(tools_file_path) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token1(project_id: str) -> str: client_id = access_secret_version( project_id=project_id, secret_id="sdk_testing_client1" @@ -123,7 +127,7 @@ def auth_token1(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token2(project_id: str) -> str: client_id = access_secret_version( project_id=project_id, secret_id="sdk_testing_client2" @@ -131,7 +135,7 @@ def auth_token2(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None]: """Starts the toolbox server as a subprocess.""" print("Downloading toolbox binary from gcs bucket...") @@ -143,20 +147,30 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None # Make toolbox executable os.chmod("toolbox", 0o700) # Run toolbox binary - toolbox_server = subprocess.Popen( - ["./toolbox", "--tools-file", tools_file_path] + toolbox_server_1 = subprocess.Popen( + ["./toolbox", "--port", "5000", "--tools-file", tools_file_path] + ) + toolbox_server_2 = subprocess.Popen( + [ + "./toolbox", + "--port", + "5001", + "--tools-file", + tools_file_path, + "--enable-draft-specs", + ] ) # Wait for server to start # Retry logic with a timeout for _ in range(5): # retries time.sleep(2) - print("Checking if toolbox is successfully started...") - if toolbox_server.poll() is None: - print("Toolbox server started successfully.") + print("Checking if both toolbox servers are successfully started...") + if toolbox_server_1.poll() is None and toolbox_server_2.poll() is None: + print("Toolbox servers started successfully.") break else: - raise RuntimeError("Toolbox server failed to start after 5 retries.") + raise RuntimeError("Toolbox servers failed to start after 5 retries.") except subprocess.CalledProcessError as e: print(e.stderr.decode("utf-8")) print(e.stdout.decode("utf-8")) @@ -164,5 +178,39 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None yield # Clean up toolbox server - toolbox_server.terminate() - toolbox_server.wait(timeout=5) + toolbox_server_1.terminate() + toolbox_server_2.terminate() + toolbox_server_1.wait(timeout=5) + toolbox_server_2.wait(timeout=5) + + +@pytest.fixture( + params=[TOOLBOX_SERVER_URL_STABLE, TOOLBOX_SERVER_URL_DRAFT], scope="session" +) +def toolbox_server_url(request) -> str: + return request.param + + +@pytest.fixture(autouse=True) +def patch_toolbox_client_url(toolbox_server_url): + from toolbox_core.client import ToolboxClient + from toolbox_core.sync_client import ToolboxSyncClient + + original_init = ToolboxClient.__init__ + original_sync_init = ToolboxSyncClient.__init__ + + def new_init(self, url=TOOLBOX_SERVER_URL_STABLE, *args, **kwargs): + if url == TOOLBOX_SERVER_URL_STABLE: + url = toolbox_server_url + original_init(self, url, *args, **kwargs) + + def new_sync_init(self, url=TOOLBOX_SERVER_URL_STABLE, *args, **kwargs): + if url == TOOLBOX_SERVER_URL_STABLE: + url = toolbox_server_url + original_sync_init(self, url, *args, **kwargs) + + from unittest.mock import patch + + with patch.object(ToolboxClient, "__init__", new_init, create=True): + with patch.object(ToolboxSyncClient, "__init__", new_sync_init, create=True): + yield diff --git a/packages/toolbox-langchain/integration.cloudbuild.yaml b/packages/toolbox-langchain/integration.cloudbuild.yaml index 39a34b5fe..db9cbc135 100644 --- a/packages/toolbox-langchain/integration.cloudbuild.yaml +++ b/packages/toolbox-langchain/integration.cloudbuild.yaml @@ -49,5 +49,5 @@ options: logging: CLOUD_LOGGING_ONLY substitutions: _VERSION: '3.13' - _TOOLBOX_VERSION: '1.5.0' + _TOOLBOX_VERSION: '1.6.0' _TOOLBOX_MANIFEST_VERSION: '34' diff --git a/packages/toolbox-langchain/tests/conftest.py b/packages/toolbox-langchain/tests/conftest.py index a1c87a7d8..7771c24a7 100644 --- a/packages/toolbox-langchain/tests/conftest.py +++ b/packages/toolbox-langchain/tests/conftest.py @@ -25,7 +25,10 @@ from typing import Generator import google -import pytest_asyncio +import pytest + +TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" +TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" from google.auth import compute_engine from google.cloud import secretmanager, storage @@ -75,7 +78,8 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - return f"v{toolbox_version}/{os_system}/{arch}/toolbox" + ext = ".exe" if os_system == "windows" else "" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" def get_auth_token(client_id: str) -> str: @@ -92,17 +96,17 @@ def get_auth_token(client_id: str) -> str: #### Define Fixtures -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def project_id() -> str: return get_env_var("GOOGLE_CLOUD_PROJECT") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_version() -> str: return get_env_var("TOOLBOX_VERSION") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def tools_file_path(project_id: str) -> Generator[str]: """Provides a temporary file path containing the tools manifest.""" tools_manifest = access_secret_version( @@ -115,7 +119,7 @@ def tools_file_path(project_id: str) -> Generator[str]: os.remove(tools_file_path) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token1(project_id: str) -> str: client_id = access_secret_version( project_id=project_id, secret_id="sdk_testing_client1" @@ -123,7 +127,7 @@ def auth_token1(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token2(project_id: str) -> str: client_id = access_secret_version( project_id=project_id, secret_id="sdk_testing_client2" @@ -131,7 +135,7 @@ def auth_token2(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None]: """Starts the toolbox server as a subprocess.""" print("Downloading toolbox binary from gcs bucket...") @@ -143,20 +147,30 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None # Make toolbox executable os.chmod("toolbox", 0o700) # Run toolbox binary - toolbox_server = subprocess.Popen( - ["./toolbox", "--tools-file", tools_file_path] + toolbox_server_1 = subprocess.Popen( + ["./toolbox", "--port", "5000", "--tools-file", tools_file_path] + ) + toolbox_server_2 = subprocess.Popen( + [ + "./toolbox", + "--port", + "5001", + "--tools-file", + tools_file_path, + "--enable-draft-specs", + ] ) # Wait for server to start # Retry logic with a timeout for _ in range(5): # retries - time.sleep(2) - print("Checking if toolbox is successfully started...") - if toolbox_server.poll() is None: - print("Toolbox server started successfully.") + time.sleep(4) + print("Checking if both toolbox servers are successfully started...") + if toolbox_server_1.poll() is None and toolbox_server_2.poll() is None: + print("Toolbox servers started successfully.") break else: - raise RuntimeError("Toolbox server failed to start after 5 retries.") + raise RuntimeError("Toolbox servers failed to start after 5 retries.") except subprocess.CalledProcessError as e: print(e.stderr.decode("utf-8")) print(e.stdout.decode("utf-8")) @@ -164,5 +178,31 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None yield # Clean up toolbox server - toolbox_server.terminate() - toolbox_server.wait() + toolbox_server_1.terminate() + toolbox_server_2.terminate() + toolbox_server_1.wait() + toolbox_server_2.wait() + + +@pytest.fixture( + params=[TOOLBOX_SERVER_URL_STABLE, TOOLBOX_SERVER_URL_DRAFT], scope="session" +) +def toolbox_server_url(request) -> str: + return request.param + + +@pytest.fixture(autouse=True) +def patch_toolbox_client_url(toolbox_server_url): + from toolbox_core.client import ToolboxClient + + original_init = ToolboxClient.__init__ + + def new_init(self, url=TOOLBOX_SERVER_URL_STABLE, *args, **kwargs): + if url == TOOLBOX_SERVER_URL_STABLE: + url = toolbox_server_url + original_init(self, url, *args, **kwargs) + + from unittest.mock import patch + + with patch.object(ToolboxClient, "__init__", new_init, create=True): + yield diff --git a/packages/toolbox-langchain/tests/test_e2e.py b/packages/toolbox-langchain/tests/test_e2e.py index 93fbd01ea..b1af22d4e 100644 --- a/packages/toolbox-langchain/tests/test_e2e.py +++ b/packages/toolbox-langchain/tests/test_e2e.py @@ -39,6 +39,7 @@ from pydantic import ValidationError from toolbox_langchain.client import ToolboxClient +from .conftest import TOOLBOX_SERVER_URL_STABLE @pytest.mark.asyncio @@ -47,7 +48,7 @@ class TestE2EClientAsync: @pytest.fixture(scope="function") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient("http://localhost:5000") + toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) return toolbox @pytest_asyncio.fixture(scope="function") @@ -194,7 +195,7 @@ class TestE2EClientSync: @pytest.fixture(scope="session") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient("http://localhost:5000") + toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) return toolbox @pytest.fixture(scope="function") diff --git a/packages/toolbox-llamaindex/integration.cloudbuild.yaml b/packages/toolbox-llamaindex/integration.cloudbuild.yaml index 0d31e0d69..3a2e609aa 100644 --- a/packages/toolbox-llamaindex/integration.cloudbuild.yaml +++ b/packages/toolbox-llamaindex/integration.cloudbuild.yaml @@ -49,5 +49,5 @@ options: logging: CLOUD_LOGGING_ONLY substitutions: _VERSION: '3.13' - _TOOLBOX_VERSION: '1.5.0' + _TOOLBOX_VERSION: '1.6.0' _TOOLBOX_MANIFEST_VERSION: '34' diff --git a/packages/toolbox-llamaindex/tests/conftest.py b/packages/toolbox-llamaindex/tests/conftest.py index c8a8fa5f9..d108293bf 100644 --- a/packages/toolbox-llamaindex/tests/conftest.py +++ b/packages/toolbox-llamaindex/tests/conftest.py @@ -25,7 +25,10 @@ from typing import Generator import google -import pytest_asyncio +import pytest + +TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" +TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" from google.auth import compute_engine from google.cloud import secretmanager, storage @@ -75,7 +78,8 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - return f"v{toolbox_version}/{os_system}/{arch}/toolbox" + ext = ".exe" if os_system == "windows" else "" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" def get_auth_token(client_id: str) -> str: @@ -92,17 +96,17 @@ def get_auth_token(client_id: str) -> str: #### Define Fixtures -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def project_id() -> str: return get_env_var("GOOGLE_CLOUD_PROJECT") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_version() -> str: return get_env_var("TOOLBOX_VERSION") -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def tools_file_path(project_id: str) -> Generator[str]: """Provides a temporary file path containing the tools manifest.""" tools_manifest = access_secret_version( @@ -115,7 +119,7 @@ def tools_file_path(project_id: str) -> Generator[str]: os.remove(tools_file_path) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token1(project_id: str) -> str: client_id = access_secret_version( project_id=project_id, secret_id="sdk_testing_client1" @@ -123,7 +127,7 @@ def auth_token1(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def auth_token2(project_id: str) -> str: client_id = access_secret_version( project_id=project_id, secret_id="sdk_testing_client2" @@ -131,7 +135,7 @@ def auth_token2(project_id: str) -> str: return get_auth_token(client_id) -@pytest_asyncio.fixture(scope="session") +@pytest.fixture(scope="session") def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None]: """Starts the toolbox server as a subprocess.""" print("Downloading toolbox binary from gcs bucket...") @@ -143,20 +147,30 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None # Make toolbox executable os.chmod("toolbox", 0o700) # Run toolbox binary - toolbox_server = subprocess.Popen( - ["./toolbox", "--tools-file", tools_file_path] + toolbox_server_1 = subprocess.Popen( + ["./toolbox", "--port", "5000", "--tools-file", tools_file_path] + ) + toolbox_server_2 = subprocess.Popen( + [ + "./toolbox", + "--port", + "5001", + "--tools-file", + tools_file_path, + "--enable-draft-specs", + ] ) # Wait for server to start # Retry logic with a timeout for _ in range(5): # retries time.sleep(4) - print("Checking if toolbox is successfully started...") - if toolbox_server.poll() is None: - print("Toolbox server started successfully.") + print("Checking if both toolbox servers are successfully started...") + if toolbox_server_1.poll() is None and toolbox_server_2.poll() is None: + print("Toolbox servers started successfully.") break else: - raise RuntimeError("Toolbox server failed to start after 5 retries.") + raise RuntimeError("Toolbox servers failed to start after 5 retries.") except subprocess.CalledProcessError as e: print(e.stderr.decode("utf-8")) print(e.stdout.decode("utf-8")) @@ -164,5 +178,31 @@ def toolbox_server(toolbox_version: str, tools_file_path: str) -> Generator[None yield # Clean up toolbox server - toolbox_server.terminate() - toolbox_server.wait() + toolbox_server_1.terminate() + toolbox_server_2.terminate() + toolbox_server_1.wait() + toolbox_server_2.wait() + + +@pytest.fixture( + params=[TOOLBOX_SERVER_URL_STABLE, TOOLBOX_SERVER_URL_DRAFT], scope="session" +) +def toolbox_server_url(request) -> str: + return request.param + + +@pytest.fixture(autouse=True) +def patch_toolbox_client_url(toolbox_server_url): + from toolbox_core.client import ToolboxClient + + original_init = ToolboxClient.__init__ + + def new_init(self, url=TOOLBOX_SERVER_URL_STABLE, *args, **kwargs): + if url == TOOLBOX_SERVER_URL_STABLE: + url = toolbox_server_url + original_init(self, url, *args, **kwargs) + + from unittest.mock import patch + + with patch.object(ToolboxClient, "__init__", new_init, create=True): + yield diff --git a/packages/toolbox-llamaindex/tests/test_e2e.py b/packages/toolbox-llamaindex/tests/test_e2e.py index e0cdba4cb..eb41aecd2 100644 --- a/packages/toolbox-llamaindex/tests/test_e2e.py +++ b/packages/toolbox-llamaindex/tests/test_e2e.py @@ -39,6 +39,7 @@ from pydantic import ValidationError from toolbox_llamaindex.client import ToolboxClient +from .conftest import TOOLBOX_SERVER_URL_STABLE @pytest.mark.asyncio @@ -47,7 +48,7 @@ class TestE2EClientAsync: @pytest.fixture(scope="function") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient("http://localhost:5000") + toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) return toolbox @pytest_asyncio.fixture(scope="function") @@ -194,7 +195,7 @@ class TestE2EClientSync: @pytest.fixture(scope="session") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient("http://localhost:5000") + toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) return toolbox @pytest.fixture(scope="function") From 4c3fb2f23b04d3229d0390848e5e5cc8f4ae0a37 Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Mon, 6 Jul 2026 11:23:20 +0530 Subject: [PATCH 2/8] chore: delint --- .../tests/integration/test_integration.py | 63 ++++++++++--------- packages/toolbox-langchain/tests/test_e2e.py | 7 ++- packages/toolbox-llamaindex/tests/test_e2e.py | 7 ++- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/packages/toolbox-adk/tests/integration/test_integration.py b/packages/toolbox-adk/tests/integration/test_integration.py index 7592fc32a..0f8a88466 100644 --- a/packages/toolbox-adk/tests/integration/test_integration.py +++ b/packages/toolbox-adk/tests/integration/test_integration.py @@ -32,7 +32,8 @@ from toolbox_core.protocol import Protocol from toolbox_adk import CredentialStrategy, ToolboxTool, ToolboxToolset -from .conftest import TOOLBOX_SERVER_URL_STABLE + +TOOLBOX_SERVER_URL = "http://localhost:5000" # Ensure TOOLBOX_VERSION is set for the fixture if "TOOLBOX_VERSION" not in os.environ: @@ -51,7 +52,7 @@ async def test_load_toolset_and_run(self): # Auth: TOOLBOX_IDENTITY for simplicity in this local test as we don't have ADK identity setup. toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", credentials=CredentialStrategy.toolbox_identity(), ) @@ -85,7 +86,7 @@ async def test_load_toolset_and_run(self): async def test_load_toolset_with_default_protocol(self): """Test initializing toolset with default protocol (MCP).""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", credentials=CredentialStrategy.toolbox_identity(), ) @@ -109,7 +110,7 @@ async def test_load_toolset_with_default_protocol(self): async def test_load_toolset_with_explicit_protocol(self): """Test initializing toolset with specific protocol (MCP_v20251125).""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", credentials=CredentialStrategy.toolbox_identity(), protocol=Protocol.MCP_v20251125, @@ -133,7 +134,7 @@ async def test_load_toolset_with_explicit_protocol(self): async def test_partial_loading_by_names(self): toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -153,7 +154,7 @@ async def test_partial_loading_by_names(self): async def test_bound_params_e2e(self): # Test binding param at toolset level toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-n-rows"], bound_params={"num_rows": "2"}, credentials=CredentialStrategy.toolbox_identity(), @@ -169,7 +170,7 @@ async def test_bound_params_e2e(self): async def test_3lo_flow_simulation(self): toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, # Load a specific tool that we know the arguments for tool_names=["get-n-rows"], credentials=CredentialStrategy.user_identity( @@ -266,7 +267,7 @@ async def test_3lo_flow_simulation(self): async def test_manual_token_integration(self): """Test the MANUAL_TOKEN strategy.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", credentials=CredentialStrategy.manual_token(token="fake-manual-token"), ) @@ -285,7 +286,7 @@ async def test_manual_credentials_integration(self): mock_creds.token = "fake-creds-token" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", credentials=CredentialStrategy.manual_credentials(credentials=mock_creds), ) @@ -298,7 +299,7 @@ async def test_manual_credentials_integration(self): async def test_api_key_integration(self): """Test the API_KEY strategy.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", credentials=CredentialStrategy.api_key(key="my-key", header_name="x-foo"), ) @@ -334,7 +335,7 @@ async def test_adk_integration_optional_params(self): # 3. Use in Toolset toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", credentials=strategy, ) @@ -358,7 +359,7 @@ async def test_header_collision(self): creds_token = "Bearer strategy-token" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name="my-toolset", additional_headers={"Authorization": manual_override}, credentials=CredentialStrategy.manual_token(token="strategy-token"), @@ -392,7 +393,7 @@ async def test_load_toolset_specific( ): """Load a specific toolset""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, toolset_name=toolset_name, credentials=CredentialStrategy.toolbox_identity(), ) @@ -407,7 +408,7 @@ async def test_load_toolset_specific( async def test_load_toolset_default(self): """Load the default toolset, i.e. all tools.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, credentials=CredentialStrategy.toolbox_identity(), ) try: @@ -430,7 +431,7 @@ async def test_load_toolset_default(self): async def test_run_tool(self): """Invoke a tool.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -452,7 +453,7 @@ async def test_run_tool(self): async def test_run_tool_missing_params(self): """Invoke a tool with missing params.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -471,7 +472,7 @@ async def test_run_tool_missing_params(self): async def test_run_tool_wrong_param_type(self): """Invoke a tool with wrong param type.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-n-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -495,7 +496,7 @@ class TestBindParams: async def test_bind_params(self): """Bind a param to an existing tool.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-n-rows"], bound_params={"num_rows": "3"}, credentials=CredentialStrategy.toolbox_identity(), @@ -517,7 +518,7 @@ async def test_bind_params(self): async def test_bind_params_callable(self): """Bind a callable param to an existing tool.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-n-rows"], bound_params={"num_rows": lambda: "3"}, credentials=CredentialStrategy.toolbox_identity(), @@ -543,7 +544,7 @@ class TestAuth: async def test_run_tool_unauth_with_auth(self, auth_token2: str): """Tests running a tool that doesn't require auth, with auth provided.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-row-by-id"], auth_token_getters={"my-test-auth": lambda: auth_token2}, credentials=CredentialStrategy.toolbox_identity(), @@ -560,7 +561,7 @@ async def test_run_tool_unauth_with_auth(self, auth_token2: str): async def test_run_multiple_tools_unauth_with_auth(self, auth_token2: str): """Tests running multiple tools that don't require auth, verifying formatting of tool lists.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-row-by-id", "search-rows"], auth_token_getters={"my-test-auth": lambda: auth_token2}, credentials=CredentialStrategy.toolbox_identity(), @@ -577,7 +578,7 @@ async def test_run_multiple_tools_unauth_with_auth(self, auth_token2: str): async def test_run_multiple_tools_partial_auth_usage(self, auth_token2: str): """Tests that when some tokens are used and some aren't across diverse tools, only the truly unused tokens appear in the error.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=[ "get-row-by-id-auth", "search-rows", @@ -602,7 +603,7 @@ async def test_run_tool_no_auth(self): """Tests running a tool requiring auth without providing auth.""" # Note: We load it without auth getters. Invocation should fail. toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-row-by-id-auth"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -622,7 +623,7 @@ async def test_run_tool_no_auth(self): async def test_run_tool_wrong_auth(self, auth_token2: str): """Tests running a tool with incorrect auth.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-row-by-id-auth"], auth_token_getters={"my-test-auth": lambda: auth_token2}, credentials=CredentialStrategy.toolbox_identity(), @@ -643,7 +644,7 @@ async def test_run_tool_wrong_auth(self, auth_token2: str): async def test_run_tool_auth(self, auth_token1: str): """Tests running a tool with correct auth.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-row-by-id-auth"], auth_token_getters={"my-test-auth": lambda: auth_token1}, credentials=CredentialStrategy.toolbox_identity(), @@ -665,7 +666,7 @@ async def get_token_asynchronously(): return auth_token1 toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["get-row-by-id-auth"], auth_token_getters={"my-test-auth": get_token_asynchronously}, credentials=CredentialStrategy.toolbox_identity(), @@ -691,7 +692,7 @@ class TestOptionalParams: async def test_run_tool_with_optional_params_omitted(self): """Invoke a tool providing only the required parameter.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["search-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -710,7 +711,7 @@ async def test_run_tool_with_optional_params_omitted(self): async def test_run_tool_with_all_valid_params(self): """Invoke a tool providing all parameters.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["search-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -730,7 +731,7 @@ async def test_run_tool_with_all_valid_params(self): async def test_run_tool_with_missing_required_param(self): """Invoke a tool without its required parameter.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["search-rows"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -755,7 +756,7 @@ class TestMapParams: async def test_run_tool_with_map_params(self): """Invoke a tool with valid map parameters.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["process-data"], credentials=CredentialStrategy.toolbox_identity(), ) @@ -786,7 +787,7 @@ async def test_run_tool_with_map_params(self): async def test_run_tool_with_wrong_map_value_type(self): """Invoke a tool with a map parameter having the wrong value type.""" toolset = ToolboxToolset( - server_url=TOOLBOX_SERVER_URL_STABLE, + server_url=TOOLBOX_SERVER_URL, tool_names=["process-data"], credentials=CredentialStrategy.toolbox_identity(), ) diff --git a/packages/toolbox-langchain/tests/test_e2e.py b/packages/toolbox-langchain/tests/test_e2e.py index b1af22d4e..e8722d98b 100644 --- a/packages/toolbox-langchain/tests/test_e2e.py +++ b/packages/toolbox-langchain/tests/test_e2e.py @@ -39,7 +39,8 @@ from pydantic import ValidationError from toolbox_langchain.client import ToolboxClient -from .conftest import TOOLBOX_SERVER_URL_STABLE + +TOOLBOX_SERVER_URL = "http://localhost:5000" @pytest.mark.asyncio @@ -48,7 +49,7 @@ class TestE2EClientAsync: @pytest.fixture(scope="function") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) + toolbox = ToolboxClient(TOOLBOX_SERVER_URL) return toolbox @pytest_asyncio.fixture(scope="function") @@ -195,7 +196,7 @@ class TestE2EClientSync: @pytest.fixture(scope="session") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) + toolbox = ToolboxClient(TOOLBOX_SERVER_URL) return toolbox @pytest.fixture(scope="function") diff --git a/packages/toolbox-llamaindex/tests/test_e2e.py b/packages/toolbox-llamaindex/tests/test_e2e.py index eb41aecd2..ae631ea8d 100644 --- a/packages/toolbox-llamaindex/tests/test_e2e.py +++ b/packages/toolbox-llamaindex/tests/test_e2e.py @@ -39,7 +39,8 @@ from pydantic import ValidationError from toolbox_llamaindex.client import ToolboxClient -from .conftest import TOOLBOX_SERVER_URL_STABLE + +TOOLBOX_SERVER_URL = "http://localhost:5000" @pytest.mark.asyncio @@ -48,7 +49,7 @@ class TestE2EClientAsync: @pytest.fixture(scope="function") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) + toolbox = ToolboxClient(TOOLBOX_SERVER_URL) return toolbox @pytest_asyncio.fixture(scope="function") @@ -195,7 +196,7 @@ class TestE2EClientSync: @pytest.fixture(scope="session") def toolbox(self): """Provides a ToolboxClient instance for each test.""" - toolbox = ToolboxClient(TOOLBOX_SERVER_URL_STABLE) + toolbox = ToolboxClient(TOOLBOX_SERVER_URL) return toolbox @pytest.fixture(scope="function") From 0b24b6ed71d57f187c7fe16a0be09d4ce3ceada8 Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Mon, 6 Jul 2026 12:34:30 +0530 Subject: [PATCH 3/8] test: update E2E protocol fallback assertions to support dynamic server URLs and ignore noise warnings in tool tests --- packages/toolbox-core/tests/test_e2e_mcp.py | 18 ++++++++++++------ packages/toolbox-core/tests/test_tool.py | 9 +++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/toolbox-core/tests/test_e2e_mcp.py b/packages/toolbox-core/tests/test_e2e_mcp.py index c35695ffa..7d7724a41 100644 --- a/packages/toolbox-core/tests/test_e2e_mcp.py +++ b/packages/toolbox-core/tests/test_e2e_mcp.py @@ -100,20 +100,26 @@ async def test_run_tool_missing_params(self, get_n_rows_tool: ToolboxTool): with pytest.raises(TypeError, match="missing a required argument: 'num_rows'"): await get_n_rows_tool() - async def test_protocol_fallback_e2e(self): + async def test_protocol_fallback_e2e(self, toolbox_server_url): """Tests that a client using MCP_LATEST can fallback to an older protocol against a server that doesn't support the latest version.""" # The E2E server currently does not support DRAFT 2026, so this will trigger a fallback. async with ToolboxClient( - "http://localhost:5000", protocol=Protocol.MCP_LATEST + toolbox_server_url, protocol=Protocol.MCP_LATEST ) as client: tool = await client.load_tool("get-n-rows") response = await tool(num_rows="1") assert "row1" in response # Verify that fallback occurred by checking the transport's final protocol version - assert ( - client._ToolboxClient__transport._protocol_version - != Protocol.MCP_LATEST.value - ) + if "5000" in toolbox_server_url: + assert ( + client._ToolboxClient__transport._protocol_version + != Protocol.MCP_LATEST.value + ) + else: + assert ( + client._ToolboxClient__transport._protocol_version + == Protocol.MCP_LATEST.value + ) async def test_run_tool_wrong_param_type(self, get_n_rows_tool: ToolboxTool): """Invoke a tool with wrong param type.""" diff --git a/packages/toolbox-core/tests/test_tool.py b/packages/toolbox-core/tests/test_tool.py index 1b23db3ae..9e5ad85b2 100644 --- a/packages/toolbox-core/tests/test_tool.py +++ b/packages/toolbox-core/tests/test_tool.py @@ -409,9 +409,14 @@ def test_tool_init_basic(http_session, sample_tool_params, sample_tool_descripti bound_params={}, client_headers={}, ) + relevant_warnings = [ + w + for w in record + if not issubclass(w.category, (ResourceWarning, DeprecationWarning)) + ] assert ( - len(record) == 0 - ), f"ToolboxTool instantiation unexpectedly warned: {[f'{w.category.__name__}: {w.message}' for w in record]}" + len(relevant_warnings) == 0 + ), f"ToolboxTool instantiation unexpectedly warned: {[f'{w.category.__name__}: {w.message}' for w in relevant_warnings]}" assert tool_instance.__name__ == TEST_TOOL_NAME assert inspect.iscoroutinefunction(tool_instance.__call__) From 16c8888ca29b4a708be3bcdc222bc2cd14fc9ef7 Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Mon, 6 Jul 2026 12:46:15 +0530 Subject: [PATCH 4/8] chore: update package dependencies and metadata across all sub-packages --- packages/toolbox-adk/pyproject.toml | 3 ++- packages/toolbox-core/pyproject.toml | 3 ++- packages/toolbox-langchain/pyproject.toml | 1 + packages/toolbox-llamaindex/pyproject.toml | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/toolbox-adk/pyproject.toml b/packages/toolbox-adk/pyproject.toml index 3ad5c35e4..54b9a2002 100644 --- a/packages/toolbox-adk/pyproject.toml +++ b/packages/toolbox-adk/pyproject.toml @@ -40,7 +40,8 @@ test = [ "pytest==9.0.3", "pytest-asyncio==1.4.0", "pytest-cov==7.1.0", - "pytest-mock==3.15.1" + "pytest-mock==3.15.1", + "numpy<2", # Pinned to <2 to prevent mypy syntax errors on python 3.10 with numpy 2.x stubs, ] # Tells setuptools that packages are under the 'src' directory diff --git a/packages/toolbox-core/pyproject.toml b/packages/toolbox-core/pyproject.toml index 6c2bf1a6d..6e44e0a11 100644 --- a/packages/toolbox-core/pyproject.toml +++ b/packages/toolbox-core/pyproject.toml @@ -60,7 +60,8 @@ test = [ "google-cloud-secret-manager==2.28.0", "google-cloud-storage==3.10.1", "aioresponses==0.7.8", - "toolbox-core[telemetry]" + "toolbox-core[telemetry]", + "numpy<2", # Pinned to <2 to prevent mypy syntax errors on python 3.10 with numpy 2.x stubs ] [build-system] requires = ["setuptools"] diff --git a/packages/toolbox-langchain/pyproject.toml b/packages/toolbox-langchain/pyproject.toml index 247fdbfab..76e0845a1 100644 --- a/packages/toolbox-langchain/pyproject.toml +++ b/packages/toolbox-langchain/pyproject.toml @@ -53,6 +53,7 @@ test = [ "Pillow==12.2.0; python_version >= '3.10'", "google-cloud-secret-manager==2.28.0", "google-cloud-storage==3.10.1", + "numpy<2", # Pinned to <2 to prevent mypy syntax errors on python 3.10 with numpy 2.x stubs ] [build-system] diff --git a/packages/toolbox-llamaindex/pyproject.toml b/packages/toolbox-llamaindex/pyproject.toml index ec8107ead..fe801b2cc 100644 --- a/packages/toolbox-llamaindex/pyproject.toml +++ b/packages/toolbox-llamaindex/pyproject.toml @@ -53,6 +53,7 @@ test = [ "Pillow==12.2.0; python_version >= '3.10'", "google-cloud-secret-manager==2.28.0", "google-cloud-storage==3.10.1", + "numpy<2", # Pinned to <2 to prevent mypy syntax errors on python 3.10 with numpy 2.x stubs ] [build-system] From 919fa3f1270c52a1be4ec1ae9220bd04c939bb04 Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Mon, 6 Jul 2026 14:55:14 +0530 Subject: [PATCH 5/8] refactor: remove platform-specific .exe extension from toolbox binary path resolution in test configurations --- packages/toolbox-adk/tests/integration/conftest.py | 3 +-- packages/toolbox-core/tests/conftest.py | 3 +-- packages/toolbox-langchain/tests/conftest.py | 3 +-- packages/toolbox-llamaindex/tests/conftest.py | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/toolbox-adk/tests/integration/conftest.py b/packages/toolbox-adk/tests/integration/conftest.py index 78d96aa0f..52e1f45c3 100644 --- a/packages/toolbox-adk/tests/integration/conftest.py +++ b/packages/toolbox-adk/tests/integration/conftest.py @@ -78,8 +78,7 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - ext = ".exe" if os_system == "windows" else "" - return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox" def get_auth_token(client_id: str) -> str: diff --git a/packages/toolbox-core/tests/conftest.py b/packages/toolbox-core/tests/conftest.py index 45fc53305..4e39ec6da 100644 --- a/packages/toolbox-core/tests/conftest.py +++ b/packages/toolbox-core/tests/conftest.py @@ -78,8 +78,7 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - ext = ".exe" if os_system == "windows" else "" - return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox" def get_auth_token(client_id: str) -> str: diff --git a/packages/toolbox-langchain/tests/conftest.py b/packages/toolbox-langchain/tests/conftest.py index 7771c24a7..fd13590aa 100644 --- a/packages/toolbox-langchain/tests/conftest.py +++ b/packages/toolbox-langchain/tests/conftest.py @@ -78,8 +78,7 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - ext = ".exe" if os_system == "windows" else "" - return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox" def get_auth_token(client_id: str) -> str: diff --git a/packages/toolbox-llamaindex/tests/conftest.py b/packages/toolbox-llamaindex/tests/conftest.py index d108293bf..c99f2474f 100644 --- a/packages/toolbox-llamaindex/tests/conftest.py +++ b/packages/toolbox-llamaindex/tests/conftest.py @@ -78,8 +78,7 @@ def get_toolbox_binary_url(toolbox_version: str) -> str: arch = ( "arm64" if os_system == "darwin" and platform.machine() == "arm64" else "amd64" ) - ext = ".exe" if os_system == "windows" else "" - return f"v{toolbox_version}/{os_system}/{arch}/toolbox{ext}" + return f"v{toolbox_version}/{os_system}/{arch}/toolbox" def get_auth_token(client_id: str) -> str: From 629b3235bbb78643e2161fbdc2565b5ce8c5086b Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Mon, 6 Jul 2026 15:04:24 +0530 Subject: [PATCH 6/8] refactor: convert patch_toolbox_client_url to an explicit fixture and apply it to E2E tests via pytestmark --- packages/toolbox-core/tests/conftest.py | 2 +- packages/toolbox-core/tests/test_e2e.py | 2 ++ packages/toolbox-core/tests/test_e2e_mcp.py | 2 ++ packages/toolbox-core/tests/test_sync_e2e.py | 2 ++ packages/toolbox-langchain/tests/conftest.py | 2 +- packages/toolbox-langchain/tests/test_e2e.py | 2 ++ packages/toolbox-llamaindex/tests/conftest.py | 2 +- packages/toolbox-llamaindex/tests/test_e2e.py | 2 ++ 8 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/toolbox-core/tests/conftest.py b/packages/toolbox-core/tests/conftest.py index 4e39ec6da..4c43f1956 100644 --- a/packages/toolbox-core/tests/conftest.py +++ b/packages/toolbox-core/tests/conftest.py @@ -190,7 +190,7 @@ def toolbox_server_url(request) -> str: return request.param -@pytest.fixture(autouse=True) +@pytest.fixture() def patch_toolbox_client_url(toolbox_server_url): from toolbox_core.client import ToolboxClient from toolbox_core.sync_client import ToolboxSyncClient diff --git a/packages/toolbox-core/tests/test_e2e.py b/packages/toolbox-core/tests/test_e2e.py index 0b926e178..9f1f6b01f 100644 --- a/packages/toolbox-core/tests/test_e2e.py +++ b/packages/toolbox-core/tests/test_e2e.py @@ -23,6 +23,8 @@ from toolbox_core.protocol import Protocol from toolbox_core.tool import ToolboxTool +pytestmark = pytest.mark.usefixtures("patch_toolbox_client_url") + # --- Shared Fixtures Defined at Module Level --- @pytest_asyncio.fixture(scope="function") diff --git a/packages/toolbox-core/tests/test_e2e_mcp.py b/packages/toolbox-core/tests/test_e2e_mcp.py index 7d7724a41..d9dc6a6cc 100644 --- a/packages/toolbox-core/tests/test_e2e_mcp.py +++ b/packages/toolbox-core/tests/test_e2e_mcp.py @@ -23,6 +23,8 @@ from toolbox_core.protocol import Protocol from toolbox_core.tool import ToolboxTool +pytestmark = pytest.mark.usefixtures("patch_toolbox_client_url") + # TODO: Include draft versions in E2E integration tests once the server # supports SEP-2575 (stateless MCP / Request-Metadata). diff --git a/packages/toolbox-core/tests/test_sync_e2e.py b/packages/toolbox-core/tests/test_sync_e2e.py index a306cedc2..38b90b131 100644 --- a/packages/toolbox-core/tests/test_sync_e2e.py +++ b/packages/toolbox-core/tests/test_sync_e2e.py @@ -17,6 +17,8 @@ from toolbox_core.sync_client import ToolboxSyncClient from toolbox_core.sync_tool import ToolboxSyncTool +pytestmark = pytest.mark.usefixtures("patch_toolbox_client_url") + # --- Shared Fixtures Defined at Module Level --- @pytest.fixture(scope="module") diff --git a/packages/toolbox-langchain/tests/conftest.py b/packages/toolbox-langchain/tests/conftest.py index fd13590aa..3afeb74a7 100644 --- a/packages/toolbox-langchain/tests/conftest.py +++ b/packages/toolbox-langchain/tests/conftest.py @@ -190,7 +190,7 @@ def toolbox_server_url(request) -> str: return request.param -@pytest.fixture(autouse=True) +@pytest.fixture() def patch_toolbox_client_url(toolbox_server_url): from toolbox_core.client import ToolboxClient diff --git a/packages/toolbox-langchain/tests/test_e2e.py b/packages/toolbox-langchain/tests/test_e2e.py index e8722d98b..8291cf4f4 100644 --- a/packages/toolbox-langchain/tests/test_e2e.py +++ b/packages/toolbox-langchain/tests/test_e2e.py @@ -40,6 +40,8 @@ from toolbox_langchain.client import ToolboxClient +pytestmark = pytest.mark.usefixtures("patch_toolbox_client_url") + TOOLBOX_SERVER_URL = "http://localhost:5000" diff --git a/packages/toolbox-llamaindex/tests/conftest.py b/packages/toolbox-llamaindex/tests/conftest.py index c99f2474f..cd20c2694 100644 --- a/packages/toolbox-llamaindex/tests/conftest.py +++ b/packages/toolbox-llamaindex/tests/conftest.py @@ -190,7 +190,7 @@ def toolbox_server_url(request) -> str: return request.param -@pytest.fixture(autouse=True) +@pytest.fixture() def patch_toolbox_client_url(toolbox_server_url): from toolbox_core.client import ToolboxClient diff --git a/packages/toolbox-llamaindex/tests/test_e2e.py b/packages/toolbox-llamaindex/tests/test_e2e.py index ae631ea8d..7664eeb32 100644 --- a/packages/toolbox-llamaindex/tests/test_e2e.py +++ b/packages/toolbox-llamaindex/tests/test_e2e.py @@ -40,6 +40,8 @@ from toolbox_llamaindex.client import ToolboxClient +pytestmark = pytest.mark.usefixtures("patch_toolbox_client_url") + TOOLBOX_SERVER_URL = "http://localhost:5000" From 2281222c55ebf2fe3515ad8373c8f8e6da4b7595 Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Mon, 6 Jul 2026 15:21:06 +0530 Subject: [PATCH 7/8] refactor: reorder imports and constants in test conftest files for consistency --- packages/toolbox-adk/tests/integration/conftest.py | 4 ++-- packages/toolbox-core/tests/conftest.py | 4 ++-- packages/toolbox-langchain/tests/conftest.py | 4 ++-- packages/toolbox-llamaindex/tests/conftest.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/toolbox-adk/tests/integration/conftest.py b/packages/toolbox-adk/tests/integration/conftest.py index 52e1f45c3..5204bf448 100644 --- a/packages/toolbox-adk/tests/integration/conftest.py +++ b/packages/toolbox-adk/tests/integration/conftest.py @@ -26,11 +26,11 @@ import google import pytest +from google.auth import compute_engine +from google.cloud import secretmanager, storage TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" -from google.auth import compute_engine -from google.cloud import secretmanager, storage #### Define Utility Functions diff --git a/packages/toolbox-core/tests/conftest.py b/packages/toolbox-core/tests/conftest.py index 4c43f1956..b78db9db6 100644 --- a/packages/toolbox-core/tests/conftest.py +++ b/packages/toolbox-core/tests/conftest.py @@ -26,11 +26,11 @@ import google import pytest +from google.auth import compute_engine +from google.cloud import secretmanager, storage TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" -from google.auth import compute_engine -from google.cloud import secretmanager, storage #### Define Utility Functions diff --git a/packages/toolbox-langchain/tests/conftest.py b/packages/toolbox-langchain/tests/conftest.py index 3afeb74a7..05d9a175a 100644 --- a/packages/toolbox-langchain/tests/conftest.py +++ b/packages/toolbox-langchain/tests/conftest.py @@ -26,11 +26,11 @@ import google import pytest +from google.auth import compute_engine +from google.cloud import secretmanager, storage TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" -from google.auth import compute_engine -from google.cloud import secretmanager, storage #### Define Utility Functions diff --git a/packages/toolbox-llamaindex/tests/conftest.py b/packages/toolbox-llamaindex/tests/conftest.py index cd20c2694..fa9784f1f 100644 --- a/packages/toolbox-llamaindex/tests/conftest.py +++ b/packages/toolbox-llamaindex/tests/conftest.py @@ -26,11 +26,11 @@ import google import pytest +from google.auth import compute_engine +from google.cloud import secretmanager, storage TOOLBOX_SERVER_URL_STABLE = "http://localhost:5000" TOOLBOX_SERVER_URL_DRAFT = "http://localhost:5001" -from google.auth import compute_engine -from google.cloud import secretmanager, storage #### Define Utility Functions From 905a3608bbbacc73699ad9425eedc24052d1f181 Mon Sep 17 00:00:00 2001 From: Anubhav Dhawan Date: Wed, 8 Jul 2026 13:49:24 +0530 Subject: [PATCH 8/8] fix: remove autouse from patch_toolbox_client_url fixture to prevent unnecessary patching in integration tests --- packages/toolbox-adk/tests/integration/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/toolbox-adk/tests/integration/conftest.py b/packages/toolbox-adk/tests/integration/conftest.py index 5204bf448..5c672547a 100644 --- a/packages/toolbox-adk/tests/integration/conftest.py +++ b/packages/toolbox-adk/tests/integration/conftest.py @@ -206,7 +206,7 @@ def toolbox_server_url(request) -> str: return request.param -@pytest.fixture(autouse=True) +@pytest.fixture() def patch_toolbox_client_url(toolbox_server_url): from toolbox_adk.toolset import ToolboxToolset