Skip to content

Commit f009816

Browse files
speedstorm1copybara-github
authored andcommitted
feat: make Pydantic AnyUrls json serializable in requests
FUTURE_COPYBARA_INTEGRATE_REVIEW=#1558 from googleapis:release-please--branches--main a73a12f PiperOrigin-RevId: 826167091
1 parent 5936664 commit f009816

File tree

3 files changed

+74
-4
lines changed

3 files changed

+74
-4
lines changed

google/genai/_api_client.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,11 +1112,19 @@ def _request_once(
11121112
http_request.headers['x-goog-user-project'] = (
11131113
self._credentials.quota_project_id
11141114
)
1115-
data = json.dumps(http_request.data) if http_request.data else None
1115+
data = json.dumps(
1116+
_common.convert_uri_to_string(http_request.data)
1117+
if http_request.data
1118+
else None
1119+
)
11161120
else:
11171121
if http_request.data:
11181122
if not isinstance(http_request.data, bytes):
1119-
data = json.dumps(http_request.data) if http_request.data else None
1123+
data = json.dumps(
1124+
_common.convert_uri_to_string(http_request.data)
1125+
if http_request.data
1126+
else None
1127+
)
11201128
else:
11211129
data = http_request.data
11221130

@@ -1180,11 +1188,11 @@ async def _async_request_once(
11801188
http_request.headers['x-goog-user-project'] = (
11811189
self._credentials.quota_project_id
11821190
)
1183-
data = json.dumps(http_request.data) if http_request.data else None
1191+
data = json.dumps(_common.convert_uri_to_string(http_request.data) if http_request.data else None)
11841192
else:
11851193
if http_request.data:
11861194
if not isinstance(http_request.data, bytes):
1187-
data = json.dumps(http_request.data) if http_request.data else None
1195+
data = json.dumps(_common.convert_uri_to_string(http_request.data) if http_request.data else None)
11881196
else:
11891197
data = http_request.data
11901198

google/genai/_common.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,3 +776,15 @@ def recursive_dict_update(
776776
target_dict[key] = value
777777
else:
778778
target_dict[key] = value
779+
780+
781+
def convert_uri_to_string(obj: Any) -> Any:
782+
if isinstance(obj, dict):
783+
return {
784+
k: convert_uri_to_string(v) for k, v in obj.items()
785+
}
786+
elif isinstance(obj, list):
787+
return [convert_uri_to_string(i) for i in obj]
788+
elif type(obj).__name__ == 'AnyUrl':
789+
return str(obj)
790+
return obj

google/genai/tests/common/test_common.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from enum import Enum
2020
import inspect
21+
import json
2122
import logging
2223
import textwrap
2324
import typing
@@ -765,3 +766,52 @@ def test_move_value_by_path():
765766
}
766767

767768
assert data == expected
769+
770+
771+
def test_convert_uri_to_string():
772+
url = pydantic.AnyUrl("http://example.com")
773+
data = {
774+
"name": "test",
775+
"url": url,
776+
"nested_list": [1, {"url_in_list": url}],
777+
"nested_dict": {
778+
"url_in_dict": url,
779+
},
780+
}
781+
expected = {
782+
"name": "test",
783+
"url": "http://example.com/",
784+
"nested_list": [1, {"url_in_list": "http://example.com/"}],
785+
"nested_dict": {
786+
"url_in_dict": "http://example.com/",
787+
},
788+
}
789+
result = _common.convert_uri_to_string(data)
790+
assert result == expected
791+
792+
793+
def test_convert_uri_to_string_no_anyurl():
794+
data = {"name": "test", "value": 1}
795+
result = _common.convert_uri_to_string(data)
796+
assert result == data
797+
798+
799+
def test_convert_uri_to_string_list_of_anyurl():
800+
url = pydantic.AnyUrl("http://example.com")
801+
data = [url, {"url": url}]
802+
expected = ["http://example.com/", {"url": "http://example.com/"}]
803+
result = _common.convert_uri_to_string(data)
804+
assert result == expected
805+
806+
807+
def test_convert_uri_to_string_anyurl_direct():
808+
url = pydantic.AnyUrl("http://example.com")
809+
result = _common.convert_uri_to_string(url)
810+
assert result == "http://example.com/"
811+
812+
813+
def test_json_dumps_fails_with_anyurl():
814+
url = pydantic.AnyUrl("http://example.com")
815+
data = {"url": url}
816+
with pytest.raises(TypeError):
817+
json.dumps(data)

0 commit comments

Comments
 (0)