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,61 @@
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
+ # mypy: ignore-errors
17
+ from __future__ import annotations
18
+
19
+ import sys
20
+ import typing_extensions
21
+ from typing import Any, Type, Union, Literal, Optional
22
+ from datetime import date, datetime
23
+ from typing_extensions import get_args as _get_args, get_origin as _get_origin
24
+
25
+ from .._types import StrBytesIntFloat
26
+ from ._datetime_parse import parse_date as _parse_date, parse_datetime as _parse_datetime
27
+
28
+ _LITERAL_TYPES = {Literal, typing_extensions.Literal}
29
+
30
+
31
+ def get_args(tp: type[Any]) -> tuple[Any, ...]:
32
+ return _get_args(tp)
33
+
34
+
35
+ def get_origin(tp: type[Any]) -> type[Any] | None:
36
+ return _get_origin(tp)
37
+
38
+
39
+ def is_union(tp: Optional[Type[Any]]) -> bool:
40
+ if sys.version_info < (3, 10):
41
+ return tp is Union # type: ignore[comparison-overlap]
42
+ else:
43
+ import types
44
+
45
+ return tp is Union or tp is types.UnionType
46
+
47
+
48
+ def is_typeddict(tp: Type[Any]) -> bool:
49
+ return typing_extensions.is_typeddict(tp)
50
+
51
+
52
+ def is_literal_type(tp: Type[Any]) -> bool:
53
+ return get_origin(tp) in _LITERAL_TYPES
54
+
55
+
56
+ def parse_date(value: Union[date, StrBytesIntFloat]) -> date:
57
+ return _parse_date(value)
58
+
59
+
60
+ def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime:
61
+ return _parse_datetime(value)
@@ -0,0 +1,151 @@
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
+ This file contains code from https://github.com/pydantic/pydantic/blob/main/pydantic/v1/datetime_parse.py
18
+ without the Pydantic v1 specific errors.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import re
24
+ from typing import Dict, Union, Optional
25
+ from datetime import date, datetime, timezone, timedelta
26
+
27
+ from .._types import StrBytesIntFloat
28
+
29
+ date_expr = r"(?P<year>\d{4})-(?P<month>\d{1,2})-(?P<day>\d{1,2})"
30
+ time_expr = (
31
+ r"(?P<hour>\d{1,2}):(?P<minute>\d{1,2})"
32
+ r"(?::(?P<second>\d{1,2})(?:\.(?P<microsecond>\d{1,6})\d{0,6})?)?"
33
+ r"(?P<tzinfo>Z|[+-]\d{2}(?::?\d{2})?)?$"
34
+ )
35
+
36
+ date_re = re.compile(f"{date_expr}$")
37
+ datetime_re = re.compile(f"{date_expr}[T ]{time_expr}")
38
+
39
+
40
+ EPOCH = datetime(1970, 1, 1)
41
+ # if greater than this, the number is in ms, if less than or equal it's in seconds
42
+ # (in seconds this is 11th October 2603, in ms it's 20th August 1970)
43
+ MS_WATERSHED = int(2e10)
44
+ # slightly more than datetime.max in ns - (datetime.max - EPOCH).total_seconds() * 1e9
45
+ MAX_NUMBER = int(3e20)
46
+
47
+
48
+ def _get_numeric(value: StrBytesIntFloat, native_expected_type: str) -> Union[None, int, float]:
49
+ if isinstance(value, (int, float)):
50
+ return value
51
+ try:
52
+ return float(value)
53
+ except ValueError:
54
+ return None
55
+ except TypeError:
56
+ raise TypeError(f"invalid type; expected {native_expected_type}, string, bytes, int or float") from None
57
+
58
+
59
+ def _from_unix_seconds(seconds: Union[int, float]) -> datetime:
60
+ if seconds > MAX_NUMBER:
61
+ return datetime.max
62
+ elif seconds < -MAX_NUMBER:
63
+ return datetime.min
64
+
65
+ while abs(seconds) > MS_WATERSHED:
66
+ seconds /= 1000
67
+ dt = EPOCH + timedelta(seconds=seconds)
68
+ return dt.replace(tzinfo=timezone.utc)
69
+
70
+
71
+ def _parse_timezone(value: Optional[str]) -> Union[None, int, timezone]:
72
+ if value == "Z":
73
+ return timezone.utc
74
+ elif value is not None:
75
+ offset_mins = int(value[-2:]) if len(value) > 3 else 0
76
+ offset = 60 * int(value[1:3]) + offset_mins
77
+ if value[0] == "-":
78
+ offset = -offset
79
+ return timezone(timedelta(minutes=offset))
80
+ else:
81
+ return None
82
+
83
+
84
+ def parse_datetime(value: Union[datetime, StrBytesIntFloat]) -> datetime:
85
+ """
86
+ Parse a datetime/int/float/string and return a datetime.datetime.
87
+
88
+ This function supports time zone offsets. When the input contains one,
89
+ the output uses a timezone with a fixed offset from UTC.
90
+
91
+ Raise ValueError if the input is well formatted but not a valid datetime.
92
+ Raise ValueError if the input isn't well formatted.
93
+ """
94
+ if isinstance(value, datetime):
95
+ return value
96
+
97
+ number = _get_numeric(value, "datetime")
98
+ if number is not None:
99
+ return _from_unix_seconds(number)
100
+
101
+ if isinstance(value, bytes):
102
+ value = value.decode()
103
+
104
+ assert not isinstance(value, (float, int))
105
+
106
+ match = datetime_re.match(value)
107
+ if match is None:
108
+ raise ValueError("invalid datetime format")
109
+
110
+ kw = match.groupdict()
111
+ if kw["microsecond"]:
112
+ kw["microsecond"] = kw["microsecond"].ljust(6, "0")
113
+
114
+ tzinfo = _parse_timezone(kw.pop("tzinfo"))
115
+ kw_: Dict[str, Union[None, int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}
116
+ kw_["tzinfo"] = tzinfo
117
+
118
+ return datetime(**kw_) # type: ignore
119
+
120
+
121
+ def parse_date(value: Union[date, StrBytesIntFloat]) -> date:
122
+ """
123
+ Parse a date/int/float/string and return a datetime.date.
124
+
125
+ Raise ValueError if the input is well formatted but not a valid date.
126
+ Raise ValueError if the input isn't well formatted.
127
+ """
128
+ if isinstance(value, date):
129
+ if isinstance(value, datetime):
130
+ return value.date()
131
+ else:
132
+ return value
133
+
134
+ number = _get_numeric(value, "date")
135
+ if number is not None:
136
+ return _from_unix_seconds(number).date()
137
+
138
+ if isinstance(value, bytes):
139
+ value = value.decode()
140
+
141
+ assert not isinstance(value, (float, int))
142
+ match = date_re.match(value)
143
+ if match is None:
144
+ raise ValueError("invalid date format")
145
+
146
+ kw = {k: int(v) for k, v in match.groupdict().items()}
147
+
148
+ try:
149
+ return date(**kw)
150
+ except ValueError:
151
+ raise ValueError("invalid date format") from None
@@ -0,0 +1,40 @@
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 os
17
+ import logging
18
+
19
+ logger: logging.Logger = logging.getLogger("google.genai._interactions")
20
+ httpx_logger: logging.Logger = logging.getLogger("httpx")
21
+
22
+
23
+ def _basic_config() -> None:
24
+ # e.g. [2023-10-05 14:12:26 - google.genai._interactions._base_client:818 - DEBUG] HTTP Request: POST http://127.0.0.1:4010/foo/bar "200 OK"
25
+ logging.basicConfig(
26
+ format="[%(asctime)s - %(name)s:%(lineno)d - %(levelname)s] %(message)s",
27
+ datefmt="%Y-%m-%d %H:%M:%S",
28
+ )
29
+
30
+
31
+ def setup_logging() -> None:
32
+ env = os.environ.get("GEMINI_NEXT_GEN_API_LOG")
33
+ if env == "debug":
34
+ _basic_config()
35
+ logger.setLevel(logging.DEBUG)
36
+ httpx_logger.setLevel(logging.DEBUG)
37
+ elif env == "info":
38
+ _basic_config()
39
+ logger.setLevel(logging.INFO)
40
+ httpx_logger.setLevel(logging.INFO)
@@ -0,0 +1,80 @@
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
+ from __future__ import annotations
17
+
18
+ from abc import ABC, abstractmethod
19
+ from typing import Generic, TypeVar, Iterable, cast
20
+ from typing_extensions import override
21
+
22
+ T = TypeVar("T")
23
+
24
+
25
+ class LazyProxy(Generic[T], ABC):
26
+ """Implements data methods to pretend that an instance is another instance.
27
+
28
+ This includes forwarding attribute access and other methods.
29
+ """
30
+
31
+ # Note: we have to special case proxies that themselves return proxies
32
+ # to support using a proxy as a catch-all for any random access, e.g. `proxy.foo.bar.baz`
33
+
34
+ def __getattr__(self, attr: str) -> object:
35
+ proxied = self.__get_proxied__()
36
+ if isinstance(proxied, LazyProxy):
37
+ return proxied # pyright: ignore
38
+ return getattr(proxied, attr)
39
+
40
+ @override
41
+ def __repr__(self) -> str:
42
+ proxied = self.__get_proxied__()
43
+ if isinstance(proxied, LazyProxy):
44
+ return proxied.__class__.__name__
45
+ return repr(self.__get_proxied__())
46
+
47
+ @override
48
+ def __str__(self) -> str:
49
+ proxied = self.__get_proxied__()
50
+ if isinstance(proxied, LazyProxy):
51
+ return proxied.__class__.__name__
52
+ return str(proxied)
53
+
54
+ @override
55
+ def __dir__(self) -> Iterable[str]:
56
+ proxied = self.__get_proxied__()
57
+ if isinstance(proxied, LazyProxy):
58
+ return []
59
+ return proxied.__dir__()
60
+
61
+ @property # type: ignore
62
+ @override
63
+ def __class__(self) -> type: # pyright: ignore
64
+ try:
65
+ proxied = self.__get_proxied__()
66
+ except Exception:
67
+ return type(self)
68
+ if issubclass(type(proxied), LazyProxy):
69
+ return type(proxied)
70
+ return proxied.__class__
71
+
72
+ def __get_proxied__(self) -> T:
73
+ return self.__load__()
74
+
75
+ def __as_proxied__(self) -> T:
76
+ """Helper method that returns the current proxy, typed as the loaded object"""
77
+ return cast(T, self)
78
+
79
+ @abstractmethod
80
+ def __load__(self) -> T: ...
@@ -0,0 +1,57 @@
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
+ from __future__ import annotations
17
+
18
+ import inspect
19
+ from typing import Any, Callable
20
+
21
+
22
+ def function_has_argument(func: Callable[..., Any], arg_name: str) -> bool:
23
+ """Returns whether or not the given function has a specific parameter"""
24
+ sig = inspect.signature(func)
25
+ return arg_name in sig.parameters
26
+
27
+
28
+ def assert_signatures_in_sync(
29
+ source_func: Callable[..., Any],
30
+ check_func: Callable[..., Any],
31
+ *,
32
+ exclude_params: set[str] = set(),
33
+ ) -> None:
34
+ """Ensure that the signature of the second function matches the first."""
35
+
36
+ check_sig = inspect.signature(check_func)
37
+ source_sig = inspect.signature(source_func)
38
+
39
+ errors: list[str] = []
40
+
41
+ for name, source_param in source_sig.parameters.items():
42
+ if name in exclude_params:
43
+ continue
44
+
45
+ custom_param = check_sig.parameters.get(name)
46
+ if not custom_param:
47
+ errors.append(f"the `{name}` param is missing")
48
+ continue
49
+
50
+ if custom_param.annotation != source_param.annotation:
51
+ errors.append(
52
+ f"types for the `{name}` param are do not match; source={repr(source_param.annotation)} checking={repr(custom_param.annotation)}"
53
+ )
54
+ continue
55
+
56
+ if errors:
57
+ raise AssertionError(f"{len(errors)} errors encountered when comparing signatures:\n\n" + "\n\n".join(errors))
@@ -0,0 +1,39 @@
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
+ from __future__ import annotations
17
+
18
+ from typing import Any
19
+ from typing_extensions import override
20
+
21
+ from ._proxy import LazyProxy
22
+
23
+
24
+ class ResourcesProxy(LazyProxy[Any]):
25
+ """A proxy for the `google.genai._interactions.resources` module.
26
+
27
+ This is used so that we can lazily import `google.genai._interactions.resources` only when
28
+ needed *and* so that users can just import `google.genai._interactions` and reference `google.genai._interactions.resources`
29
+ """
30
+
31
+ @override
32
+ def __load__(self) -> Any:
33
+ import importlib
34
+
35
+ mod = importlib.import_module("google.genai._interactions.resources")
36
+ return mod
37
+
38
+
39
+ resources = ResourcesProxy().__as_proxied__()
@@ -0,0 +1,27 @@
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
+ from typing import Any
17
+ from typing_extensions import Iterator, AsyncIterator
18
+
19
+
20
+ def consume_sync_iterator(iterator: Iterator[Any]) -> None:
21
+ for _ in iterator:
22
+ ...
23
+
24
+
25
+ async def consume_async_iterator(iterator: AsyncIterator[Any]) -> None:
26
+ async for _ in iterator:
27
+ ...
@@ -0,0 +1,73 @@
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
+ from __future__ import annotations
17
+
18
+ import asyncio
19
+ import functools
20
+ from typing import TypeVar, Callable, Awaitable
21
+ from typing_extensions import ParamSpec
22
+
23
+ import anyio
24
+ import sniffio
25
+ import anyio.to_thread
26
+
27
+ T_Retval = TypeVar("T_Retval")
28
+ T_ParamSpec = ParamSpec("T_ParamSpec")
29
+
30
+
31
+ async def to_thread(
32
+ func: Callable[T_ParamSpec, T_Retval], /, *args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs
33
+ ) -> T_Retval:
34
+ if sniffio.current_async_library() == "asyncio":
35
+ return await asyncio.to_thread(func, *args, **kwargs)
36
+
37
+ return await anyio.to_thread.run_sync(
38
+ functools.partial(func, *args, **kwargs),
39
+ )
40
+
41
+
42
+ # inspired by `asyncer`, https://github.com/tiangolo/asyncer
43
+ def asyncify(function: Callable[T_ParamSpec, T_Retval]) -> Callable[T_ParamSpec, Awaitable[T_Retval]]:
44
+ """
45
+ Take a blocking function and create an async one that receives the same
46
+ positional and keyword arguments.
47
+
48
+ Usage:
49
+
50
+ ```python
51
+ def blocking_func(arg1, arg2, kwarg1=None):
52
+ # blocking code
53
+ return result
54
+
55
+
56
+ result = asyncify(blocking_function)(arg1, arg2, kwarg1=value1)
57
+ ```
58
+
59
+ ## Arguments
60
+
61
+ `function`: a blocking regular callable (e.g. a function)
62
+
63
+ ## Return
64
+
65
+ An async function that takes the same positional and keyword arguments as the
66
+ original one, that when called runs the same original function in a thread worker
67
+ and returns the result.
68
+ """
69
+
70
+ async def wrapper(*args: T_ParamSpec.args, **kwargs: T_ParamSpec.kwargs) -> T_Retval:
71
+ return await to_thread(function, *args, **kwargs)
72
+
73
+ return wrapper