1515
1616import asyncio
1717from asyncio import AbstractEventLoop
18+ from concurrent .futures import Future
1819from threading import Thread
1920from typing import Any , Callable , Coroutine , Mapping , Optional , Union
2021
@@ -86,6 +87,103 @@ def close(self):
8687 coro = self .__async_client .close ()
8788 asyncio .run_coroutine_threadsafe (coro , self .__loop ).result ()
8889
90+ def _load_tool_future (
91+ self ,
92+ name : str ,
93+ auth_token_getters : dict [str , Callable [[], str ]] = {},
94+ bound_params : Mapping [str , Union [Callable [[], Any ], Any ]] = {},
95+ ) -> Future [ToolboxSyncTool ]:
96+ """
97+ Asynchronously initiates the loading of a specific tool from the Toolbox service.
98+
99+ This method schedules the tool loading operation on a background event loop
100+ and immediately returns a `concurrent.futures.Future`. This allows other
101+ operations to proceed while the tool is being loaded. To get the actual
102+ `ToolboxSyncTool` instance, call `.result()` on the returned future, which
103+ will block until the tool is available or an error occurs.
104+
105+ Args:
106+ name: The unique name or identifier of the tool to load.
107+ auth_token_getters: A mapping of authentication service names to
108+ callables that return the corresponding authentication token.
109+ bound_params: A mapping of parameter names to bind to specific values or
110+ callables that are called to produce values as needed.
111+
112+ Returns:
113+ A `concurrent.futures.Future` that, upon successful completion, will
114+ yield a `ToolboxSyncTool` instance representing the loaded tool.
115+
116+ Raises:
117+ ValueError: If the background event loop or thread (required for asynchronous
118+ operations) is not running or properly initialized.
119+
120+ """
121+
122+ async def async_worker () -> ToolboxSyncTool :
123+ if not self .__loop or not self .__thread :
124+ raise ValueError ("Background loop or thread cannot be None." )
125+ async_tool = await self .__async_client .load_tool (
126+ name , auth_token_getters , bound_params
127+ )
128+ return ToolboxSyncTool (async_tool , self .__loop , self .__thread )
129+
130+ if not self .__loop or not self .__thread :
131+ raise ValueError ("Background loop or thread cannot be None." )
132+ return asyncio .run_coroutine_threadsafe (async_worker (), self .__loop )
133+
134+ def _load_toolset_future (
135+ self ,
136+ name : Optional [str ] = None ,
137+ auth_token_getters : dict [str , Callable [[], str ]] = {},
138+ bound_params : Mapping [str , Union [Callable [[], Any ], Any ]] = {},
139+ strict : bool = False ,
140+ ) -> Future [list [ToolboxSyncTool ]]:
141+ """
142+ Asynchronously initiates loading of all tools within a specified toolset.
143+
144+ This method schedules the toolset loading operation on a background event
145+ loop and returns a `concurrent.futures.Future` without blocking.
146+ The future's result will be a list of `ToolboxSyncTool` instances.
147+ Call `.result()` on the returned future to wait for completion and get
148+ the list of tools.
149+
150+ Args:
151+ name: Name of the toolset to load tools.
152+ auth_token_getters: A mapping of authentication service names to
153+ callables that return the corresponding authentication token.
154+ bound_params: A mapping of parameter names to bind to specific values or
155+ callables that are called to produce values as needed.
156+ strict: If True, raises an error if *any* loaded tool instance fails
157+ to utilize at least one provided parameter or auth token (if any
158+ provided). If False (default), raises an error only if a
159+ user-provided parameter or auth token cannot be applied to *any*
160+ loaded tool across the set.
161+
162+ Returns:
163+ A `concurrent.futures.Future` that, upon successful completion, will
164+ yield a list of `ToolboxSyncTool` instances.
165+
166+ Raises:
167+ ValueError: If the background event loop or thread is not running,
168+ or if validation fails based on the `strict` flag during
169+ the underlying asynchronous loading process.
170+ """
171+
172+ async def async_worker () -> list [ToolboxSyncTool ]:
173+ if not self .__loop or not self .__thread :
174+ raise ValueError ("Background loop or thread cannot be None." )
175+ async_tools = await self .__async_client .load_toolset (
176+ name , auth_token_getters , bound_params , strict
177+ )
178+ return [
179+ ToolboxSyncTool (async_tool , self .__loop , self .__thread )
180+ for async_tool in async_tools
181+ ]
182+
183+ if not self .__loop or not self .__thread :
184+ raise ValueError ("Background loop or thread cannot be None." )
185+ return asyncio .run_coroutine_threadsafe (async_worker (), self .__loop )
186+
89187 def load_tool (
90188 self ,
91189 name : str ,
@@ -111,13 +209,7 @@ def load_tool(
111209 for execution. The specific arguments and behavior of the callable
112210 depend on the tool itself.
113211 """
114- coro = self .__async_client .load_tool (name , auth_token_getters , bound_params )
115-
116- if not self .__loop or not self .__thread :
117- raise ValueError ("Background loop or thread cannot be None." )
118-
119- async_tool = asyncio .run_coroutine_threadsafe (coro , self .__loop ).result ()
120- return ToolboxSyncTool (async_tool , self .__loop , self .__thread )
212+ return self ._load_tool_future (name , auth_token_getters , bound_params ).result ()
121213
122214 def load_toolset (
123215 self ,
@@ -148,18 +240,9 @@ def load_toolset(
148240 Raises:
149241 ValueError: If validation fails based on the `strict` flag.
150242 """
151- coro = self .__async_client . load_toolset (
243+ return self ._load_toolset_future (
152244 name , auth_token_getters , bound_params , strict
153- )
154-
155- if not self .__loop or not self .__thread :
156- raise ValueError ("Background loop or thread cannot be None." )
157-
158- async_tools = asyncio .run_coroutine_threadsafe (coro , self .__loop ).result ()
159- return [
160- ToolboxSyncTool (async_tool , self .__loop , self .__thread )
161- for async_tool in async_tools
162- ]
245+ ).result ()
163246
164247 def add_headers (
165248 self , headers : Mapping [str , Union [Callable , Coroutine , str ]]
0 commit comments