google-genai 1.55.0__py3-none-any.whl → 1.56.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 (241) hide show
  1. google/genai/_interactions/_base_client.py +8 -2
  2. google/genai/_interactions/resources/interactions.py +6 -6
  3. google/genai/_interactions/types/__init__.py +2 -0
  4. google/genai/_interactions/types/audio_content.py +0 -1
  5. google/genai/_interactions/types/audio_content_param.py +0 -1
  6. google/genai/_interactions/types/code_execution_call_content.py +0 -1
  7. google/genai/_interactions/types/code_execution_call_content_param.py +0 -1
  8. google/genai/_interactions/types/code_execution_result_content.py +0 -1
  9. google/genai/_interactions/types/code_execution_result_content_param.py +0 -1
  10. google/genai/_interactions/types/content_delta.py +7 -23
  11. google/genai/_interactions/types/deep_research_agent_config.py +0 -1
  12. google/genai/_interactions/types/deep_research_agent_config_param.py +0 -1
  13. google/genai/_interactions/types/document_content.py +3 -2
  14. google/genai/_interactions/types/document_content_param.py +3 -2
  15. google/genai/{tests/__init__.py → _interactions/types/document_mime_type.py} +5 -3
  16. google/genai/{tests/afc/__init__.py → _interactions/types/document_mime_type_param.py} +8 -4
  17. google/genai/_interactions/types/dynamic_agent_config.py +0 -1
  18. google/genai/_interactions/types/dynamic_agent_config_param.py +0 -1
  19. google/genai/_interactions/types/file_search_result_content.py +0 -1
  20. google/genai/_interactions/types/file_search_result_content_param.py +0 -1
  21. google/genai/_interactions/types/function_call_content.py +0 -1
  22. google/genai/_interactions/types/function_call_content_param.py +0 -1
  23. google/genai/_interactions/types/function_result_content.py +1 -2
  24. google/genai/_interactions/types/function_result_content_param.py +1 -2
  25. google/genai/_interactions/types/google_search_call_content.py +0 -1
  26. google/genai/_interactions/types/google_search_call_content_param.py +0 -1
  27. google/genai/_interactions/types/google_search_result_content.py +0 -1
  28. google/genai/_interactions/types/google_search_result_content_param.py +0 -1
  29. google/genai/_interactions/types/image_content.py +1 -2
  30. google/genai/_interactions/types/image_content_param.py +1 -2
  31. google/genai/_interactions/types/mcp_server_tool_call_content.py +0 -1
  32. google/genai/_interactions/types/mcp_server_tool_call_content_param.py +0 -1
  33. google/genai/_interactions/types/mcp_server_tool_result_content.py +1 -2
  34. google/genai/_interactions/types/mcp_server_tool_result_content_param.py +1 -2
  35. google/genai/_interactions/types/text_content.py +0 -1
  36. google/genai/_interactions/types/text_content_param.py +0 -1
  37. google/genai/_interactions/types/thinking_level.py +1 -1
  38. google/genai/_interactions/types/thought_content.py +0 -1
  39. google/genai/_interactions/types/thought_content_param.py +0 -1
  40. google/genai/_interactions/types/url_context_call_content.py +0 -1
  41. google/genai/_interactions/types/url_context_call_content_param.py +0 -1
  42. google/genai/_interactions/types/url_context_result_content.py +0 -1
  43. google/genai/_interactions/types/url_context_result_content_param.py +0 -1
  44. google/genai/_interactions/types/video_content.py +1 -2
  45. google/genai/_interactions/types/video_content_param.py +1 -2
  46. google/genai/_live_converters.py +2 -30
  47. google/genai/client.py +3 -1
  48. google/genai/models.py +2 -29
  49. google/genai/tunings.py +1 -27
  50. google/genai/types.py +20 -22
  51. google/genai/version.py +1 -1
  52. {google_genai-1.55.0.dist-info → google_genai-1.56.0.dist-info}/METADATA +224 -22
  53. google_genai-1.56.0.dist-info/RECORD +162 -0
  54. google/genai/tests/afc/test_convert_if_exist_pydantic_model.py +0 -309
  55. google/genai/tests/afc/test_convert_number_values_for_function_call_args.py +0 -63
  56. google/genai/tests/afc/test_find_afc_incompatible_tool_indexes.py +0 -240
  57. google/genai/tests/afc/test_generate_content_stream_afc.py +0 -530
  58. google/genai/tests/afc/test_generate_content_stream_afc_thoughts.py +0 -77
  59. google/genai/tests/afc/test_get_function_map.py +0 -176
  60. google/genai/tests/afc/test_get_function_response_parts.py +0 -277
  61. google/genai/tests/afc/test_get_max_remote_calls_for_afc.py +0 -130
  62. google/genai/tests/afc/test_invoke_function_from_dict_args.py +0 -241
  63. google/genai/tests/afc/test_raise_error_for_afc_incompatible_config.py +0 -159
  64. google/genai/tests/afc/test_should_append_afc_history.py +0 -53
  65. google/genai/tests/afc/test_should_disable_afc.py +0 -214
  66. google/genai/tests/batches/__init__.py +0 -17
  67. google/genai/tests/batches/test_cancel.py +0 -77
  68. google/genai/tests/batches/test_create.py +0 -78
  69. google/genai/tests/batches/test_create_with_bigquery.py +0 -113
  70. google/genai/tests/batches/test_create_with_file.py +0 -82
  71. google/genai/tests/batches/test_create_with_gcs.py +0 -125
  72. google/genai/tests/batches/test_create_with_inlined_requests.py +0 -255
  73. google/genai/tests/batches/test_delete.py +0 -86
  74. google/genai/tests/batches/test_embedding.py +0 -157
  75. google/genai/tests/batches/test_get.py +0 -78
  76. google/genai/tests/batches/test_list.py +0 -79
  77. google/genai/tests/caches/__init__.py +0 -17
  78. google/genai/tests/caches/constants.py +0 -29
  79. google/genai/tests/caches/test_create.py +0 -210
  80. google/genai/tests/caches/test_create_custom_url.py +0 -105
  81. google/genai/tests/caches/test_delete.py +0 -54
  82. google/genai/tests/caches/test_delete_custom_url.py +0 -52
  83. google/genai/tests/caches/test_get.py +0 -94
  84. google/genai/tests/caches/test_get_custom_url.py +0 -52
  85. google/genai/tests/caches/test_list.py +0 -68
  86. google/genai/tests/caches/test_update.py +0 -70
  87. google/genai/tests/caches/test_update_custom_url.py +0 -58
  88. google/genai/tests/chats/__init__.py +0 -1
  89. google/genai/tests/chats/test_get_history.py +0 -597
  90. google/genai/tests/chats/test_send_message.py +0 -844
  91. google/genai/tests/chats/test_validate_response.py +0 -90
  92. google/genai/tests/client/__init__.py +0 -17
  93. google/genai/tests/client/test_async_stream.py +0 -427
  94. google/genai/tests/client/test_client_close.py +0 -197
  95. google/genai/tests/client/test_client_initialization.py +0 -1687
  96. google/genai/tests/client/test_client_requests.py +0 -355
  97. google/genai/tests/client/test_custom_client.py +0 -77
  98. google/genai/tests/client/test_http_options.py +0 -178
  99. google/genai/tests/client/test_replay_client_equality.py +0 -168
  100. google/genai/tests/client/test_retries.py +0 -846
  101. google/genai/tests/client/test_upload_errors.py +0 -136
  102. google/genai/tests/common/__init__.py +0 -17
  103. google/genai/tests/common/test_common.py +0 -954
  104. google/genai/tests/conftest.py +0 -162
  105. google/genai/tests/documents/__init__.py +0 -17
  106. google/genai/tests/documents/test_delete.py +0 -51
  107. google/genai/tests/documents/test_get.py +0 -85
  108. google/genai/tests/documents/test_list.py +0 -72
  109. google/genai/tests/errors/__init__.py +0 -1
  110. google/genai/tests/errors/test_api_error.py +0 -417
  111. google/genai/tests/file_search_stores/__init__.py +0 -17
  112. google/genai/tests/file_search_stores/test_create.py +0 -66
  113. google/genai/tests/file_search_stores/test_delete.py +0 -64
  114. google/genai/tests/file_search_stores/test_get.py +0 -94
  115. google/genai/tests/file_search_stores/test_import_file.py +0 -112
  116. google/genai/tests/file_search_stores/test_list.py +0 -57
  117. google/genai/tests/file_search_stores/test_upload_to_file_search_store.py +0 -141
  118. google/genai/tests/files/__init__.py +0 -17
  119. google/genai/tests/files/test_delete.py +0 -46
  120. google/genai/tests/files/test_download.py +0 -85
  121. google/genai/tests/files/test_get.py +0 -46
  122. google/genai/tests/files/test_list.py +0 -72
  123. google/genai/tests/files/test_upload.py +0 -255
  124. google/genai/tests/imports/test_no_optional_imports.py +0 -28
  125. google/genai/tests/interactions/test_integration.py +0 -80
  126. google/genai/tests/live/__init__.py +0 -16
  127. google/genai/tests/live/test_live.py +0 -2177
  128. google/genai/tests/live/test_live_music.py +0 -362
  129. google/genai/tests/live/test_live_response.py +0 -163
  130. google/genai/tests/live/test_send_client_content.py +0 -147
  131. google/genai/tests/live/test_send_realtime_input.py +0 -268
  132. google/genai/tests/live/test_send_tool_response.py +0 -222
  133. google/genai/tests/local_tokenizer/__init__.py +0 -17
  134. google/genai/tests/local_tokenizer/test_local_tokenizer.py +0 -343
  135. google/genai/tests/local_tokenizer/test_local_tokenizer_loader.py +0 -235
  136. google/genai/tests/mcp/__init__.py +0 -17
  137. google/genai/tests/mcp/test_has_mcp_tool_usage.py +0 -89
  138. google/genai/tests/mcp/test_mcp_to_gemini_tools.py +0 -191
  139. google/genai/tests/mcp/test_parse_config_for_mcp_sessions.py +0 -201
  140. google/genai/tests/mcp/test_parse_config_for_mcp_usage.py +0 -130
  141. google/genai/tests/mcp/test_set_mcp_usage_header.py +0 -72
  142. google/genai/tests/models/__init__.py +0 -17
  143. google/genai/tests/models/constants.py +0 -8
  144. google/genai/tests/models/test_compute_tokens.py +0 -120
  145. google/genai/tests/models/test_count_tokens.py +0 -159
  146. google/genai/tests/models/test_delete.py +0 -107
  147. google/genai/tests/models/test_edit_image.py +0 -264
  148. google/genai/tests/models/test_embed_content.py +0 -94
  149. google/genai/tests/models/test_function_call_streaming.py +0 -442
  150. google/genai/tests/models/test_generate_content.py +0 -2502
  151. google/genai/tests/models/test_generate_content_cached_content.py +0 -132
  152. google/genai/tests/models/test_generate_content_config_zero_value.py +0 -103
  153. google/genai/tests/models/test_generate_content_from_apikey.py +0 -44
  154. google/genai/tests/models/test_generate_content_http_options.py +0 -40
  155. google/genai/tests/models/test_generate_content_image_generation.py +0 -143
  156. google/genai/tests/models/test_generate_content_mcp.py +0 -343
  157. google/genai/tests/models/test_generate_content_media_resolution.py +0 -97
  158. google/genai/tests/models/test_generate_content_model.py +0 -139
  159. google/genai/tests/models/test_generate_content_part.py +0 -821
  160. google/genai/tests/models/test_generate_content_thought.py +0 -76
  161. google/genai/tests/models/test_generate_content_tools.py +0 -1761
  162. google/genai/tests/models/test_generate_images.py +0 -191
  163. google/genai/tests/models/test_generate_videos.py +0 -759
  164. google/genai/tests/models/test_get.py +0 -104
  165. google/genai/tests/models/test_list.py +0 -233
  166. google/genai/tests/models/test_recontext_image.py +0 -189
  167. google/genai/tests/models/test_segment_image.py +0 -148
  168. google/genai/tests/models/test_update.py +0 -95
  169. google/genai/tests/models/test_upscale_image.py +0 -157
  170. google/genai/tests/operations/__init__.py +0 -17
  171. google/genai/tests/operations/test_get.py +0 -38
  172. google/genai/tests/public_samples/__init__.py +0 -17
  173. google/genai/tests/public_samples/test_gemini_text_only.py +0 -34
  174. google/genai/tests/pytest_helper.py +0 -229
  175. google/genai/tests/shared/__init__.py +0 -16
  176. google/genai/tests/shared/batches/__init__.py +0 -14
  177. google/genai/tests/shared/batches/test_create_delete.py +0 -57
  178. google/genai/tests/shared/batches/test_create_get_cancel.py +0 -56
  179. google/genai/tests/shared/batches/test_list.py +0 -40
  180. google/genai/tests/shared/caches/__init__.py +0 -14
  181. google/genai/tests/shared/caches/test_create_get_delete.py +0 -67
  182. google/genai/tests/shared/caches/test_create_update_get.py +0 -71
  183. google/genai/tests/shared/caches/test_list.py +0 -40
  184. google/genai/tests/shared/chats/__init__.py +0 -14
  185. google/genai/tests/shared/chats/test_send_message.py +0 -48
  186. google/genai/tests/shared/chats/test_send_message_stream.py +0 -50
  187. google/genai/tests/shared/files/__init__.py +0 -14
  188. google/genai/tests/shared/files/test_list.py +0 -41
  189. google/genai/tests/shared/files/test_upload_get_delete.py +0 -54
  190. google/genai/tests/shared/models/__init__.py +0 -14
  191. google/genai/tests/shared/models/test_compute_tokens.py +0 -41
  192. google/genai/tests/shared/models/test_count_tokens.py +0 -40
  193. google/genai/tests/shared/models/test_edit_image.py +0 -67
  194. google/genai/tests/shared/models/test_embed.py +0 -40
  195. google/genai/tests/shared/models/test_generate_content.py +0 -39
  196. google/genai/tests/shared/models/test_generate_content_stream.py +0 -54
  197. google/genai/tests/shared/models/test_generate_images.py +0 -40
  198. google/genai/tests/shared/models/test_generate_videos.py +0 -38
  199. google/genai/tests/shared/models/test_list.py +0 -37
  200. google/genai/tests/shared/models/test_recontext_image.py +0 -55
  201. google/genai/tests/shared/models/test_segment_image.py +0 -52
  202. google/genai/tests/shared/models/test_upscale_image.py +0 -52
  203. google/genai/tests/shared/tunings/__init__.py +0 -16
  204. google/genai/tests/shared/tunings/test_create.py +0 -46
  205. google/genai/tests/shared/tunings/test_create_get_cancel.py +0 -56
  206. google/genai/tests/shared/tunings/test_list.py +0 -39
  207. google/genai/tests/tokens/__init__.py +0 -16
  208. google/genai/tests/tokens/test_create.py +0 -154
  209. google/genai/tests/transformers/__init__.py +0 -17
  210. google/genai/tests/transformers/test_blobs.py +0 -71
  211. google/genai/tests/transformers/test_bytes.py +0 -15
  212. google/genai/tests/transformers/test_duck_type.py +0 -96
  213. google/genai/tests/transformers/test_function_responses.py +0 -72
  214. google/genai/tests/transformers/test_schema.py +0 -653
  215. google/genai/tests/transformers/test_t_batch.py +0 -286
  216. google/genai/tests/transformers/test_t_content.py +0 -160
  217. google/genai/tests/transformers/test_t_contents.py +0 -398
  218. google/genai/tests/transformers/test_t_part.py +0 -85
  219. google/genai/tests/transformers/test_t_parts.py +0 -87
  220. google/genai/tests/transformers/test_t_tool.py +0 -157
  221. google/genai/tests/transformers/test_t_tools.py +0 -195
  222. google/genai/tests/tunings/__init__.py +0 -16
  223. google/genai/tests/tunings/test_cancel.py +0 -39
  224. google/genai/tests/tunings/test_end_to_end.py +0 -106
  225. google/genai/tests/tunings/test_get.py +0 -67
  226. google/genai/tests/tunings/test_list.py +0 -75
  227. google/genai/tests/tunings/test_tune.py +0 -268
  228. google/genai/tests/types/__init__.py +0 -16
  229. google/genai/tests/types/test_bytes_internal.py +0 -271
  230. google/genai/tests/types/test_bytes_type.py +0 -152
  231. google/genai/tests/types/test_future.py +0 -101
  232. google/genai/tests/types/test_optional_types.py +0 -36
  233. google/genai/tests/types/test_part_type.py +0 -616
  234. google/genai/tests/types/test_schema_from_json_schema.py +0 -417
  235. google/genai/tests/types/test_schema_json_schema.py +0 -468
  236. google/genai/tests/types/test_types.py +0 -2903
  237. google_genai-1.55.0.dist-info/RECORD +0 -345
  238. /google/genai/{tests/interactions/__init__.py → _interactions/py.typed} +0 -0
  239. {google_genai-1.55.0.dist-info → google_genai-1.56.0.dist-info}/WHEEL +0 -0
  240. {google_genai-1.55.0.dist-info → google_genai-1.56.0.dist-info}/licenses/LICENSE +0 -0
  241. {google_genai-1.55.0.dist-info → google_genai-1.56.0.dist-info}/top_level.txt +0 -0
@@ -1,616 +0,0 @@
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