|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
| 15 | +from typing import Any |
| 16 | +from typing import Callable |
15 | 17 | from typing import Optional |
| 18 | +from typing import Union |
16 | 19 |
|
17 | 20 | from google.adk.agents.invocation_context import InvocationContext |
18 | 21 | from google.adk.agents.sequential_agent import SequentialAgent |
@@ -157,6 +160,54 @@ async def run_async(self, **kwargs): |
157 | 160 | assert t2._defers_response is True |
158 | 161 |
|
159 | 162 |
|
| 163 | +def _sample_handler(value: str) -> str: |
| 164 | + return value |
| 165 | + |
| 166 | + |
| 167 | +def test_from_config_resolves_parametrized_callable(): |
| 168 | + """A ``Callable[..., ...]`` arg is resolved, not skipped as unsupported.""" |
| 169 | + from google.adk.tools.tool_configs import ToolArgsConfig |
| 170 | + |
| 171 | + class CallbackTool(BaseTool): |
| 172 | + |
| 173 | + def __init__(self, handler: Callable[[str], str]): |
| 174 | + super().__init__(name='callback_tool', description='desc') |
| 175 | + self.handler = handler |
| 176 | + |
| 177 | + async def run_async(self, **kwargs): |
| 178 | + pass |
| 179 | + |
| 180 | + config = ToolArgsConfig(handler=f'{__name__}._sample_handler') |
| 181 | + tool = CallbackTool.from_config(config, '') |
| 182 | + |
| 183 | + assert tool.handler is _sample_handler |
| 184 | + |
| 185 | + |
| 186 | +def test_from_config_skips_list_of_non_class(): |
| 187 | + """Non-class ``list`` element types are skipped, not an issubclass error.""" |
| 188 | + from google.adk.tools.tool_configs import ToolArgsConfig |
| 189 | + |
| 190 | + class ListTool(BaseTool): |
| 191 | + |
| 192 | + def __init__( |
| 193 | + self, |
| 194 | + unions: Optional[list[Union[int, str]]] = None, |
| 195 | + anys: Optional[list[Any]] = None, |
| 196 | + ): |
| 197 | + super().__init__(name='list_tool', description='desc') |
| 198 | + self.unions = unions |
| 199 | + self.anys = anys |
| 200 | + |
| 201 | + async def run_async(self, **kwargs): |
| 202 | + pass |
| 203 | + |
| 204 | + config = ToolArgsConfig(unions=[1, 'two'], anys=[1, 'two']) |
| 205 | + tool = ListTool.from_config(config, '') |
| 206 | + |
| 207 | + assert tool.unions is None |
| 208 | + assert tool.anys is None |
| 209 | + |
| 210 | + |
160 | 211 | def test_response_scheduling_defaults_to_none(): |
161 | 212 | """response_scheduling defaults to None, preserving existing behavior.""" |
162 | 213 |
|
|
0 commit comments