Skip to content

Commit 8e1b69c

Browse files
Require concrete serialized output in extract tool
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent dfd786f commit 8e1b69c

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

hyperbrowser/tools/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,10 @@ def _serialize_extract_tool_data(data: Any) -> str:
207207
if data is None:
208208
return ""
209209
try:
210-
return json.dumps(data, allow_nan=False)
210+
serialized_data = json.dumps(data, allow_nan=False)
211+
if type(serialized_data) is not str:
212+
raise TypeError("serialized extract tool response data must be a string")
213+
return serialized_data
211214
except HyperbrowserError:
212215
raise
213216
except Exception as exc:

tests/test_tools_extract.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,49 @@ async def run():
579579
assert exc_info.value.original_error is not None
580580

581581

582+
def test_extract_tool_runnable_wraps_non_string_serialization_results(
583+
monkeypatch: pytest.MonkeyPatch,
584+
):
585+
class _SerializedString(str):
586+
pass
587+
588+
def _return_string_subclass(*_args, **_kwargs):
589+
return _SerializedString('{"ok": true}')
590+
591+
monkeypatch.setattr(tools_module.json, "dumps", _return_string_subclass)
592+
593+
with pytest.raises(
594+
HyperbrowserError, match="Failed to serialize extract tool response data"
595+
) as exc_info:
596+
WebsiteExtractTool.runnable(_SyncClient(), {"urls": ["https://example.com"]})
597+
598+
assert isinstance(exc_info.value.original_error, TypeError)
599+
600+
601+
def test_extract_tool_async_runnable_wraps_non_string_serialization_results(
602+
monkeypatch: pytest.MonkeyPatch,
603+
):
604+
class _SerializedString(str):
605+
pass
606+
607+
def _return_string_subclass(*_args, **_kwargs):
608+
return _SerializedString('{"ok": true}')
609+
610+
monkeypatch.setattr(tools_module.json, "dumps", _return_string_subclass)
611+
612+
async def run():
613+
return await WebsiteExtractTool.async_runnable(
614+
_AsyncClient(), {"urls": ["https://example.com"]}
615+
)
616+
617+
with pytest.raises(
618+
HyperbrowserError, match="Failed to serialize extract tool response data"
619+
) as exc_info:
620+
asyncio.run(run())
621+
622+
assert isinstance(exc_info.value.original_error, TypeError)
623+
624+
582625
def test_extract_tool_runnable_rejects_nan_json_payloads():
583626
client = _SyncClient(response_data={"value": math.nan})
584627

0 commit comments

Comments
 (0)