@@ -131,6 +131,60 @@ async def test_load_toolset_success(aioresponses, test_tool_str, test_tool_int_b
131
131
assert {t .__name__ for t in tools } == manifest .tools .keys ()
132
132
133
133
134
+ @pytest .mark .asyncio
135
+ async def test_invoke_tool_server_error (aioresponses , test_tool_str ):
136
+ """Tests that invoking a tool raises an Exception when the server returns an
137
+ error status."""
138
+ TOOL_NAME = "server_error_tool"
139
+ ERROR_MESSAGE = "Simulated Server Error"
140
+ manifest = ManifestSchema (serverVersion = "0.0.0" , tools = {TOOL_NAME : test_tool_str })
141
+
142
+ aioresponses .get (
143
+ f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } " ,
144
+ payload = manifest .model_dump (),
145
+ status = 200 ,
146
+ )
147
+ aioresponses .post (
148
+ f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } /invoke" ,
149
+ payload = {"error" : ERROR_MESSAGE },
150
+ status = 500 ,
151
+ )
152
+
153
+ async with ToolboxClient (TEST_BASE_URL ) as client :
154
+ loaded_tool = await client .load_tool (TOOL_NAME )
155
+
156
+ with pytest .raises (Exception , match = ERROR_MESSAGE ):
157
+ await loaded_tool (param1 = "some input" )
158
+
159
+
160
+ @pytest .mark .asyncio
161
+ async def test_load_tool_not_found_in_manifest (aioresponses , test_tool_str ):
162
+ """
163
+ Tests that load_tool raises an Exception when the requested tool name
164
+ is not found in the manifest returned by the server, using existing fixtures.
165
+ """
166
+ ACTUAL_TOOL_IN_MANIFEST = "actual_tool_abc"
167
+ REQUESTED_TOOL_NAME = "non_existent_tool_xyz"
168
+
169
+ manifest = ManifestSchema (
170
+ serverVersion = "0.0.0" , tools = {ACTUAL_TOOL_IN_MANIFEST : test_tool_str }
171
+ )
172
+
173
+ aioresponses .get (
174
+ f"{ TEST_BASE_URL } /api/tool/{ REQUESTED_TOOL_NAME } " ,
175
+ payload = manifest .model_dump (),
176
+ status = 200 ,
177
+ )
178
+
179
+ async with ToolboxClient (TEST_BASE_URL ) as client :
180
+ with pytest .raises (Exception , match = f"Tool '{ REQUESTED_TOOL_NAME } ' not found!" ):
181
+ await client .load_tool (REQUESTED_TOOL_NAME )
182
+
183
+ aioresponses .assert_called_once_with (
184
+ f"{ TEST_BASE_URL } /api/tool/{ REQUESTED_TOOL_NAME } " , method = "GET"
185
+ )
186
+
187
+
134
188
class TestAuth :
135
189
136
190
@pytest .fixture
@@ -183,7 +237,7 @@ def token_handler():
183
237
tool = await client .load_tool (
184
238
tool_name , auth_token_getters = {"my-auth-service" : token_handler }
185
239
)
186
- res = await tool (5 )
240
+ await tool (5 )
187
241
188
242
@pytest .mark .asyncio
189
243
async def test_auth_with_add_token_success (
@@ -196,20 +250,35 @@ def token_handler():
196
250
197
251
tool = await client .load_tool (tool_name )
198
252
tool = tool .add_auth_token_getters ({"my-auth-service" : token_handler })
199
- res = await tool (5 )
253
+ await tool (5 )
200
254
201
255
@pytest .mark .asyncio
202
256
async def test_auth_with_load_tool_fail_no_token (
203
257
self , tool_name , expected_header , client
204
258
):
205
259
"""Tests 'load_tool' with auth token is specified."""
206
260
207
- def token_handler ():
208
- return expected_header
209
-
210
261
tool = await client .load_tool (tool_name )
211
262
with pytest .raises (Exception ):
212
- res = await tool (5 )
263
+ await tool (5 )
264
+
265
+ @pytest .mark .asyncio
266
+ async def test_add_auth_token_getters_duplicate_fail (self , tool_name , client ):
267
+ """
268
+ Tests that adding a duplicate auth token getter raises ValueError.
269
+ """
270
+ AUTH_SERVICE = "my-auth-service"
271
+
272
+ tool = await client .load_tool (tool_name )
273
+
274
+ authed_tool = tool .add_auth_token_getters ({AUTH_SERVICE : {}})
275
+ assert AUTH_SERVICE in authed_tool ._ToolboxTool__auth_service_token_getters
276
+
277
+ with pytest .raises (
278
+ ValueError ,
279
+ match = f"Authentication source\\ (s\\ ) `{ AUTH_SERVICE } ` already registered in tool `{ tool_name } `." ,
280
+ ):
281
+ authed_tool .add_auth_token_getters ({AUTH_SERVICE : {}})
213
282
214
283
215
284
class TestBoundParameter :
@@ -319,62 +388,15 @@ async def test_bind_param_fail(self, tool_name, client):
319
388
with pytest .raises (Exception ):
320
389
tool = tool .bind_parameters ({"argC" : lambda : 5 })
321
390
391
+ @pytest .mark .asyncio
392
+ async def test_bind_param_static_value_success (self , tool_name , client ):
393
+ """
394
+ Tests bind_parameters method with a static value.
395
+ """
322
396
323
- @pytest .mark .asyncio
324
- async def test_invoke_tool_server_error (aioresponses , test_tool_str ):
325
- """Tests that invoking a tool raises an Exception when the server returns an
326
- error status."""
327
- TOOL_NAME = "server_error_tool"
328
- ERROR_MESSAGE = "Simulated Server Error"
329
- manifest = ManifestSchema (serverVersion = "0.0.0" , tools = {TOOL_NAME : test_tool_str })
330
-
331
- aioresponses .get (
332
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } " ,
333
- payload = manifest .model_dump (),
334
- status = 200 ,
335
- )
336
- aioresponses .post (
337
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } /invoke" ,
338
- payload = {"error" : ERROR_MESSAGE },
339
- status = 500 ,
340
- )
341
-
342
- async with ToolboxClient (TEST_BASE_URL ) as client :
343
- loaded_tool = await client .load_tool (TOOL_NAME )
344
-
345
- with pytest .raises (Exception , match = ERROR_MESSAGE ):
346
- await loaded_tool (param1 = "some input" )
347
-
348
-
349
- @pytest .mark .asyncio
350
- async def test_bind_param_static_value_success (aioresponses , test_tool_int_bool ):
351
- """
352
- Tests bind_parameters method with a static value.
353
- """
354
- TOOL_NAME = "async_bind_tool"
355
- manifest = ManifestSchema (
356
- serverVersion = "0.0.0" , tools = {TOOL_NAME : test_tool_int_bool }
357
- )
358
-
359
- aioresponses .get (
360
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } " ,
361
- payload = manifest .model_dump (),
362
- status = 200 ,
363
- )
364
-
365
- def reflect_parameters (url , ** kwargs ):
366
- received_params = kwargs .get ("json" , {})
367
- return CallbackResult (status = 200 , payload = {"result" : received_params })
368
-
369
- aioresponses .post (
370
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } /invoke" ,
371
- callback = reflect_parameters ,
372
- )
373
-
374
- bound_value = "Test value"
397
+ bound_value = "Test value"
375
398
376
- async with ToolboxClient (TEST_BASE_URL ) as client :
377
- tool = await client .load_tool (TOOL_NAME )
399
+ tool = await client .load_tool (tool_name )
378
400
bound_tool = tool .bind_parameters ({"argB" : bound_value })
379
401
380
402
assert bound_tool is not tool
@@ -386,37 +408,16 @@ def reflect_parameters(url, **kwargs):
386
408
387
409
assert res_payload == {"argA" : passed_value_a , "argB" : bound_value }
388
410
411
+ @pytest .mark .asyncio
412
+ async def test_bind_param_sync_callable_value_success (self , tool_name , client ):
413
+ """
414
+ Tests bind_parameters method with a sync callable value.
415
+ """
389
416
390
- @pytest .mark .asyncio
391
- async def test_bind_param_sync_callable_value_success (aioresponses , test_tool_int_bool ):
392
- """
393
- Tests bind_parameters method with a sync callable value.
394
- """
395
- TOOL_NAME = "async_bind_tool"
396
- manifest = ManifestSchema (
397
- serverVersion = "0.0.0" , tools = {TOOL_NAME : test_tool_int_bool }
398
- )
399
-
400
- aioresponses .get (
401
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } " ,
402
- payload = manifest .model_dump (),
403
- status = 200 ,
404
- )
405
-
406
- def reflect_parameters (url , ** kwargs ):
407
- received_params = kwargs .get ("json" , {})
408
- return CallbackResult (status = 200 , payload = {"result" : received_params })
409
-
410
- aioresponses .post (
411
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } /invoke" ,
412
- callback = reflect_parameters ,
413
- )
414
-
415
- bound_value_result = True
416
- bound_sync_callable = Mock (return_value = bound_value_result )
417
+ bound_value_result = True
418
+ bound_sync_callable = Mock (return_value = bound_value_result )
417
419
418
- async with ToolboxClient (TEST_BASE_URL ) as client :
419
- tool = await client .load_tool (TOOL_NAME )
420
+ tool = await client .load_tool (tool_name )
420
421
bound_tool = tool .bind_parameters ({"argB" : bound_sync_callable })
421
422
422
423
assert bound_tool is not tool
@@ -429,39 +430,16 @@ def reflect_parameters(url, **kwargs):
429
430
assert res_payload == {"argA" : passed_value_a , "argB" : bound_value_result }
430
431
bound_sync_callable .assert_called_once ()
431
432
433
+ @pytest .mark .asyncio
434
+ async def test_bind_param_async_callable_value_success (self , tool_name , client ):
435
+ """
436
+ Tests bind_parameters method with an async callable value.
437
+ """
432
438
433
- @pytest .mark .asyncio
434
- async def test_bind_param_async_callable_value_success (
435
- aioresponses , test_tool_int_bool
436
- ):
437
- """
438
- Tests bind_parameters method with an async callable value.
439
- """
440
- TOOL_NAME = "async_bind_tool"
441
- manifest = ManifestSchema (
442
- serverVersion = "0.0.0" , tools = {TOOL_NAME : test_tool_int_bool }
443
- )
444
-
445
- aioresponses .get (
446
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } " ,
447
- payload = manifest .model_dump (),
448
- status = 200 ,
449
- )
450
-
451
- def reflect_parameters (url , ** kwargs ):
452
- received_params = kwargs .get ("json" , {})
453
- return CallbackResult (status = 200 , payload = {"result" : received_params })
454
-
455
- aioresponses .post (
456
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } /invoke" ,
457
- callback = reflect_parameters ,
458
- )
459
-
460
- bound_value_result = True
461
- bound_async_callable = AsyncMock (return_value = bound_value_result )
439
+ bound_value_result = True
440
+ bound_async_callable = AsyncMock (return_value = bound_value_result )
462
441
463
- async with ToolboxClient (TEST_BASE_URL ) as client :
464
- tool = await client .load_tool (TOOL_NAME )
442
+ tool = await client .load_tool (tool_name )
465
443
bound_tool = tool .bind_parameters ({"argB" : bound_async_callable })
466
444
467
445
assert bound_tool is not tool
@@ -473,59 +451,3 @@ def reflect_parameters(url, **kwargs):
473
451
474
452
assert res_payload == {"argA" : passed_value_a , "argB" : bound_value_result }
475
453
bound_async_callable .assert_awaited_once ()
476
-
477
-
478
- @pytest .mark .asyncio
479
- async def test_add_auth_token_getters_duplicate_fail (aioresponses , test_tool_auth ):
480
- """
481
- Tests that adding a duplicate auth token getter raises ValueError.
482
- """
483
- TOOL_NAME = "duplicate_auth_tool"
484
- AUTH_SERVICE = "my-auth-service"
485
- manifest = ManifestSchema (serverVersion = "0.0.0" , tools = {TOOL_NAME : test_tool_auth })
486
-
487
- aioresponses .get (
488
- f"{ TEST_BASE_URL } /api/tool/{ TOOL_NAME } " ,
489
- payload = manifest .model_dump (),
490
- status = 200 ,
491
- )
492
-
493
- async with ToolboxClient (TEST_BASE_URL ) as client :
494
- tool = await client .load_tool (TOOL_NAME )
495
-
496
- authed_tool = tool .add_auth_token_getters ({AUTH_SERVICE : {}})
497
- assert AUTH_SERVICE in authed_tool ._ToolboxTool__auth_service_token_getters
498
-
499
- with pytest .raises (
500
- ValueError ,
501
- match = f"Authentication source\\ (s\\ ) `{ AUTH_SERVICE } ` already registered in tool `{ TOOL_NAME } `." ,
502
- ):
503
- authed_tool .add_auth_token_getters ({AUTH_SERVICE : {}})
504
-
505
-
506
- @pytest .mark .asyncio
507
- async def test_load_tool_not_found_in_manifest (aioresponses , test_tool_str ):
508
- """
509
- Tests that load_tool raises an Exception when the requested tool name
510
- is not found in the manifest returned by the server, using existing fixtures.
511
- """
512
- ACTUAL_TOOL_IN_MANIFEST = "actual_tool_abc"
513
- REQUESTED_TOOL_NAME = "non_existent_tool_xyz"
514
-
515
- manifest = ManifestSchema (
516
- serverVersion = "0.0.0" , tools = {ACTUAL_TOOL_IN_MANIFEST : test_tool_str }
517
- )
518
-
519
- aioresponses .get (
520
- f"{ TEST_BASE_URL } /api/tool/{ REQUESTED_TOOL_NAME } " ,
521
- payload = manifest .model_dump (),
522
- status = 200 ,
523
- )
524
-
525
- async with ToolboxClient (TEST_BASE_URL ) as client :
526
- with pytest .raises (Exception , match = f"Tool '{ REQUESTED_TOOL_NAME } ' not found!" ):
527
- await client .load_tool (REQUESTED_TOOL_NAME )
528
-
529
- aioresponses .assert_called_once_with (
530
- f"{ TEST_BASE_URL } /api/tool/{ REQUESTED_TOOL_NAME } " , method = "GET"
531
- )
0 commit comments