google-genai 1.53.0__py3-none-any.whl → 1.55.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. google/genai/__init__.py +1 -0
  2. google/genai/_api_client.py +6 -6
  3. google/genai/_interactions/__init__.py +117 -0
  4. google/genai/_interactions/_base_client.py +2019 -0
  5. google/genai/_interactions/_client.py +511 -0
  6. google/genai/_interactions/_compat.py +234 -0
  7. google/genai/_interactions/_constants.py +29 -0
  8. google/genai/_interactions/_exceptions.py +122 -0
  9. google/genai/_interactions/_files.py +139 -0
  10. google/genai/_interactions/_models.py +873 -0
  11. google/genai/_interactions/_qs.py +165 -0
  12. google/genai/_interactions/_resource.py +58 -0
  13. google/genai/_interactions/_response.py +847 -0
  14. google/genai/_interactions/_streaming.py +354 -0
  15. google/genai/_interactions/_types.py +276 -0
  16. google/genai/_interactions/_utils/__init__.py +79 -0
  17. google/genai/_interactions/_utils/_compat.py +61 -0
  18. google/genai/_interactions/_utils/_datetime_parse.py +151 -0
  19. google/genai/_interactions/_utils/_logs.py +40 -0
  20. google/genai/_interactions/_utils/_proxy.py +80 -0
  21. google/genai/_interactions/_utils/_reflection.py +57 -0
  22. google/genai/_interactions/_utils/_resources_proxy.py +39 -0
  23. google/genai/_interactions/_utils/_streams.py +27 -0
  24. google/genai/_interactions/_utils/_sync.py +73 -0
  25. google/genai/_interactions/_utils/_transform.py +472 -0
  26. google/genai/_interactions/_utils/_typing.py +172 -0
  27. google/genai/_interactions/_utils/_utils.py +437 -0
  28. google/genai/_interactions/_version.py +18 -0
  29. google/genai/_interactions/resources/__init__.py +34 -0
  30. google/genai/_interactions/resources/interactions.py +1350 -0
  31. google/genai/_interactions/types/__init__.py +107 -0
  32. google/genai/_interactions/types/allowed_tools.py +33 -0
  33. google/genai/_interactions/types/allowed_tools_param.py +35 -0
  34. google/genai/_interactions/types/annotation.py +42 -0
  35. google/genai/_interactions/types/annotation_param.py +42 -0
  36. google/genai/_interactions/types/audio_content.py +38 -0
  37. google/genai/_interactions/types/audio_content_param.py +45 -0
  38. google/genai/_interactions/types/audio_mime_type.py +25 -0
  39. google/genai/_interactions/types/audio_mime_type_param.py +27 -0
  40. google/genai/_interactions/types/code_execution_call_arguments.py +33 -0
  41. google/genai/_interactions/types/code_execution_call_arguments_param.py +32 -0
  42. google/genai/_interactions/types/code_execution_call_content.py +37 -0
  43. google/genai/_interactions/types/code_execution_call_content_param.py +37 -0
  44. google/genai/_interactions/types/code_execution_result_content.py +42 -0
  45. google/genai/_interactions/types/code_execution_result_content_param.py +41 -0
  46. google/genai/_interactions/types/content_delta.py +358 -0
  47. google/genai/_interactions/types/content_start.py +79 -0
  48. google/genai/_interactions/types/content_stop.py +35 -0
  49. google/genai/_interactions/types/deep_research_agent_config.py +33 -0
  50. google/genai/_interactions/types/deep_research_agent_config_param.py +32 -0
  51. google/genai/_interactions/types/document_content.py +36 -0
  52. google/genai/_interactions/types/document_content_param.py +43 -0
  53. google/genai/_interactions/types/dynamic_agent_config.py +44 -0
  54. google/genai/_interactions/types/dynamic_agent_config_param.py +33 -0
  55. google/genai/_interactions/types/error_event.py +46 -0
  56. google/genai/_interactions/types/file_search_result_content.py +46 -0
  57. google/genai/_interactions/types/file_search_result_content_param.py +46 -0
  58. google/genai/_interactions/types/function.py +38 -0
  59. google/genai/_interactions/types/function_call_content.py +39 -0
  60. google/genai/_interactions/types/function_call_content_param.py +39 -0
  61. google/genai/_interactions/types/function_param.py +37 -0
  62. google/genai/_interactions/types/function_result_content.py +52 -0
  63. google/genai/_interactions/types/function_result_content_param.py +54 -0
  64. google/genai/_interactions/types/generation_config.py +57 -0
  65. google/genai/_interactions/types/generation_config_param.py +59 -0
  66. google/genai/_interactions/types/google_search_call_arguments.py +29 -0
  67. google/genai/_interactions/types/google_search_call_arguments_param.py +31 -0
  68. google/genai/_interactions/types/google_search_call_content.py +37 -0
  69. google/genai/_interactions/types/google_search_call_content_param.py +37 -0
  70. google/genai/_interactions/types/google_search_result.py +35 -0
  71. google/genai/_interactions/types/google_search_result_content.py +43 -0
  72. google/genai/_interactions/types/google_search_result_content_param.py +44 -0
  73. google/genai/_interactions/types/google_search_result_param.py +35 -0
  74. google/genai/_interactions/types/image_content.py +41 -0
  75. google/genai/_interactions/types/image_content_param.py +48 -0
  76. google/genai/_interactions/types/image_mime_type.py +23 -0
  77. google/genai/_interactions/types/image_mime_type_param.py +25 -0
  78. google/genai/_interactions/types/interaction.py +165 -0
  79. google/genai/_interactions/types/interaction_create_params.py +212 -0
  80. google/genai/_interactions/types/interaction_event.py +37 -0
  81. google/genai/_interactions/types/interaction_get_params.py +46 -0
  82. google/genai/_interactions/types/interaction_sse_event.py +32 -0
  83. google/genai/_interactions/types/interaction_status_update.py +37 -0
  84. google/genai/_interactions/types/mcp_server_tool_call_content.py +42 -0
  85. google/genai/_interactions/types/mcp_server_tool_call_content_param.py +42 -0
  86. google/genai/_interactions/types/mcp_server_tool_result_content.py +52 -0
  87. google/genai/_interactions/types/mcp_server_tool_result_content_param.py +54 -0
  88. google/genai/_interactions/types/model.py +36 -0
  89. google/genai/_interactions/types/model_param.py +38 -0
  90. google/genai/_interactions/types/speech_config.py +35 -0
  91. google/genai/_interactions/types/speech_config_param.py +35 -0
  92. google/genai/_interactions/types/text_content.py +37 -0
  93. google/genai/_interactions/types/text_content_param.py +38 -0
  94. google/genai/_interactions/types/thinking_level.py +22 -0
  95. google/genai/_interactions/types/thought_content.py +41 -0
  96. google/genai/_interactions/types/thought_content_param.py +47 -0
  97. google/genai/_interactions/types/tool.py +100 -0
  98. google/genai/_interactions/types/tool_choice.py +26 -0
  99. google/genai/_interactions/types/tool_choice_config.py +28 -0
  100. google/genai/_interactions/types/tool_choice_config_param.py +29 -0
  101. google/genai/_interactions/types/tool_choice_param.py +28 -0
  102. google/genai/_interactions/types/tool_choice_type.py +22 -0
  103. google/genai/_interactions/types/tool_param.py +97 -0
  104. google/genai/_interactions/types/turn.py +76 -0
  105. google/genai/_interactions/types/turn_param.py +73 -0
  106. google/genai/_interactions/types/url_context_call_arguments.py +29 -0
  107. google/genai/_interactions/types/url_context_call_arguments_param.py +31 -0
  108. google/genai/_interactions/types/url_context_call_content.py +37 -0
  109. google/genai/_interactions/types/url_context_call_content_param.py +37 -0
  110. google/genai/_interactions/types/url_context_result.py +33 -0
  111. google/genai/_interactions/types/url_context_result_content.py +43 -0
  112. google/genai/_interactions/types/url_context_result_content_param.py +44 -0
  113. google/genai/_interactions/types/url_context_result_param.py +32 -0
  114. google/genai/_interactions/types/usage.py +106 -0
  115. google/genai/_interactions/types/usage_param.py +106 -0
  116. google/genai/_interactions/types/video_content.py +41 -0
  117. google/genai/_interactions/types/video_content_param.py +48 -0
  118. google/genai/_interactions/types/video_mime_type.py +36 -0
  119. google/genai/_interactions/types/video_mime_type_param.py +38 -0
  120. google/genai/_live_converters.py +34 -3
  121. google/genai/_tokens_converters.py +5 -0
  122. google/genai/batches.py +62 -55
  123. google/genai/client.py +223 -0
  124. google/genai/errors.py +16 -1
  125. google/genai/file_search_stores.py +60 -60
  126. google/genai/files.py +56 -56
  127. google/genai/interactions.py +17 -0
  128. google/genai/live.py +4 -3
  129. google/genai/models.py +15 -3
  130. google/genai/tests/__init__.py +21 -0
  131. google/genai/tests/afc/__init__.py +21 -0
  132. google/genai/tests/afc/test_convert_if_exist_pydantic_model.py +309 -0
  133. google/genai/tests/afc/test_convert_number_values_for_function_call_args.py +63 -0
  134. google/genai/tests/afc/test_find_afc_incompatible_tool_indexes.py +240 -0
  135. google/genai/tests/afc/test_generate_content_stream_afc.py +530 -0
  136. google/genai/tests/afc/test_generate_content_stream_afc_thoughts.py +77 -0
  137. google/genai/tests/afc/test_get_function_map.py +176 -0
  138. google/genai/tests/afc/test_get_function_response_parts.py +277 -0
  139. google/genai/tests/afc/test_get_max_remote_calls_for_afc.py +130 -0
  140. google/genai/tests/afc/test_invoke_function_from_dict_args.py +241 -0
  141. google/genai/tests/afc/test_raise_error_for_afc_incompatible_config.py +159 -0
  142. google/genai/tests/afc/test_should_append_afc_history.py +53 -0
  143. google/genai/tests/afc/test_should_disable_afc.py +214 -0
  144. google/genai/tests/batches/__init__.py +17 -0
  145. google/genai/tests/batches/test_cancel.py +77 -0
  146. google/genai/tests/batches/test_create.py +78 -0
  147. google/genai/tests/batches/test_create_with_bigquery.py +113 -0
  148. google/genai/tests/batches/test_create_with_file.py +82 -0
  149. google/genai/tests/batches/test_create_with_gcs.py +125 -0
  150. google/genai/tests/batches/test_create_with_inlined_requests.py +255 -0
  151. google/genai/tests/batches/test_delete.py +86 -0
  152. google/genai/tests/batches/test_embedding.py +157 -0
  153. google/genai/tests/batches/test_get.py +78 -0
  154. google/genai/tests/batches/test_list.py +79 -0
  155. google/genai/tests/caches/__init__.py +17 -0
  156. google/genai/tests/caches/constants.py +29 -0
  157. google/genai/tests/caches/test_create.py +210 -0
  158. google/genai/tests/caches/test_create_custom_url.py +105 -0
  159. google/genai/tests/caches/test_delete.py +54 -0
  160. google/genai/tests/caches/test_delete_custom_url.py +52 -0
  161. google/genai/tests/caches/test_get.py +94 -0
  162. google/genai/tests/caches/test_get_custom_url.py +52 -0
  163. google/genai/tests/caches/test_list.py +68 -0
  164. google/genai/tests/caches/test_update.py +70 -0
  165. google/genai/tests/caches/test_update_custom_url.py +58 -0
  166. google/genai/tests/chats/__init__.py +1 -0
  167. google/genai/tests/chats/test_get_history.py +597 -0
  168. google/genai/tests/chats/test_send_message.py +844 -0
  169. google/genai/tests/chats/test_validate_response.py +90 -0
  170. google/genai/tests/client/__init__.py +17 -0
  171. google/genai/tests/client/test_async_stream.py +427 -0
  172. google/genai/tests/client/test_client_close.py +197 -0
  173. google/genai/tests/client/test_client_initialization.py +1687 -0
  174. google/genai/tests/client/test_client_requests.py +355 -0
  175. google/genai/tests/client/test_custom_client.py +77 -0
  176. google/genai/tests/client/test_http_options.py +178 -0
  177. google/genai/tests/client/test_replay_client_equality.py +168 -0
  178. google/genai/tests/client/test_retries.py +846 -0
  179. google/genai/tests/client/test_upload_errors.py +136 -0
  180. google/genai/tests/common/__init__.py +17 -0
  181. google/genai/tests/common/test_common.py +954 -0
  182. google/genai/tests/conftest.py +162 -0
  183. google/genai/tests/documents/__init__.py +17 -0
  184. google/genai/tests/documents/test_delete.py +51 -0
  185. google/genai/tests/documents/test_get.py +85 -0
  186. google/genai/tests/documents/test_list.py +72 -0
  187. google/genai/tests/errors/__init__.py +1 -0
  188. google/genai/tests/errors/test_api_error.py +417 -0
  189. google/genai/tests/file_search_stores/__init__.py +17 -0
  190. google/genai/tests/file_search_stores/test_create.py +66 -0
  191. google/genai/tests/file_search_stores/test_delete.py +64 -0
  192. google/genai/tests/file_search_stores/test_get.py +94 -0
  193. google/genai/tests/file_search_stores/test_import_file.py +112 -0
  194. google/genai/tests/file_search_stores/test_list.py +57 -0
  195. google/genai/tests/file_search_stores/test_upload_to_file_search_store.py +141 -0
  196. google/genai/tests/files/__init__.py +17 -0
  197. google/genai/tests/files/test_delete.py +46 -0
  198. google/genai/tests/files/test_download.py +85 -0
  199. google/genai/tests/files/test_get.py +46 -0
  200. google/genai/tests/files/test_list.py +72 -0
  201. google/genai/tests/files/test_upload.py +255 -0
  202. google/genai/tests/imports/test_no_optional_imports.py +28 -0
  203. google/genai/tests/interactions/__init__.py +0 -0
  204. google/genai/tests/interactions/test_integration.py +80 -0
  205. google/genai/tests/live/__init__.py +16 -0
  206. google/genai/tests/live/test_live.py +2177 -0
  207. google/genai/tests/live/test_live_music.py +362 -0
  208. google/genai/tests/live/test_live_response.py +163 -0
  209. google/genai/tests/live/test_send_client_content.py +147 -0
  210. google/genai/tests/live/test_send_realtime_input.py +268 -0
  211. google/genai/tests/live/test_send_tool_response.py +222 -0
  212. google/genai/tests/local_tokenizer/__init__.py +17 -0
  213. google/genai/tests/local_tokenizer/test_local_tokenizer.py +343 -0
  214. google/genai/tests/local_tokenizer/test_local_tokenizer_loader.py +235 -0
  215. google/genai/tests/mcp/__init__.py +17 -0
  216. google/genai/tests/mcp/test_has_mcp_tool_usage.py +89 -0
  217. google/genai/tests/mcp/test_mcp_to_gemini_tools.py +191 -0
  218. google/genai/tests/mcp/test_parse_config_for_mcp_sessions.py +201 -0
  219. google/genai/tests/mcp/test_parse_config_for_mcp_usage.py +130 -0
  220. google/genai/tests/mcp/test_set_mcp_usage_header.py +72 -0
  221. google/genai/tests/models/__init__.py +17 -0
  222. google/genai/tests/models/constants.py +8 -0
  223. google/genai/tests/models/test_compute_tokens.py +120 -0
  224. google/genai/tests/models/test_count_tokens.py +159 -0
  225. google/genai/tests/models/test_delete.py +107 -0
  226. google/genai/tests/models/test_edit_image.py +264 -0
  227. google/genai/tests/models/test_embed_content.py +94 -0
  228. google/genai/tests/models/test_function_call_streaming.py +442 -0
  229. google/genai/tests/models/test_generate_content.py +2502 -0
  230. google/genai/tests/models/test_generate_content_cached_content.py +132 -0
  231. google/genai/tests/models/test_generate_content_config_zero_value.py +103 -0
  232. google/genai/tests/models/test_generate_content_from_apikey.py +44 -0
  233. google/genai/tests/models/test_generate_content_http_options.py +40 -0
  234. google/genai/tests/models/test_generate_content_image_generation.py +143 -0
  235. google/genai/tests/models/test_generate_content_mcp.py +343 -0
  236. google/genai/tests/models/test_generate_content_media_resolution.py +97 -0
  237. google/genai/tests/models/test_generate_content_model.py +139 -0
  238. google/genai/tests/models/test_generate_content_part.py +821 -0
  239. google/genai/tests/models/test_generate_content_thought.py +76 -0
  240. google/genai/tests/models/test_generate_content_tools.py +1761 -0
  241. google/genai/tests/models/test_generate_images.py +191 -0
  242. google/genai/tests/models/test_generate_videos.py +759 -0
  243. google/genai/tests/models/test_get.py +104 -0
  244. google/genai/tests/models/test_list.py +233 -0
  245. google/genai/tests/models/test_recontext_image.py +189 -0
  246. google/genai/tests/models/test_segment_image.py +148 -0
  247. google/genai/tests/models/test_update.py +95 -0
  248. google/genai/tests/models/test_upscale_image.py +157 -0
  249. google/genai/tests/operations/__init__.py +17 -0
  250. google/genai/tests/operations/test_get.py +38 -0
  251. google/genai/tests/public_samples/__init__.py +17 -0
  252. google/genai/tests/public_samples/test_gemini_text_only.py +34 -0
  253. google/genai/tests/pytest_helper.py +229 -0
  254. google/genai/tests/shared/__init__.py +16 -0
  255. google/genai/tests/shared/batches/__init__.py +14 -0
  256. google/genai/tests/shared/batches/test_create_delete.py +57 -0
  257. google/genai/tests/shared/batches/test_create_get_cancel.py +56 -0
  258. google/genai/tests/shared/batches/test_list.py +40 -0
  259. google/genai/tests/shared/caches/__init__.py +14 -0
  260. google/genai/tests/shared/caches/test_create_get_delete.py +67 -0
  261. google/genai/tests/shared/caches/test_create_update_get.py +71 -0
  262. google/genai/tests/shared/caches/test_list.py +40 -0
  263. google/genai/tests/shared/chats/__init__.py +14 -0
  264. google/genai/tests/shared/chats/test_send_message.py +48 -0
  265. google/genai/tests/shared/chats/test_send_message_stream.py +50 -0
  266. google/genai/tests/shared/files/__init__.py +14 -0
  267. google/genai/tests/shared/files/test_list.py +41 -0
  268. google/genai/tests/shared/files/test_upload_get_delete.py +54 -0
  269. google/genai/tests/shared/models/__init__.py +14 -0
  270. google/genai/tests/shared/models/test_compute_tokens.py +41 -0
  271. google/genai/tests/shared/models/test_count_tokens.py +40 -0
  272. google/genai/tests/shared/models/test_edit_image.py +67 -0
  273. google/genai/tests/shared/models/test_embed.py +40 -0
  274. google/genai/tests/shared/models/test_generate_content.py +39 -0
  275. google/genai/tests/shared/models/test_generate_content_stream.py +54 -0
  276. google/genai/tests/shared/models/test_generate_images.py +40 -0
  277. google/genai/tests/shared/models/test_generate_videos.py +38 -0
  278. google/genai/tests/shared/models/test_list.py +37 -0
  279. google/genai/tests/shared/models/test_recontext_image.py +55 -0
  280. google/genai/tests/shared/models/test_segment_image.py +52 -0
  281. google/genai/tests/shared/models/test_upscale_image.py +52 -0
  282. google/genai/tests/shared/tunings/__init__.py +16 -0
  283. google/genai/tests/shared/tunings/test_create.py +46 -0
  284. google/genai/tests/shared/tunings/test_create_get_cancel.py +56 -0
  285. google/genai/tests/shared/tunings/test_list.py +39 -0
  286. google/genai/tests/tokens/__init__.py +16 -0
  287. google/genai/tests/tokens/test_create.py +154 -0
  288. google/genai/tests/transformers/__init__.py +17 -0
  289. google/genai/tests/transformers/test_blobs.py +71 -0
  290. google/genai/tests/transformers/test_bytes.py +15 -0
  291. google/genai/tests/transformers/test_duck_type.py +96 -0
  292. google/genai/tests/transformers/test_function_responses.py +72 -0
  293. google/genai/tests/transformers/test_schema.py +653 -0
  294. google/genai/tests/transformers/test_t_batch.py +286 -0
  295. google/genai/tests/transformers/test_t_content.py +160 -0
  296. google/genai/tests/transformers/test_t_contents.py +398 -0
  297. google/genai/tests/transformers/test_t_part.py +85 -0
  298. google/genai/tests/transformers/test_t_parts.py +87 -0
  299. google/genai/tests/transformers/test_t_tool.py +157 -0
  300. google/genai/tests/transformers/test_t_tools.py +195 -0
  301. google/genai/tests/tunings/__init__.py +16 -0
  302. google/genai/tests/tunings/test_cancel.py +39 -0
  303. google/genai/tests/tunings/test_end_to_end.py +106 -0
  304. google/genai/tests/tunings/test_get.py +67 -0
  305. google/genai/tests/tunings/test_list.py +75 -0
  306. google/genai/tests/tunings/test_tune.py +268 -0
  307. google/genai/tests/types/__init__.py +16 -0
  308. google/genai/tests/types/test_bytes_internal.py +271 -0
  309. google/genai/tests/types/test_bytes_type.py +152 -0
  310. google/genai/tests/types/test_future.py +101 -0
  311. google/genai/tests/types/test_optional_types.py +36 -0
  312. google/genai/tests/types/test_part_type.py +616 -0
  313. google/genai/tests/types/test_schema_from_json_schema.py +417 -0
  314. google/genai/tests/types/test_schema_json_schema.py +468 -0
  315. google/genai/tests/types/test_types.py +2903 -0
  316. google/genai/tunings.py +57 -57
  317. google/genai/types.py +229 -121
  318. google/genai/version.py +1 -1
  319. {google_genai-1.53.0.dist-info → google_genai-1.55.0.dist-info}/METADATA +4 -2
  320. google_genai-1.55.0.dist-info/RECORD +345 -0
  321. google_genai-1.53.0.dist-info/RECORD +0 -41
  322. {google_genai-1.53.0.dist-info → google_genai-1.55.0.dist-info}/WHEEL +0 -0
  323. {google_genai-1.53.0.dist-info → google_genai-1.55.0.dist-info}/licenses/LICENSE +0 -0
  324. {google_genai-1.53.0.dist-info → google_genai-1.55.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,417 @@
1
+ # Copyright 2025 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the 'License');
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an 'AS IS' BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+
16
+ import logging
17
+ import pydantic
18
+
19
+ from ... import types
20
+
21
+
22
+ def _get_not_none_fields(model: pydantic.BaseModel) -> list[str]:
23
+ """Returns field names in a Pydantic model whose values are not None."""
24
+ return [
25
+ field for field, value in model.model_dump().items() if value is not None
26
+ ]
27
+
28
+
29
+ def test_empty_json_schema_conversion():
30
+ """Test conversion of empty JSONSchema to Schema."""
31
+ json_schema = types.JSONSchema()
32
+ gemini_api_schema = types.Schema.from_json_schema(json_schema=json_schema)
33
+ vertex_ai_schema = types.Schema.from_json_schema(
34
+ json_schema=json_schema, api_option='VERTEX_AI'
35
+ )
36
+
37
+ assert gemini_api_schema == types.Schema()
38
+ assert vertex_ai_schema == types.Schema()
39
+
40
+
41
+ def test_not_null_type_conversion():
42
+ """Test conversion of JSONSchema.type to Schema.type"""
43
+ json_schema_types = [
44
+ 'string',
45
+ 'number',
46
+ 'integer',
47
+ 'boolean',
48
+ 'array',
49
+ 'object',
50
+ ]
51
+ schema_types = [
52
+ 'STRING',
53
+ 'NUMBER',
54
+ 'INTEGER',
55
+ 'BOOLEAN',
56
+ 'ARRAY',
57
+ 'OBJECT',
58
+ ]
59
+ for json_schema_type, expected_type in zip(json_schema_types, schema_types):
60
+ json_schema1 = types.JSONSchema(type=types.JSONSchemaType(json_schema_type))
61
+ json_schema2 = types.JSONSchema(type=json_schema_type)
62
+ gemini_api_schema1 = types.Schema.from_json_schema(json_schema=json_schema1)
63
+ vertex_ai_schema1 = types.Schema.from_json_schema(
64
+ json_schema=json_schema1, api_option='VERTEX_AI'
65
+ )
66
+ gemini_api_schema2 = types.Schema.from_json_schema(json_schema=json_schema2)
67
+ vertex_ai_schema2 = types.Schema.from_json_schema(
68
+ json_schema=json_schema2, api_option='VERTEX_AI'
69
+ )
70
+
71
+ gemini_api_not_none_field_name1 = _get_not_none_fields(gemini_api_schema1)
72
+ vertex_api_not_none_field_name1 = _get_not_none_fields(vertex_ai_schema1)
73
+ gemini_api_not_none_field_name2 = _get_not_none_fields(gemini_api_schema2)
74
+ vertex_ai_not_none_field_name2 = _get_not_none_fields(vertex_ai_schema2)
75
+
76
+ assert gemini_api_schema1.type == expected_type
77
+ assert vertex_ai_schema1.type == expected_type
78
+ assert gemini_api_schema2.type == expected_type
79
+ assert vertex_ai_schema2.type == expected_type
80
+ assert gemini_api_not_none_field_name1 == ['type']
81
+ assert vertex_api_not_none_field_name1 == ['type']
82
+ assert gemini_api_not_none_field_name2 == ['type']
83
+ assert vertex_ai_not_none_field_name2 == ['type']
84
+
85
+
86
+ def test_nullable_conversion():
87
+ """Test conversion of JSONSchema.nullable to Schema.nullable"""
88
+ json_schema1 = types.JSONSchema(
89
+ type=[types.JSONSchemaType('string'), types.JSONSchemaType('null')],
90
+ )
91
+ json_schema2 = types.JSONSchema(
92
+ type=['string', 'null'],
93
+ )
94
+ gemini_api_schema1 = types.Schema.from_json_schema(json_schema=json_schema1)
95
+ vertex_ai_schema1 = types.Schema.from_json_schema(
96
+ json_schema=json_schema1, api_option='VERTEX_AI'
97
+ )
98
+ gemini_api_schema2 = types.Schema.from_json_schema(json_schema=json_schema2)
99
+ vertex_ai_schema2 = types.Schema.from_json_schema(
100
+ json_schema=json_schema2, api_option='VERTEX_AI'
101
+ )
102
+ gemini_api_not_none_field_names1 = _get_not_none_fields(gemini_api_schema1)
103
+ vertex_ai_not_none_field_names1 = _get_not_none_fields(vertex_ai_schema1)
104
+ gemini_api_not_none_field_names2 = _get_not_none_fields(gemini_api_schema2)
105
+ vertex_ai_not_none_field_names2 = _get_not_none_fields(vertex_ai_schema2)
106
+
107
+ assert gemini_api_schema1.nullable
108
+ assert vertex_ai_schema1.nullable
109
+ assert gemini_api_schema2.nullable
110
+ assert vertex_ai_schema2.nullable
111
+ assert set(gemini_api_not_none_field_names1) == set(['type', 'nullable'])
112
+ assert set(vertex_ai_not_none_field_names1) == set(['type', 'nullable'])
113
+ assert set(gemini_api_not_none_field_names2) == set(['type', 'nullable'])
114
+ assert set(vertex_ai_not_none_field_names2) == set(['type', 'nullable'])
115
+
116
+
117
+ def test_nullable_in_union_like_type_conversion():
118
+ """Test conversion of JSONSchema.nullable to Schema.nullable"""
119
+ json_schema1 = types.JSONSchema(
120
+ type=[
121
+ types.JSONSchemaType('string'),
122
+ types.JSONSchemaType('null'),
123
+ types.JSONSchemaType('object'),
124
+ types.JSONSchemaType('number'),
125
+ types.JSONSchemaType('array'),
126
+ types.JSONSchemaType('boolean'),
127
+ types.JSONSchemaType('integer'),
128
+ ],
129
+ )
130
+ gemini_api_schema1 = types.Schema.from_json_schema(json_schema=json_schema1)
131
+ vertex_ai_schema1 = types.Schema.from_json_schema(
132
+ json_schema=json_schema1, api_option='VERTEX_AI'
133
+ )
134
+ gemini_api_not_none_field_names1 = _get_not_none_fields(gemini_api_schema1)
135
+ vertex_ai_not_none_field_names1 = _get_not_none_fields(vertex_ai_schema1)
136
+ json_schema2 = types.JSONSchema(
137
+ type=[
138
+ 'string',
139
+ 'null',
140
+ 'object',
141
+ 'number',
142
+ 'array',
143
+ 'boolean',
144
+ 'integer',
145
+ ]
146
+ )
147
+ gemini_api_schema2 = types.Schema.from_json_schema(json_schema=json_schema2)
148
+ vertex_ai_schema2 = types.Schema.from_json_schema(
149
+ json_schema=json_schema2, api_option='VERTEX_AI'
150
+ )
151
+ expected_schema = types.Schema(
152
+ nullable=True,
153
+ any_of=[
154
+ types.Schema(type='STRING'),
155
+ types.Schema(type='OBJECT'),
156
+ types.Schema(type='NUMBER'),
157
+ types.Schema(type='ARRAY'),
158
+ types.Schema(type='BOOLEAN'),
159
+ types.Schema(type='INTEGER'),
160
+ ],
161
+ )
162
+
163
+ assert gemini_api_schema1 == expected_schema
164
+ assert vertex_ai_schema1 == expected_schema
165
+ assert gemini_api_schema2 == expected_schema
166
+ assert vertex_ai_schema2 == expected_schema
167
+
168
+
169
+ def test_union_like_type_conversion_suite1():
170
+ """Test conversion of JSONSchema.type to Schema.any_of"""
171
+ json_schema = types.JSONSchema(
172
+ type=[
173
+ types.JSONSchemaType('string'),
174
+ types.JSONSchemaType('object'),
175
+ types.JSONSchemaType('null'),
176
+ ],
177
+ description='description',
178
+ default='default',
179
+ max_length=10,
180
+ min_length=5,
181
+ enum=['value1', 'value2'],
182
+ format='format',
183
+ pattern='pattern',
184
+ title='title',
185
+ min_properties=1,
186
+ max_properties=2,
187
+ required=['field1', 'field2'],
188
+ properties={
189
+ 'field1': types.JSONSchema(type='string'),
190
+ 'field2': types.JSONSchema(type='integer'),
191
+ },
192
+ )
193
+ actual_gemini_api_schema = types.Schema.from_json_schema(
194
+ json_schema=json_schema
195
+ )
196
+ actual_vertex_ai_schema = types.Schema.from_json_schema(
197
+ json_schema=json_schema, api_option='VERTEX_AI'
198
+ )
199
+ expected_schema = types.Schema(
200
+ nullable=True,
201
+ any_of=[
202
+ types.Schema(
203
+ type='STRING',
204
+ description='description',
205
+ max_length=10,
206
+ min_length=5,
207
+ enum=['value1', 'value2'],
208
+ format='format',
209
+ pattern='pattern',
210
+ title='title',
211
+ ),
212
+ types.Schema(
213
+ type='OBJECT',
214
+ properties={
215
+ 'field1': types.Schema(type='STRING'),
216
+ 'field2': types.Schema(type='INTEGER'),
217
+ },
218
+ required=['field1', 'field2'],
219
+ min_properties=1,
220
+ max_properties=2,
221
+ title='title',
222
+ description='description',
223
+ ),
224
+ ],
225
+ )
226
+
227
+ assert actual_gemini_api_schema == expected_schema
228
+ assert actual_vertex_ai_schema == expected_schema
229
+
230
+
231
+ def test_union_like_type_conversion_suite2():
232
+ """Test conversion of JSONSchema.type to Schema.any_of"""
233
+ json_schema = types.JSONSchema(
234
+ type=[
235
+ types.JSONSchemaType('integer'),
236
+ types.JSONSchemaType('array'),
237
+ ],
238
+ description='description',
239
+ items=types.JSONSchema(type='integer', maximum=2, minimum=1),
240
+ min_items=1,
241
+ max_items=2,
242
+ title='title',
243
+ enum=['1', '2'],
244
+ maximum=2,
245
+ minimum=1,
246
+ )
247
+ actual_gemini_api_schema = types.Schema.from_json_schema(
248
+ json_schema=json_schema
249
+ )
250
+ actual_vertex_ai_schema = types.Schema.from_json_schema(
251
+ json_schema=json_schema, api_option='VERTEX_AI'
252
+ )
253
+ expected_schema = types.Schema(
254
+ any_of=[
255
+ types.Schema(
256
+ type='INTEGER',
257
+ description='description',
258
+ maximum=2,
259
+ minimum=1,
260
+ enum=['1', '2'],
261
+ title='title',
262
+ ),
263
+ types.Schema(
264
+ type='ARRAY',
265
+ items=types.Schema(type='INTEGER', maximum=2, minimum=1),
266
+ min_items=1,
267
+ max_items=2,
268
+ title='title',
269
+ description='description',
270
+ ),
271
+ ],
272
+ )
273
+
274
+ assert actual_gemini_api_schema == expected_schema
275
+ assert actual_vertex_ai_schema == expected_schema
276
+
277
+
278
+ def test_array_type_conversion():
279
+ """Test conversion of JSONSchema.items to Schema.items"""
280
+ json_schema = types.JSONSchema(
281
+ type=types.JSONSchemaType('array'),
282
+ items=types.JSONSchema(
283
+ type='object',
284
+ properties={
285
+ 'field1': types.JSONSchema(type='string'),
286
+ 'field2': types.JSONSchema(type='integer'),
287
+ },
288
+ required=['field1', 'field2'],
289
+ min_properties=1,
290
+ max_properties=2,
291
+ title='title',
292
+ description='description',
293
+ ),
294
+ )
295
+ gemini_api_schema = types.Schema.from_json_schema(json_schema=json_schema)
296
+ vertex_ai_schema = types.Schema.from_json_schema(
297
+ json_schema=json_schema, api_option='VERTEX_AI'
298
+ )
299
+ expected_schema = types.Schema(
300
+ type='ARRAY',
301
+ items=types.Schema(
302
+ type='OBJECT',
303
+ properties={
304
+ 'field1': types.Schema(type='STRING'),
305
+ 'field2': types.Schema(type='INTEGER'),
306
+ },
307
+ required=['field1', 'field2'],
308
+ min_properties=1,
309
+ max_properties=2,
310
+ title='title',
311
+ description='description',
312
+ ),
313
+ )
314
+
315
+ assert gemini_api_schema == expected_schema
316
+ assert vertex_ai_schema == expected_schema
317
+
318
+
319
+ def test_complex_object_type_conversion():
320
+ """Test conversion of JSONSchema.properties to Schema.properties"""
321
+ json_schema = types.JSONSchema(
322
+ type=types.JSONSchemaType('object'),
323
+ properties={
324
+ 'field1': types.JSONSchema(
325
+ type=['string', 'array', 'null'],
326
+ description='description1',
327
+ max_length=20,
328
+ min_length=15,
329
+ enum=['value1', 'value2'],
330
+ format='format',
331
+ pattern='pattern',
332
+ title='title1',
333
+ items=types.JSONSchema(type='integer', maximum=2, minimum=1),
334
+ min_items=1,
335
+ max_items=2,
336
+ ),
337
+ 'field2': types.JSONSchema(type='integer'),
338
+ },
339
+ required=['field1', 'field2'],
340
+ min_properties=1,
341
+ max_properties=2,
342
+ title='title',
343
+ description='description',
344
+ )
345
+ gemini_api_schema = types.Schema.from_json_schema(json_schema=json_schema)
346
+ vertex_ai_schema = types.Schema.from_json_schema(
347
+ json_schema=json_schema, api_option='VERTEX_AI'
348
+ )
349
+ expected_schema = types.Schema(
350
+ type='OBJECT',
351
+ properties={
352
+ 'field1': types.Schema(
353
+ nullable=True,
354
+ any_of=[
355
+ types.Schema(
356
+ type='STRING',
357
+ description='description1',
358
+ max_length=20,
359
+ min_length=15,
360
+ enum=['value1', 'value2'],
361
+ format='format',
362
+ pattern='pattern',
363
+ title='title1',
364
+ ),
365
+ types.Schema(
366
+ type='ARRAY',
367
+ items=types.Schema(type='INTEGER', maximum=2, minimum=1),
368
+ min_items=1,
369
+ max_items=2,
370
+ title='title1',
371
+ description='description1',
372
+ ),
373
+ ],
374
+ ),
375
+ 'field2': types.Schema(type='INTEGER'),
376
+ },
377
+ required=['field1', 'field2'],
378
+ min_properties=1,
379
+ max_properties=2,
380
+ title='title',
381
+ description='description',
382
+ )
383
+
384
+ assert gemini_api_schema == expected_schema
385
+ assert vertex_ai_schema == expected_schema
386
+
387
+
388
+ def test_from_json_schema_logs_only_once(caplog):
389
+ """Test that the info message is logged only once across multiple from_json_schema calls."""
390
+ from ... import types as types_module
391
+
392
+ types_module._from_json_schema_warning_logged = False
393
+
394
+ caplog.set_level(logging.INFO, logger='google_genai.types')
395
+
396
+ json_schema1 = types_module.JSONSchema(type='string')
397
+ schema1 = types_module.Schema.from_json_schema(json_schema=json_schema1)
398
+
399
+ assert len(caplog.records) == 1
400
+ assert 'Json Schema is now supported natively' in caplog.text
401
+ assert 'response_json_schema' in caplog.text
402
+
403
+ json_schema2 = types_module.JSONSchema(type='number')
404
+ schema2 = types_module.Schema.from_json_schema(json_schema=json_schema2)
405
+
406
+ assert len(caplog.records) == 1
407
+
408
+ json_schema3 = types_module.JSONSchema(type='object')
409
+ schema3 = types_module.Schema.from_json_schema(json_schema=json_schema3)
410
+
411
+ assert len(caplog.records) == 1
412
+
413
+ assert schema1.type == types_module.Type('STRING')
414
+ assert schema2.type == types_module.Type('NUMBER')
415
+ assert schema3.type == types.Type('OBJECT')
416
+
417
+ types_module._from_json_schema_warning_logged = False