Skip to content

Commit 916c865

Browse files
committed
chore: Delint
1 parent 4945c4f commit 916c865

File tree

1 file changed

+23
-83
lines changed

1 file changed

+23
-83
lines changed

packages/toolbox-core/tests/test_sync_client.py

Lines changed: 23 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def manage_sync_client_class_state():
6161

6262

6363
@pytest.fixture()
64-
def test_tool_str_schema(): # Renamed to avoid conflict if original fixture is imported
64+
def test_tool_str_schema():
6565
return ToolSchema(
6666
description="Test Tool with String input",
6767
parameters=[
@@ -73,7 +73,7 @@ def test_tool_str_schema(): # Renamed to avoid conflict if original fixture is
7373

7474

7575
@pytest.fixture()
76-
def test_tool_int_bool_schema(): # Renamed
76+
def test_tool_int_bool_schema():
7777
return ToolSchema(
7878
description="Test Tool with Int, Bool",
7979
parameters=[
@@ -84,7 +84,7 @@ def test_tool_int_bool_schema(): # Renamed
8484

8585

8686
@pytest.fixture()
87-
def test_tool_auth_schema(): # Renamed
87+
def test_tool_auth_schema():
8888
return ToolSchema(
8989
description="Test Tool with Int,Bool+Auth",
9090
parameters=[
@@ -104,7 +104,7 @@ def tool_schema_minimal():
104104
return ToolSchema(description="Minimal Test Tool", parameters=[])
105105

106106

107-
# --- Helper Functions for Mocking (from existing tests) ---
107+
# --- Helper Functions for Mocking ---
108108
def mock_tool_load(
109109
aio_resp: aioresponses,
110110
tool_name: str,
@@ -113,9 +113,7 @@ def mock_tool_load(
113113
server_version: str = "0.0.0",
114114
status: int = 200,
115115
callback: Optional[Callable] = None,
116-
payload_override: Optional[
117-
Any
118-
] = None, # Changed from Callable to Any for flexibility
116+
payload_override: Optional[Any] = None,
119117
):
120118
url = f"{base_url}/api/tool/{tool_name}"
121119
payload_data = {}
@@ -162,15 +160,9 @@ def mock_tool_invoke(
162160
def test_sync_client_initialization_and_loop_management():
163161
"""Tests that the event loop and thread are managed correctly at class level."""
164162
client1 = ToolboxSyncClient(TEST_BASE_URL)
165-
assert (
166-
client1._ToolboxSyncClient__loop is not None
167-
), "Loop should be created"
168-
assert (
169-
client1._ToolboxSyncClient__thread is not None
170-
), "Thread should be created"
171-
assert (
172-
client1._ToolboxSyncClient__thread.is_alive()
173-
), "Thread should be running"
163+
assert client1._ToolboxSyncClient__loop is not None, "Loop should be created"
164+
assert client1._ToolboxSyncClient__thread is not None, "Thread should be created"
165+
assert client1._ToolboxSyncClient__thread.is_alive(), "Thread should be running"
174166
assert isinstance(
175167
client1._ToolboxSyncClient__async_client, ToolboxClient
176168
), "Async client should be ToolboxClient instance"
@@ -180,9 +172,7 @@ def test_sync_client_initialization_and_loop_management():
180172

181173
client2 = ToolboxSyncClient(TEST_BASE_URL) # Should reuse existing loop/thread
182174
assert client2._ToolboxSyncClient__loop is loop1, "Loop should be reused"
183-
assert (
184-
client2._ToolboxSyncClient__thread is thread1
185-
), "Thread should be reused"
175+
assert client2._ToolboxSyncClient__thread is thread1, "Thread should be reused"
186176
assert isinstance(client2._ToolboxSyncClient__async_client, ToolboxClient)
187177

188178
client1.close() # Closes its async_client's session
@@ -192,22 +182,11 @@ def test_sync_client_initialization_and_loop_management():
192182

193183
def test_sync_client_close_method():
194184
"""Tests the close() method of ToolboxSyncClient."""
195-
# We need to mock the underlying async_client's close method.
196-
# The __init__ of ToolboxSyncClient creates the async_client in a thread.
197-
# Patching `ToolboxClient` class to control the instance it produces.
198-
199-
# This specific test has an issue: `async_client.close()` is a coroutine.
200-
# `ToolboxSyncClient.close()` calls `asyncio.run_coroutine_threadsafe(coro, self.__loop).result()`.
201-
# The `self.__loop` in `close()` (and other methods) refers to `ToolboxSyncClient._ToolboxSyncClient__loop`.
202-
203185
mock_async_client_instance = AsyncMock(spec=ToolboxClient)
204186
mock_async_client_instance.close = AsyncMock(
205187
return_value=None
206188
) # close() is a coroutine
207189

208-
# Patch 'create_client' to return our mocked async client instance
209-
# This is tricky because create_client is an inner async function.
210-
# A better way: patch ToolboxClient constructor.
211190
with patch(
212191
"toolbox_core.sync_client.ToolboxClient",
213192
return_value=mock_async_client_instance,
@@ -224,9 +203,6 @@ def test_sync_client_close_method():
224203

225204
def test_sync_client_context_manager(aioresponses, tool_schema_minimal):
226205
"""Tests the context manager (__enter__ and __exit__) functionality."""
227-
# Use aioresponses to ensure close is effective (though hard to check session state directly)
228-
# The main check is that close() is called on exit.
229-
230206
with patch.object(
231207
ToolboxSyncClient, "close", wraps=ToolboxSyncClient.close, autospec=True
232208
) as mock_close_method:
@@ -267,16 +243,13 @@ def test_sync_load_tool_success(aioresponses, test_tool_str_schema):
267243
test_tool_str_schema.description
268244
+ f"\n\nArgs:\n param1 (str): Description of Param1" # This format comes from ToolboxTool
269245
)
270-
# This assertion depends on the mock ToolboxTool's __doc__ generation or the real one
271-
# For now, we check that the doc is based on the schema's description
272246
assert test_tool_str_schema.description in loaded_tool.__doc__
273247

274248
sig = inspect.signature(loaded_tool)
275249
assert list(sig.parameters.keys()) == [
276250
p.name for p in test_tool_str_schema.parameters
277251
]
278252

279-
# Invoke the synchronous tool
280253
result = loaded_tool(param1="some value")
281254
assert result == "sync_tool_ok"
282255

@@ -351,7 +324,7 @@ def test_sync_load_tool_not_found_in_manifest(aioresponses, test_tool_str_schema
351324
# The error comes from the underlying async client's parsing
352325
with pytest.raises(
353326
ValueError,
354-
match=f"Tool '{REQUESTED_TOOL_NAME}' not found!", # Adjusted error message if ToolboxClient is source
327+
match=f"Tool '{REQUESTED_TOOL_NAME}' not found!",
355328
):
356329
client.load_tool(REQUESTED_TOOL_NAME)
357330

@@ -397,21 +370,15 @@ def post_callback(url, **kwargs):
397370
def test_sync_add_headers_duplicate_fail(aioresponses):
398371
"""Tests that adding a duplicate header via add_headers raises ValueError (from async client)."""
399372
initial_headers = {"X-Initial-Header": "initial_value"}
400-
401-
# The error for duplicate headers is raised by the underlying ToolboxClient.
402-
# We need to ensure ToolboxSyncClient correctly calls and propagates it.
403-
# For this, we can mock the async_client's add_headers.
404-
405373
mock_async_client = AsyncMock(spec=ToolboxClient)
406374

407375
# Configure add_headers to simulate the ValueError from ToolboxClient
408376
async def mock_add_headers_async(headers):
409377
# Simulate ToolboxClient's check
410-
if "X-Initial-Header" in headers: # simplified check
378+
if "X-Initial-Header" in headers:
411379
raise ValueError("Client header(s) `X-Initial-Header` already registered")
412380

413381
mock_async_client.add_headers = AsyncMock(side_effect=mock_add_headers_async)
414-
# mock_async_client.close = AsyncMock() # For context manager
415382

416383
with patch(
417384
"toolbox_core.sync_client.ToolboxClient", return_value=mock_async_client
@@ -426,7 +393,7 @@ async def mock_add_headers_async(headers):
426393
client.add_headers({"X-Initial-Header": "another_value"})
427394

428395

429-
def test_load_tool_raises_if_loop_or_thread_none(test_tool_str_schema):
396+
def test_load_tool_raises_if_loop_or_thread_none():
430397
"""
431398
Tests that load_tool and load_toolset raise ValueError if the class-level
432399
event loop or thread is None when accessed.
@@ -464,14 +431,13 @@ def test_load_tool_raises_if_loop_or_thread_none(test_tool_str_schema):
464431

465432
class TestSyncAuth:
466433
@pytest.fixture
467-
def expected_header_token(self): # Renamed to avoid clash
434+
def expected_header_token(self):
468435
return "sync_auth_token_for_testing"
469436

470437
@pytest.fixture
471-
def tool_name_auth(self): # Renamed
438+
def tool_name_auth(self):
472439
return "sync_auth_tool1"
473440

474-
475441
def test_auth_with_load_tool_success(
476442
self,
477443
tool_name_auth,
@@ -489,7 +455,9 @@ def test_auth_with_load_tool_success(
489455
)
490456

491457
def require_headers_callback(url, **kwargs):
492-
assert kwargs["headers"].get("my-auth-service_token") == expected_header_token
458+
assert (
459+
kwargs["headers"].get("my-auth-service_token") == expected_header_token
460+
)
493461
return CallbackResult(status=200, payload={"result": "auth_ok"})
494462

495463
aioresponses.post(
@@ -505,7 +473,6 @@ def token_handler():
505473
tool = client.load_tool(
506474
tool_name_auth, auth_token_getters={"my-auth-service": token_handler}
507475
)
508-
# Tool invocation depends on parameters; test_tool_auth_schema has argA (int), argB (bool with auth)
509476
result = tool(argA=5) # argB is the authed param in schema
510477
assert result == "auth_ok"
511478

@@ -526,7 +493,9 @@ def test_auth_with_add_token_success(
526493
)
527494

528495
def require_headers_callback(url, **kwargs):
529-
assert kwargs["headers"].get("my-auth-service_token") == expected_header_token
496+
assert (
497+
kwargs["headers"].get("my-auth-service_token") == expected_header_token
498+
)
530499
return CallbackResult(status=200, payload={"result": "auth_ok"})
531500

532501
aioresponses.post(
@@ -540,7 +509,6 @@ def token_handler():
540509
return expected_header_token
541510

542511
tool = client.load_tool(tool_name_auth)
543-
# Assuming ToolboxSyncTool.add_auth_token_getters works by wrapping async tool's method
544512
authed_tool = tool.add_auth_token_getters(
545513
{"my-auth-service": token_handler}
546514
)
@@ -558,13 +526,6 @@ def test_auth_with_load_tool_fail_no_token(
558526
payload=manifest.model_dump(),
559527
status=200,
560528
)
561-
# Server will reject if token is missing and required by its logic / schema implies it
562-
# The require_headers_callback in this class's fixture handles the 400
563-
# For this test, the error should be raised during tool invocation if mock Tool requires it
564-
# Or, if the server itself validates based on schema, the POST might fail.
565-
# The mock ToolboxTool's __call__ has a simplified auth check.
566-
567-
# If the server responds with 400 due to missing token in payload
568529
aioresponses.post(
569530
f"{TEST_BASE_URL}/api/tool/{tool_name_auth}/invoke",
570531
payload={"error": "Missing token"},
@@ -575,8 +536,9 @@ def test_auth_with_load_tool_fail_no_token(
575536
tool = client.load_tool(tool_name_auth)
576537
# Invocation should fail
577538
with pytest.raises(
578-
ValueError, match="One or more of the following authn services are required to invoke this tool: my-auth-service"
579-
): # Match error from server
539+
ValueError,
540+
match="One or more of the following authn services are required to invoke this tool: my-auth-service",
541+
): # Match error from client
580542
tool(argA=15, argB=True)
581543

582544
def test_add_auth_token_getters_duplicate_fail(
@@ -598,30 +560,10 @@ def test_add_auth_token_getters_duplicate_fail(
598560

599561
# First addition should work
600562
authed_tool = tool.add_auth_token_getters({AUTH_SERVICE: lambda: "token1"})
601-
# The error for duplicate registration is typically raised by the underlying async tool/client logic
602-
# My mock ToolboxTool.add_auth_token_getters currently overwrites.
603-
# The original test for ToolboxClient implies `_ToolboxTool__auth_service_token_getters`
604-
# The check should be in ToolboxTool's add_auth_token_getters.
605-
# For ToolboxSyncClient, the error would propagate if ToolboxTool raises it.
606-
# Let's assume ToolboxTool is robust.
607-
# If the original test `TestAuth.test_add_auth_token_getters_duplicate_fail` passed,
608-
# it's because `ToolboxTool.add_auth_token_getters` raised that ValueError.
609-
# My mock `ToolboxTool` needs to be updated or the test adjusted.
610-
# For now, assuming it propagates:
611563
with pytest.raises(
612564
ValueError,
613565
match=f"Authentication source\\(s\\) `{AUTH_SERVICE}` already registered in tool `{tool_name_auth}`.",
614566
):
615-
# This error message implies the state is checked *before* adding.
616-
# The mock ToolboxTool's add_auth_token_getters would need to check self._auth_getters.
617-
# This test may need a more sophisticated mock for ToolboxTool or it tests ToolboxClient behavior.
618-
# Given the prompt, this is testing the wrapper. If the error originates from the wrapped object, it should propagate.
619-
# The error message is from the original `ToolboxClient` test suite.
620-
# This test would pass if the *async* `ToolboxTool.add_auth_token_getters`
621-
# has the logic to raise this error.
622-
# For the sync wrapper, we're testing that it correctly calls the async method
623-
# and re-wraps, and propagates exceptions.
624-
# Let's assume the async tool raises it.
625567
authed_tool.add_auth_token_getters({AUTH_SERVICE: lambda: "token2"})
626568

627569
def test_add_auth_token_getters_missing_fail(
@@ -642,7 +584,6 @@ def test_add_auth_token_getters_missing_fail(
642584

643585
with pytest.raises(
644586
ValueError,
645-
# This error comes from validation logic within ToolboxTool or ToolboxClient upon tool creation/configuration
646587
match=f"Authentication source\\(s\\) `{UNUSED_AUTH_SERVICE}` unused by tool `{tool_name_auth}`.",
647588
):
648589
tool.add_auth_token_getters({UNUSED_AUTH_SERVICE: lambda: "token"})
@@ -665,7 +606,6 @@ def test_constructor_getters_missing_fail(
665606
ValueError,
666607
match=f"Validation failed for tool '{tool_name_auth}': unused auth tokens: {UNUSED_AUTH_SERVICE}.",
667608
):
668-
# This validation happens in ToolboxClient.load_tool based on schema vs getters
669609
client.load_tool(
670610
tool_name_auth,
671611
auth_token_getters={UNUSED_AUTH_SERVICE: lambda: "token"},

0 commit comments

Comments
 (0)