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,616 @@
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
+
17
+ import pytest
18
+ from ... import types
19
+
20
+
21
+ @pytest.fixture
22
+ def generate_content_response():
23
+ return types.GenerateContentResponse()
24
+
25
+
26
+ def test_candidate_empty_text():
27
+ response = types.GenerateContentResponse()
28
+ assert response.text is None
29
+
30
+
31
+ def test_first_candidate_empty_content_text():
32
+ response = types.GenerateContentResponse(candidates=[])
33
+
34
+ # MUST assert None not implicit boolean False
35
+ assert response.text is None
36
+
37
+
38
+ def test_first_candidate_empty_parts_text():
39
+ response = types.GenerateContentResponse(candidates=[types.Candidate()])
40
+
41
+ # MUST assert None not implicit boolean False
42
+ assert response.text is None
43
+
44
+
45
+ def test_content_empty_parts_text():
46
+ response = types.GenerateContentResponse(
47
+ candidates=[types.Candidate(content=types.Content())]
48
+ )
49
+
50
+ # MUST assert None not implicit boolean False
51
+ assert response.text is None
52
+
53
+
54
+ def test_two_candidates_text(caplog, generate_content_response):
55
+ from ... import types as types_module
56
+ types_module._response_text_warning_logged = False
57
+
58
+ generate_content_response.candidates = [
59
+ types.Candidate(
60
+ content=types.Content(
61
+ parts=[
62
+ types.Part(text='Hello1'),
63
+ types.Part(text='World1'),
64
+ ]
65
+ )
66
+ ),
67
+ types.Candidate(
68
+ content=types.Content(
69
+ parts=[
70
+ types.Part(text='Hello2'),
71
+ types.Part(text='World2'),
72
+ ]
73
+ )
74
+ ),
75
+ ]
76
+
77
+ assert generate_content_response.text == 'Hello1World1'
78
+ assert any(
79
+ record.levelname == 'WARNING'
80
+ and 'there are 2 candidates' in record.message
81
+ for record in caplog.records
82
+ )
83
+ generate_content_response.candidates = None
84
+
85
+
86
+ def test_thought_signature_no_warning(caplog, generate_content_response):
87
+ generate_content_response.candidates = [
88
+ types.Candidate(
89
+ content=types.Content(
90
+ parts=[
91
+ types.Part(text='Hello'),
92
+ types.Part(thought_signature=b'thought'),
93
+ ]
94
+ )
95
+ ),
96
+ ]
97
+
98
+ assert generate_content_response.text == 'Hello'
99
+ assert not any(
100
+ record.levelname == 'WARNING'
101
+ and 'there are non-text parts in the response' in record.message
102
+ for record in caplog.records
103
+ )
104
+ generate_content_response.candidates = None
105
+
106
+
107
+ def test_thought_signature_no_warning_in_text(
108
+ caplog, generate_content_response
109
+ ):
110
+ generate_content_response.candidates = [
111
+ types.Candidate(
112
+ content=types.Content(
113
+ parts=[
114
+ types.Part(text='Hello', thought_signature=b'thought'),
115
+ ]
116
+ )
117
+ ),
118
+ ]
119
+
120
+ assert generate_content_response.text == 'Hello'
121
+ assert not any(
122
+ record.levelname == 'WARNING'
123
+ and 'there are non-text parts in the response' in record.message
124
+ for record in caplog.records
125
+ )
126
+ generate_content_response.candidates = None
127
+
128
+
129
+ def test_1_candidate_text():
130
+ response = types.GenerateContentResponse(
131
+ candidates=[
132
+ types.Candidate(
133
+ content=types.Content(
134
+ parts=[
135
+ types.Part(text='Hello1'),
136
+ types.Part(text='World1'),
137
+ ]
138
+ )
139
+ )
140
+ ]
141
+ )
142
+
143
+ assert response.text == 'Hello1World1'
144
+
145
+
146
+ def test_all_empty_text_in_parts():
147
+ response = types.GenerateContentResponse(
148
+ candidates=[
149
+ types.Candidate(
150
+ content=types.Content(
151
+ parts=[
152
+ types.Part(text=''),
153
+ types.Part(text=''),
154
+ ]
155
+ )
156
+ ),
157
+ types.Candidate(
158
+ content=types.Content(
159
+ parts=[
160
+ types.Part(text='Hello2'),
161
+ types.Part(text='World2'),
162
+ ]
163
+ )
164
+ ),
165
+ ]
166
+ )
167
+
168
+ # MUST assert empty string, not implicit boolean False
169
+ assert response.text == ''
170
+
171
+
172
+ def test_one_empty_text_in_parts():
173
+ response = types.GenerateContentResponse(
174
+ candidates=[
175
+ types.Candidate(
176
+ content=types.Content(
177
+ parts=[
178
+ types.Part(text=''),
179
+ types.Part(text='World1'),
180
+ ]
181
+ )
182
+ ),
183
+ types.Candidate(
184
+ content=types.Content(
185
+ parts=[
186
+ types.Part(text='Hello2'),
187
+ types.Part(text='World2'),
188
+ ]
189
+ )
190
+ ),
191
+ ]
192
+ )
193
+
194
+ assert response.text == 'World1'
195
+
196
+
197
+ def test_all_none_text():
198
+ response = types.GenerateContentResponse(
199
+ candidates=[
200
+ types.Candidate(
201
+ content=types.Content(
202
+ parts=[
203
+ types.Part(),
204
+ types.Part(),
205
+ ]
206
+ )
207
+ ),
208
+ types.Candidate(
209
+ content=types.Content(
210
+ parts=[
211
+ types.Part(text='Hello2'),
212
+ types.Part(text='World2'),
213
+ ]
214
+ )
215
+ ),
216
+ ]
217
+ )
218
+
219
+ # MUST assert None not implicit boolean False
220
+ assert response.text is None
221
+
222
+
223
+ def test_none_empty_text():
224
+ response = types.GenerateContentResponse(
225
+ candidates=[
226
+ types.Candidate(
227
+ content=types.Content(
228
+ parts=[
229
+ types.Part(),
230
+ types.Part(text=''),
231
+ ]
232
+ )
233
+ ),
234
+ types.Candidate(
235
+ content=types.Content(
236
+ parts=[
237
+ types.Part(text='Hello2'),
238
+ types.Part(text='World2'),
239
+ ]
240
+ )
241
+ ),
242
+ ]
243
+ )
244
+
245
+ # MUST assert empty string, not implicit boolean False
246
+ assert response.text == ''
247
+
248
+
249
+ def test_non_text_part_text(caplog, generate_content_response):
250
+ generate_content_response.candidates = [
251
+ types.Candidate(
252
+ content=types.Content(
253
+ parts=[
254
+ types.Part(function_call=types.FunctionCall()),
255
+ ]
256
+ )
257
+ ),
258
+ ]
259
+
260
+ assert generate_content_response.text is None
261
+ assert any(
262
+ record.levelname == 'WARNING'
263
+ and 'there are non-text parts in the response' in record.message
264
+ for record in caplog.records
265
+ )
266
+ generate_content_response.candidates = None
267
+
268
+
269
+ def test_non_text_part_and_text_part_text(caplog, generate_content_response):
270
+ generate_content_response.candidates = [
271
+ types.Candidate(
272
+ content=types.Content(
273
+ parts=[
274
+ types.Part(function_call=types.FunctionCall()),
275
+ types.Part(text='World1'),
276
+ ]
277
+ )
278
+ ),
279
+ ]
280
+
281
+ assert generate_content_response.text == 'World1'
282
+ assert not any(
283
+ record.levelname == 'WARNING'
284
+ and 'there are no text parts in the response' in record.message
285
+ for record in caplog.records
286
+ )
287
+ generate_content_response.candidates = None
288
+
289
+
290
+ def test_candidates_none_function_calls():
291
+ response = types.GenerateContentResponse()
292
+ assert response.function_calls is None
293
+
294
+
295
+ def test_candidates_empty_function_calls():
296
+ response = types.GenerateContentResponse(candidates=[])
297
+ assert response.function_calls is None
298
+
299
+
300
+ def test_content_none_function_calls():
301
+ response = types.GenerateContentResponse(candidates=[types.Candidate()])
302
+ assert response.function_calls is None
303
+
304
+
305
+ def test_parts_none_function_calls():
306
+ response = types.GenerateContentResponse(
307
+ candidates=[types.Candidate(content=types.Content())]
308
+ )
309
+ assert response.function_calls is None
310
+
311
+
312
+ def test_parts_empty_function_calls():
313
+ response = types.GenerateContentResponse(
314
+ candidates=[
315
+ types.Candidate(content=types.Content(parts=[])),
316
+ ]
317
+ )
318
+ assert response.function_calls is None
319
+
320
+
321
+ def test_multiple_candidates_function_calls(caplog, generate_content_response):
322
+ generate_content_response.candidates = [
323
+ types.Candidate(
324
+ content=types.Content(
325
+ parts=[
326
+ types.Part(
327
+ function_call=types.FunctionCall.model_validate({
328
+ 'args': {'key1': 'value1'},
329
+ 'name': 'funcCall1',
330
+ })
331
+ )
332
+ ]
333
+ )
334
+ ),
335
+ types.Candidate(
336
+ content=types.Content(
337
+ parts=[
338
+ types.Part(
339
+ function_call=types.FunctionCall.model_validate({
340
+ 'args': {'key2': 'value2'},
341
+ 'name': 'funcCall2',
342
+ })
343
+ )
344
+ ]
345
+ )
346
+ ),
347
+ ]
348
+ assert generate_content_response.function_calls == [
349
+ types.FunctionCall(name='funcCall1', args={'key1': 'value1'})
350
+ ]
351
+ assert any(
352
+ record.levelname == 'WARNING'
353
+ and 'there are multiple candidates in the response' in record.message
354
+ for record in caplog.records
355
+ )
356
+ generate_content_response.candidates = None
357
+
358
+
359
+ def test_multiple_function_calls():
360
+ response = types.GenerateContentResponse(
361
+ candidates=[
362
+ types.Candidate(
363
+ content=types.Content(
364
+ parts=[
365
+ types.Part(
366
+ function_call=types.FunctionCall.model_validate({
367
+ 'args': {'key1': 'value1'},
368
+ 'name': 'funcCall1',
369
+ })
370
+ ),
371
+ types.Part(
372
+ function_call=types.FunctionCall.model_validate({
373
+ 'args': {'key2': 'value2'},
374
+ 'name': 'funcCall2',
375
+ })
376
+ ),
377
+ ]
378
+ )
379
+ ),
380
+ ]
381
+ )
382
+ assert response.function_calls == [
383
+ types.FunctionCall(name='funcCall1', args={'key1': 'value1'}),
384
+ types.FunctionCall(name='funcCall2', args={'key2': 'value2'}),
385
+ ]
386
+
387
+
388
+ def test_no_function_calls():
389
+ response = types.GenerateContentResponse(
390
+ candidates=[
391
+ types.Candidate(
392
+ content=types.Content(
393
+ parts=[
394
+ types.Part(text='Hello1'),
395
+ types.Part(text='World1'),
396
+ ]
397
+ )
398
+ ),
399
+ ]
400
+ )
401
+ assert response.function_calls is None
402
+
403
+
404
+ def test_executable_code_empty_candidates():
405
+ response = types.GenerateContentResponse()
406
+
407
+ assert response.executable_code is None
408
+
409
+
410
+ def test_executable_code_empty_content():
411
+ response = types.GenerateContentResponse(candidates=[])
412
+
413
+ assert response.executable_code is None
414
+
415
+
416
+ def test_executable_code_empty_parts():
417
+ response = types.GenerateContentResponse(candidates=[types.Candidate(
418
+ content=types.Content()
419
+ )])
420
+
421
+ assert response.executable_code is None
422
+
423
+
424
+ def test_executable_code_two_candidates(caplog, generate_content_response):
425
+ generate_content_response.candidates = [
426
+ types.Candidate(
427
+ content=types.Content(
428
+ parts=[
429
+ types.Part(
430
+ executable_code=types.ExecutableCode(
431
+ code='print("hello")', language='PYTHON'
432
+ )
433
+ )
434
+ ]
435
+ )
436
+ ),
437
+ types.Candidate(
438
+ content=types.Content(
439
+ parts=[
440
+ types.Part(
441
+ executable_code=types.ExecutableCode(
442
+ code='print("world")', language='PYTHON'
443
+ )
444
+ )
445
+ ]
446
+ )
447
+ ),
448
+ ]
449
+
450
+ assert generate_content_response.executable_code == 'print("hello")'
451
+ assert any(
452
+ record.levelname == 'WARNING'
453
+ and 'there are multiple candidates in the response' in record.message
454
+ for record in caplog.records
455
+ )
456
+ generate_content_response.candidates = None
457
+
458
+ def test_executable_code_one_candidate():
459
+ response = types.GenerateContentResponse(
460
+ candidates=[
461
+ types.Candidate(
462
+ content=types.Content(
463
+ parts=[
464
+ types.Part(
465
+ executable_code=types.ExecutableCode(
466
+ code='print("hello")', language='PYTHON'
467
+ )
468
+ )
469
+ ]
470
+ )
471
+ )
472
+ ]
473
+ )
474
+
475
+ assert response.executable_code == 'print("hello")'
476
+
477
+
478
+ def test_code_execution_result_empty_candidates():
479
+ response = types.GenerateContentResponse()
480
+
481
+ assert response.code_execution_result is None, response.code_execution_result
482
+
483
+
484
+ def test_code_execution_result_empty_content():
485
+ response = types.GenerateContentResponse(candidates=[])
486
+
487
+ assert response.code_execution_result is None
488
+
489
+
490
+ def test_code_execution_result_empty_parts():
491
+ response = types.GenerateContentResponse(
492
+ candidates=[types.Candidate(content=types.Content())]
493
+ )
494
+
495
+ assert response.code_execution_result is None
496
+
497
+
498
+ def test_code_execution_result_two_candidates(caplog, generate_content_response):
499
+ generate_content_response.candidates = [
500
+ types.Candidate(
501
+ content=types.Content(
502
+ parts=[
503
+ types.Part(
504
+ code_execution_result=types.CodeExecutionResult(
505
+ outcome='OUTCOME_OK', output='"hello"'
506
+ )
507
+ )
508
+ ]
509
+ )
510
+ ),
511
+ types.Candidate(
512
+ content=types.Content(
513
+ parts=[
514
+ types.Part(
515
+ code_execution_result=types.CodeExecutionResult(
516
+ outcome='OUTCOME_ERROR', output='"world"'
517
+ )
518
+ )
519
+ ]
520
+ )
521
+ ),
522
+ ]
523
+
524
+ assert generate_content_response.code_execution_result == '"hello"'
525
+ assert any (
526
+ record.levelname == 'WARNING'
527
+ and 'there are multiple candidates in the response' in record.message
528
+ for record in caplog.records
529
+ )
530
+ generate_content_response.candidates = None
531
+
532
+
533
+ def test_code_execution_result_one_candidate():
534
+ response = types.GenerateContentResponse(
535
+ candidates=[
536
+ types.Candidate(
537
+ content=types.Content(
538
+ parts=[
539
+ types.Part(
540
+ code_execution_result=types.CodeExecutionResult(
541
+ outcome='OUTCOME_OK', output='"hello"'
542
+ )
543
+ )
544
+ ]
545
+ )
546
+ )
547
+ ]
548
+ )
549
+
550
+ assert response.code_execution_result == '"hello"'
551
+
552
+
553
+ def test_from_file_media_resolution_str():
554
+ file_uri = types.Part.from_uri(
555
+ file_uri='gs://test',
556
+ mime_type='image/png',
557
+ media_resolution='MEDIA_RESOLUTION_LOW',
558
+ )
559
+ assert file_uri.file_data.file_uri == 'gs://test'
560
+ assert file_uri.file_data.mime_type == 'image/png'
561
+ assert file_uri.media_resolution.level == types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW
562
+
563
+
564
+ def test_from_file_media_resolution_enum():
565
+ file_uri = types.Part.from_uri(
566
+ file_uri='gs://test',
567
+ mime_type='image/png',
568
+ media_resolution=types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW,
569
+ )
570
+ assert file_uri.file_data.file_uri == 'gs://test'
571
+ assert file_uri.file_data.mime_type == 'image/png'
572
+ assert file_uri.media_resolution.level == types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW
573
+
574
+
575
+ def test_from_file_media_resolution_object():
576
+ file_uri = types.Part.from_uri(
577
+ file_uri='gs://test',
578
+ mime_type='image/png',
579
+ media_resolution=types.PartMediaResolution(level='MEDIA_RESOLUTION_LOW'),
580
+ )
581
+ assert file_uri.file_data.file_uri == 'gs://test'
582
+ assert file_uri.file_data.mime_type == 'image/png'
583
+ assert file_uri.media_resolution.level == types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW
584
+
585
+
586
+ def test_from_bytes_media_resolution_str():
587
+ file_uri = types.Part.from_bytes(
588
+ data=b'1234',
589
+ mime_type='image/png',
590
+ media_resolution='MEDIA_RESOLUTION_LOW',
591
+ )
592
+ assert file_uri.inline_data.data == b'1234'
593
+ assert file_uri.inline_data.mime_type == 'image/png'
594
+ assert file_uri.media_resolution.level == types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW
595
+
596
+
597
+ def test_from_bytes_media_resolution_enum():
598
+ file_uri = types.Part.from_bytes(
599
+ data=b'1234',
600
+ mime_type='image/png',
601
+ media_resolution=types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW,
602
+ )
603
+ assert file_uri.inline_data.data == b'1234'
604
+ assert file_uri.inline_data.mime_type == 'image/png'
605
+ assert file_uri.media_resolution.level == types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW
606
+
607
+
608
+ def test_from_bytes_media_resolution_object():
609
+ file_uri = types.Part.from_bytes(
610
+ data=b'1234',
611
+ mime_type='image/png',
612
+ media_resolution=types.PartMediaResolution(level='MEDIA_RESOLUTION_LOW'),
613
+ )
614
+ assert file_uri.inline_data.data == b'1234'
615
+ assert file_uri.inline_data.mime_type == 'image/png'
616
+ assert file_uri.media_resolution.level == types.PartMediaResolutionLevel.MEDIA_RESOLUTION_LOW