Skip to content

Commit 0fc894b

Browse files
committed
test: WIP for E2E tests
1 parent e859a54 commit 0fc894b

File tree

4 files changed

+62
-78
lines changed

4 files changed

+62
-78
lines changed

packages/toolbox-core/src/toolbox_core/sync_client.py

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from .client import ToolboxClient
2222
from .sync_tool import ToolboxSyncTool
23+
from concurrent.futures import Future
2324

2425

2526
class ToolboxSyncClient:
@@ -85,6 +86,46 @@ def close(self):
8586
coro = self.__async_client.close()
8687
asyncio.run_coroutine_threadsafe(coro, self.__loop).result()
8788

89+
def load_tool_future(
90+
self,
91+
name: str,
92+
auth_token_getters: dict[str, Callable[[], str]] = {},
93+
bound_params: Mapping[str, Union[Callable[[], Any], Any]] = {},
94+
) -> Future[ToolboxSyncTool]:
95+
"""
96+
Returns a future that loads a tool from the server.
97+
"""
98+
if not self.__loop or not self.__thread:
99+
raise ValueError("Background loop or thread cannot be None.")
100+
101+
async def async_worker() -> ToolboxSyncTool:
102+
async_tool = self.__async_client.load_tool(name, auth_token_getters, bound_params)
103+
return ToolboxSyncTool(async_tool, self.__loop, self.__thread)
104+
return asyncio.run_coroutine_threadsafe(async_worker(), self.__loop)
105+
106+
def load_toolset_future(
107+
self,
108+
name: Optional[str] = None,
109+
auth_token_getters: dict[str, Callable[[], str]] = {},
110+
bound_params: Mapping[str, Union[Callable[[], Any], Any]] = {},
111+
strict: bool = False,
112+
) -> Future[list[ToolboxSyncTool]]:
113+
"""
114+
Returns a future that fetches a toolset and loads all tools defined within it.
115+
"""
116+
if not self.__loop or not self.__thread:
117+
raise ValueError("Background loop or thread cannot be None.")
118+
119+
async def async_worker() -> list[ToolboxSyncTool]:
120+
async_tools = await self.__async_client.load_toolset(
121+
name, auth_token_getters, bound_params, strict
122+
)
123+
return [
124+
ToolboxSyncTool(async_tool, self.__loop, self.__thread)
125+
for async_tool in async_tools
126+
]
127+
return asyncio.run_coroutine_threadsafe(async_worker(), self.__loop)
128+
88129
def load_tool(
89130
self,
90131
name: str,
@@ -110,13 +151,7 @@ def load_tool(
110151
for execution. The specific arguments and behavior of the callable
111152
depend on the tool itself.
112153
"""
113-
coro = self.__async_client.load_tool(name, auth_token_getters, bound_params)
114-
115-
if not self.__loop or not self.__thread:
116-
raise ValueError("Background loop or thread cannot be None.")
117-
118-
async_tool = asyncio.run_coroutine_threadsafe(coro, self.__loop).result()
119-
return ToolboxSyncTool(async_tool, self.__loop, self.__thread)
154+
return self.load_tool_future(name, auth_token_getters, bound_params).result()
120155

121156
def load_toolset(
122157
self,
@@ -147,18 +182,7 @@ def load_toolset(
147182
Raises:
148183
ValueError: If validation fails based on the `strict` flag.
149184
"""
150-
coro = self.__async_client.load_toolset(
151-
name, auth_token_getters, bound_params, strict
152-
)
153-
154-
if not self.__loop or not self.__thread:
155-
raise ValueError("Background loop or thread cannot be None.")
156-
157-
async_tools = asyncio.run_coroutine_threadsafe(coro, self.__loop).result()
158-
return [
159-
ToolboxSyncTool(async_tool, self.__loop, self.__thread)
160-
for async_tool in async_tools
161-
]
185+
return self.load_toolset_future(name, auth_token_getters, bound_params, strict).result()
162186

163187
def add_headers(
164188
self, headers: Mapping[str, Union[Callable, Coroutine, str]]

packages/toolbox-core/src/toolbox_core/sync_tool.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from .protocol import ParameterSchema
2323
from .tool import ToolboxTool
24+
from concurrent.futures import Future
2425

2526

2627
class ToolboxSyncTool:
@@ -129,6 +130,13 @@ def _auth_service_token_getters(self) -> Mapping[str, Callable[[], str]]:
129130
def _client_headers(self) -> Mapping[str, Union[Callable, Coroutine, str]]:
130131
return self.__async_tool._client_headers
131132

133+
def call_future(self, *args: Any, **kwargs: Any) -> Future[str]:
134+
"""
135+
Returns future that calls the remote tool with the provided arguments.
136+
"""
137+
coro = self.__async_tool(*args, **kwargs)
138+
return asyncio.run_coroutine_threadsafe(coro, self.__loop)
139+
132140
def __call__(self, *args: Any, **kwargs: Any) -> str:
133141
"""
134142
Synchronously calls the remote tool with the provided arguments.
@@ -143,8 +151,7 @@ def __call__(self, *args: Any, **kwargs: Any) -> str:
143151
Returns:
144152
The string result returned by the remote tool execution.
145153
"""
146-
coro = self.__async_tool(*args, **kwargs)
147-
return asyncio.run_coroutine_threadsafe(coro, self.__loop).result()
154+
return self.call_future(*args, **kwargs).result()
148155

149156
def add_auth_token_getters(
150157
self,

packages/toolbox-langchain/src/toolbox_langchain/client.py

Lines changed: 8 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import asyncio
15+
from asyncio import wrap_future
1616
from typing import Any, Callable, Optional, Union
1717
from warnings import warn
1818

@@ -85,30 +85,12 @@ async def aload_tool(
8585
)
8686
auth_token_getters = auth_headers
8787

88-
coro = self.__core_client._async_client.load_tool(
88+
core_tool = await wrap_future(self.__core_client.aload_tool(
8989
name=tool_name,
9090
auth_token_getters=auth_token_getters,
9191
bound_params=bound_params,
92-
)
93-
94-
if not self.__core_client._loop:
95-
# If a loop has not been provided, attempt to run in current thread.
96-
core_tool = await coro
97-
else:
98-
# Otherwise, run in the background thread.
99-
core_tool = await asyncio.wrap_future(
100-
asyncio.run_coroutine_threadsafe(coro, self.__core_client._loop)
101-
)
102-
103-
if not self.__core_client._loop or not self.__core_client._thread:
104-
raise ValueError("Background loop or thread cannot be None.")
105-
106-
core_sync_tool = ToolboxSyncTool(
107-
core_tool,
108-
self.__core_client._loop,
109-
self.__core_client._thread,
110-
)
111-
return ToolboxTool(core_tool=core_sync_tool)
92+
))
93+
return ToolboxTool(core_tool=core_tool)
11294

11395
async def aload_toolset(
11496
self,
@@ -167,36 +149,16 @@ async def aload_toolset(
167149
)
168150
auth_token_getters = auth_headers
169151

170-
coro = self.__core_client._async_client.load_toolset(
152+
core_tools = await wrap_future(self.__core_client.aload_toolset(
171153
name=toolset_name,
172154
auth_token_getters=auth_token_getters,
173155
bound_params=bound_params,
174156
strict=strict,
175-
)
176-
177-
if not self.__core_client._loop:
178-
# If a loop has not been provided, attempt to run in current thread.
179-
core_tools = await coro
180-
else:
181-
# Otherwise, run in the background thread.
182-
core_tools = await asyncio.wrap_future(
183-
asyncio.run_coroutine_threadsafe(coro, self.__core_client._loop)
184-
)
185-
186-
if not self.__core_client._loop or not self.__core_client._thread:
187-
raise ValueError("Background loop or thread cannot be None.")
157+
))
188158

189-
core_sync_tools = [
190-
ToolboxSyncTool(
191-
core_tool,
192-
self.__core_client._loop,
193-
self.__core_client._thread,
194-
)
195-
for core_tool in core_tools
196-
]
197159
tools = []
198-
for core_sync_tool in core_sync_tools:
199-
tools.append(ToolboxTool(core_tool=core_sync_tool))
160+
for core_tool in core_tools:
161+
tools.append(ToolboxTool(core_tool=core_tool))
200162
return tools
201163

202164
def load_tool(

packages/toolbox-langchain/src/toolbox_langchain/tools.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import asyncio
15+
from asyncio import wrap_future
1616
from typing import Any, Callable, Union
1717

1818
from deprecated import deprecated
@@ -50,16 +50,7 @@ def _run(self, **kwargs: Any) -> str:
5050
return self.__core_tool(**kwargs)
5151

5252
async def _arun(self, **kwargs: Any) -> str:
53-
coro = self.__core_tool._async_tool(**kwargs)
54-
55-
# If a loop has not been provided, attempt to run in current thread.
56-
if not self.__core_tool._loop:
57-
return await coro
58-
59-
# Otherwise, run in the background thread.
60-
return await asyncio.wrap_future(
61-
asyncio.run_coroutine_threadsafe(coro, self.__core_tool._loop)
62-
)
53+
return await wrap_future(self.__core_tool._async_tool.arun(**kwargs))
6354

6455
def add_auth_token_getters(
6556
self, auth_token_getters: dict[str, Callable[[], str]]

0 commit comments

Comments
 (0)