google-genai 1.54.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.
- google/genai/__init__.py +1 -0
- google/genai/_interactions/__init__.py +117 -0
- google/genai/_interactions/_base_client.py +2019 -0
- google/genai/_interactions/_client.py +511 -0
- google/genai/_interactions/_compat.py +234 -0
- google/genai/_interactions/_constants.py +29 -0
- google/genai/_interactions/_exceptions.py +122 -0
- google/genai/_interactions/_files.py +139 -0
- google/genai/_interactions/_models.py +873 -0
- google/genai/_interactions/_qs.py +165 -0
- google/genai/_interactions/_resource.py +58 -0
- google/genai/_interactions/_response.py +847 -0
- google/genai/_interactions/_streaming.py +354 -0
- google/genai/_interactions/_types.py +276 -0
- google/genai/_interactions/_utils/__init__.py +79 -0
- google/genai/_interactions/_utils/_compat.py +61 -0
- google/genai/_interactions/_utils/_datetime_parse.py +151 -0
- google/genai/_interactions/_utils/_logs.py +40 -0
- google/genai/_interactions/_utils/_proxy.py +80 -0
- google/genai/_interactions/_utils/_reflection.py +57 -0
- google/genai/_interactions/_utils/_resources_proxy.py +39 -0
- google/genai/_interactions/_utils/_streams.py +27 -0
- google/genai/_interactions/_utils/_sync.py +73 -0
- google/genai/_interactions/_utils/_transform.py +472 -0
- google/genai/_interactions/_utils/_typing.py +172 -0
- google/genai/_interactions/_utils/_utils.py +437 -0
- google/genai/_interactions/_version.py +18 -0
- google/genai/_interactions/resources/__init__.py +34 -0
- google/genai/_interactions/resources/interactions.py +1350 -0
- google/genai/_interactions/types/__init__.py +107 -0
- google/genai/_interactions/types/allowed_tools.py +33 -0
- google/genai/_interactions/types/allowed_tools_param.py +35 -0
- google/genai/_interactions/types/annotation.py +42 -0
- google/genai/_interactions/types/annotation_param.py +42 -0
- google/genai/_interactions/types/audio_content.py +38 -0
- google/genai/_interactions/types/audio_content_param.py +45 -0
- google/genai/_interactions/types/audio_mime_type.py +25 -0
- google/genai/_interactions/types/audio_mime_type_param.py +27 -0
- google/genai/_interactions/types/code_execution_call_arguments.py +33 -0
- google/genai/_interactions/types/code_execution_call_arguments_param.py +32 -0
- google/genai/_interactions/types/code_execution_call_content.py +37 -0
- google/genai/_interactions/types/code_execution_call_content_param.py +37 -0
- google/genai/_interactions/types/code_execution_result_content.py +42 -0
- google/genai/_interactions/types/code_execution_result_content_param.py +41 -0
- google/genai/_interactions/types/content_delta.py +358 -0
- google/genai/_interactions/types/content_start.py +79 -0
- google/genai/_interactions/types/content_stop.py +35 -0
- google/genai/_interactions/types/deep_research_agent_config.py +33 -0
- google/genai/_interactions/types/deep_research_agent_config_param.py +32 -0
- google/genai/_interactions/types/document_content.py +36 -0
- google/genai/_interactions/types/document_content_param.py +43 -0
- google/genai/_interactions/types/dynamic_agent_config.py +44 -0
- google/genai/_interactions/types/dynamic_agent_config_param.py +33 -0
- google/genai/_interactions/types/error_event.py +46 -0
- google/genai/_interactions/types/file_search_result_content.py +46 -0
- google/genai/_interactions/types/file_search_result_content_param.py +46 -0
- google/genai/_interactions/types/function.py +38 -0
- google/genai/_interactions/types/function_call_content.py +39 -0
- google/genai/_interactions/types/function_call_content_param.py +39 -0
- google/genai/_interactions/types/function_param.py +37 -0
- google/genai/_interactions/types/function_result_content.py +52 -0
- google/genai/_interactions/types/function_result_content_param.py +54 -0
- google/genai/_interactions/types/generation_config.py +57 -0
- google/genai/_interactions/types/generation_config_param.py +59 -0
- google/genai/_interactions/types/google_search_call_arguments.py +29 -0
- google/genai/_interactions/types/google_search_call_arguments_param.py +31 -0
- google/genai/_interactions/types/google_search_call_content.py +37 -0
- google/genai/_interactions/types/google_search_call_content_param.py +37 -0
- google/genai/_interactions/types/google_search_result.py +35 -0
- google/genai/_interactions/types/google_search_result_content.py +43 -0
- google/genai/_interactions/types/google_search_result_content_param.py +44 -0
- google/genai/_interactions/types/google_search_result_param.py +35 -0
- google/genai/_interactions/types/image_content.py +41 -0
- google/genai/_interactions/types/image_content_param.py +48 -0
- google/genai/_interactions/types/image_mime_type.py +23 -0
- google/genai/_interactions/types/image_mime_type_param.py +25 -0
- google/genai/_interactions/types/interaction.py +165 -0
- google/genai/_interactions/types/interaction_create_params.py +212 -0
- google/genai/_interactions/types/interaction_event.py +37 -0
- google/genai/_interactions/types/interaction_get_params.py +46 -0
- google/genai/_interactions/types/interaction_sse_event.py +32 -0
- google/genai/_interactions/types/interaction_status_update.py +37 -0
- google/genai/_interactions/types/mcp_server_tool_call_content.py +42 -0
- google/genai/_interactions/types/mcp_server_tool_call_content_param.py +42 -0
- google/genai/_interactions/types/mcp_server_tool_result_content.py +52 -0
- google/genai/_interactions/types/mcp_server_tool_result_content_param.py +54 -0
- google/genai/_interactions/types/model.py +36 -0
- google/genai/_interactions/types/model_param.py +38 -0
- google/genai/_interactions/types/speech_config.py +35 -0
- google/genai/_interactions/types/speech_config_param.py +35 -0
- google/genai/_interactions/types/text_content.py +37 -0
- google/genai/_interactions/types/text_content_param.py +38 -0
- google/genai/_interactions/types/thinking_level.py +22 -0
- google/genai/_interactions/types/thought_content.py +41 -0
- google/genai/_interactions/types/thought_content_param.py +47 -0
- google/genai/_interactions/types/tool.py +100 -0
- google/genai/_interactions/types/tool_choice.py +26 -0
- google/genai/_interactions/types/tool_choice_config.py +28 -0
- google/genai/_interactions/types/tool_choice_config_param.py +29 -0
- google/genai/_interactions/types/tool_choice_param.py +28 -0
- google/genai/_interactions/types/tool_choice_type.py +22 -0
- google/genai/_interactions/types/tool_param.py +97 -0
- google/genai/_interactions/types/turn.py +76 -0
- google/genai/_interactions/types/turn_param.py +73 -0
- google/genai/_interactions/types/url_context_call_arguments.py +29 -0
- google/genai/_interactions/types/url_context_call_arguments_param.py +31 -0
- google/genai/_interactions/types/url_context_call_content.py +37 -0
- google/genai/_interactions/types/url_context_call_content_param.py +37 -0
- google/genai/_interactions/types/url_context_result.py +33 -0
- google/genai/_interactions/types/url_context_result_content.py +43 -0
- google/genai/_interactions/types/url_context_result_content_param.py +44 -0
- google/genai/_interactions/types/url_context_result_param.py +32 -0
- google/genai/_interactions/types/usage.py +106 -0
- google/genai/_interactions/types/usage_param.py +106 -0
- google/genai/_interactions/types/video_content.py +41 -0
- google/genai/_interactions/types/video_content_param.py +48 -0
- google/genai/_interactions/types/video_mime_type.py +36 -0
- google/genai/_interactions/types/video_mime_type_param.py +38 -0
- google/genai/_live_converters.py +31 -0
- google/genai/_tokens_converters.py +5 -0
- google/genai/batches.py +7 -0
- google/genai/client.py +223 -0
- google/genai/interactions.py +17 -0
- google/genai/live.py +4 -3
- google/genai/models.py +12 -0
- google/genai/tests/__init__.py +21 -0
- google/genai/tests/afc/__init__.py +21 -0
- google/genai/tests/afc/test_convert_if_exist_pydantic_model.py +309 -0
- google/genai/tests/afc/test_convert_number_values_for_function_call_args.py +63 -0
- google/genai/tests/afc/test_find_afc_incompatible_tool_indexes.py +240 -0
- google/genai/tests/afc/test_generate_content_stream_afc.py +530 -0
- google/genai/tests/afc/test_generate_content_stream_afc_thoughts.py +77 -0
- google/genai/tests/afc/test_get_function_map.py +176 -0
- google/genai/tests/afc/test_get_function_response_parts.py +277 -0
- google/genai/tests/afc/test_get_max_remote_calls_for_afc.py +130 -0
- google/genai/tests/afc/test_invoke_function_from_dict_args.py +241 -0
- google/genai/tests/afc/test_raise_error_for_afc_incompatible_config.py +159 -0
- google/genai/tests/afc/test_should_append_afc_history.py +53 -0
- google/genai/tests/afc/test_should_disable_afc.py +214 -0
- google/genai/tests/batches/__init__.py +17 -0
- google/genai/tests/batches/test_cancel.py +77 -0
- google/genai/tests/batches/test_create.py +78 -0
- google/genai/tests/batches/test_create_with_bigquery.py +113 -0
- google/genai/tests/batches/test_create_with_file.py +82 -0
- google/genai/tests/batches/test_create_with_gcs.py +125 -0
- google/genai/tests/batches/test_create_with_inlined_requests.py +255 -0
- google/genai/tests/batches/test_delete.py +86 -0
- google/genai/tests/batches/test_embedding.py +157 -0
- google/genai/tests/batches/test_get.py +78 -0
- google/genai/tests/batches/test_list.py +79 -0
- google/genai/tests/caches/__init__.py +17 -0
- google/genai/tests/caches/constants.py +29 -0
- google/genai/tests/caches/test_create.py +210 -0
- google/genai/tests/caches/test_create_custom_url.py +105 -0
- google/genai/tests/caches/test_delete.py +54 -0
- google/genai/tests/caches/test_delete_custom_url.py +52 -0
- google/genai/tests/caches/test_get.py +94 -0
- google/genai/tests/caches/test_get_custom_url.py +52 -0
- google/genai/tests/caches/test_list.py +68 -0
- google/genai/tests/caches/test_update.py +70 -0
- google/genai/tests/caches/test_update_custom_url.py +58 -0
- google/genai/tests/chats/__init__.py +1 -0
- google/genai/tests/chats/test_get_history.py +597 -0
- google/genai/tests/chats/test_send_message.py +844 -0
- google/genai/tests/chats/test_validate_response.py +90 -0
- google/genai/tests/client/__init__.py +17 -0
- google/genai/tests/client/test_async_stream.py +427 -0
- google/genai/tests/client/test_client_close.py +197 -0
- google/genai/tests/client/test_client_initialization.py +1687 -0
- google/genai/tests/client/test_client_requests.py +355 -0
- google/genai/tests/client/test_custom_client.py +77 -0
- google/genai/tests/client/test_http_options.py +178 -0
- google/genai/tests/client/test_replay_client_equality.py +168 -0
- google/genai/tests/client/test_retries.py +846 -0
- google/genai/tests/client/test_upload_errors.py +136 -0
- google/genai/tests/common/__init__.py +17 -0
- google/genai/tests/common/test_common.py +954 -0
- google/genai/tests/conftest.py +162 -0
- google/genai/tests/documents/__init__.py +17 -0
- google/genai/tests/documents/test_delete.py +51 -0
- google/genai/tests/documents/test_get.py +85 -0
- google/genai/tests/documents/test_list.py +72 -0
- google/genai/tests/errors/__init__.py +1 -0
- google/genai/tests/errors/test_api_error.py +417 -0
- google/genai/tests/file_search_stores/__init__.py +17 -0
- google/genai/tests/file_search_stores/test_create.py +66 -0
- google/genai/tests/file_search_stores/test_delete.py +64 -0
- google/genai/tests/file_search_stores/test_get.py +94 -0
- google/genai/tests/file_search_stores/test_import_file.py +112 -0
- google/genai/tests/file_search_stores/test_list.py +57 -0
- google/genai/tests/file_search_stores/test_upload_to_file_search_store.py +141 -0
- google/genai/tests/files/__init__.py +17 -0
- google/genai/tests/files/test_delete.py +46 -0
- google/genai/tests/files/test_download.py +85 -0
- google/genai/tests/files/test_get.py +46 -0
- google/genai/tests/files/test_list.py +72 -0
- google/genai/tests/files/test_upload.py +255 -0
- google/genai/tests/imports/test_no_optional_imports.py +28 -0
- google/genai/tests/interactions/__init__.py +0 -0
- google/genai/tests/interactions/test_integration.py +80 -0
- google/genai/tests/live/__init__.py +16 -0
- google/genai/tests/live/test_live.py +2177 -0
- google/genai/tests/live/test_live_music.py +362 -0
- google/genai/tests/live/test_live_response.py +163 -0
- google/genai/tests/live/test_send_client_content.py +147 -0
- google/genai/tests/live/test_send_realtime_input.py +268 -0
- google/genai/tests/live/test_send_tool_response.py +222 -0
- google/genai/tests/local_tokenizer/__init__.py +17 -0
- google/genai/tests/local_tokenizer/test_local_tokenizer.py +343 -0
- google/genai/tests/local_tokenizer/test_local_tokenizer_loader.py +235 -0
- google/genai/tests/mcp/__init__.py +17 -0
- google/genai/tests/mcp/test_has_mcp_tool_usage.py +89 -0
- google/genai/tests/mcp/test_mcp_to_gemini_tools.py +191 -0
- google/genai/tests/mcp/test_parse_config_for_mcp_sessions.py +201 -0
- google/genai/tests/mcp/test_parse_config_for_mcp_usage.py +130 -0
- google/genai/tests/mcp/test_set_mcp_usage_header.py +72 -0
- google/genai/tests/models/__init__.py +17 -0
- google/genai/tests/models/constants.py +8 -0
- google/genai/tests/models/test_compute_tokens.py +120 -0
- google/genai/tests/models/test_count_tokens.py +159 -0
- google/genai/tests/models/test_delete.py +107 -0
- google/genai/tests/models/test_edit_image.py +264 -0
- google/genai/tests/models/test_embed_content.py +94 -0
- google/genai/tests/models/test_function_call_streaming.py +442 -0
- google/genai/tests/models/test_generate_content.py +2502 -0
- google/genai/tests/models/test_generate_content_cached_content.py +132 -0
- google/genai/tests/models/test_generate_content_config_zero_value.py +103 -0
- google/genai/tests/models/test_generate_content_from_apikey.py +44 -0
- google/genai/tests/models/test_generate_content_http_options.py +40 -0
- google/genai/tests/models/test_generate_content_image_generation.py +143 -0
- google/genai/tests/models/test_generate_content_mcp.py +343 -0
- google/genai/tests/models/test_generate_content_media_resolution.py +97 -0
- google/genai/tests/models/test_generate_content_model.py +139 -0
- google/genai/tests/models/test_generate_content_part.py +821 -0
- google/genai/tests/models/test_generate_content_thought.py +76 -0
- google/genai/tests/models/test_generate_content_tools.py +1761 -0
- google/genai/tests/models/test_generate_images.py +191 -0
- google/genai/tests/models/test_generate_videos.py +759 -0
- google/genai/tests/models/test_get.py +104 -0
- google/genai/tests/models/test_list.py +233 -0
- google/genai/tests/models/test_recontext_image.py +189 -0
- google/genai/tests/models/test_segment_image.py +148 -0
- google/genai/tests/models/test_update.py +95 -0
- google/genai/tests/models/test_upscale_image.py +157 -0
- google/genai/tests/operations/__init__.py +17 -0
- google/genai/tests/operations/test_get.py +38 -0
- google/genai/tests/public_samples/__init__.py +17 -0
- google/genai/tests/public_samples/test_gemini_text_only.py +34 -0
- google/genai/tests/pytest_helper.py +229 -0
- google/genai/tests/shared/__init__.py +16 -0
- google/genai/tests/shared/batches/__init__.py +14 -0
- google/genai/tests/shared/batches/test_create_delete.py +57 -0
- google/genai/tests/shared/batches/test_create_get_cancel.py +56 -0
- google/genai/tests/shared/batches/test_list.py +40 -0
- google/genai/tests/shared/caches/__init__.py +14 -0
- google/genai/tests/shared/caches/test_create_get_delete.py +67 -0
- google/genai/tests/shared/caches/test_create_update_get.py +71 -0
- google/genai/tests/shared/caches/test_list.py +40 -0
- google/genai/tests/shared/chats/__init__.py +14 -0
- google/genai/tests/shared/chats/test_send_message.py +48 -0
- google/genai/tests/shared/chats/test_send_message_stream.py +50 -0
- google/genai/tests/shared/files/__init__.py +14 -0
- google/genai/tests/shared/files/test_list.py +41 -0
- google/genai/tests/shared/files/test_upload_get_delete.py +54 -0
- google/genai/tests/shared/models/__init__.py +14 -0
- google/genai/tests/shared/models/test_compute_tokens.py +41 -0
- google/genai/tests/shared/models/test_count_tokens.py +40 -0
- google/genai/tests/shared/models/test_edit_image.py +67 -0
- google/genai/tests/shared/models/test_embed.py +40 -0
- google/genai/tests/shared/models/test_generate_content.py +39 -0
- google/genai/tests/shared/models/test_generate_content_stream.py +54 -0
- google/genai/tests/shared/models/test_generate_images.py +40 -0
- google/genai/tests/shared/models/test_generate_videos.py +38 -0
- google/genai/tests/shared/models/test_list.py +37 -0
- google/genai/tests/shared/models/test_recontext_image.py +55 -0
- google/genai/tests/shared/models/test_segment_image.py +52 -0
- google/genai/tests/shared/models/test_upscale_image.py +52 -0
- google/genai/tests/shared/tunings/__init__.py +16 -0
- google/genai/tests/shared/tunings/test_create.py +46 -0
- google/genai/tests/shared/tunings/test_create_get_cancel.py +56 -0
- google/genai/tests/shared/tunings/test_list.py +39 -0
- google/genai/tests/tokens/__init__.py +16 -0
- google/genai/tests/tokens/test_create.py +154 -0
- google/genai/tests/transformers/__init__.py +17 -0
- google/genai/tests/transformers/test_blobs.py +71 -0
- google/genai/tests/transformers/test_bytes.py +15 -0
- google/genai/tests/transformers/test_duck_type.py +96 -0
- google/genai/tests/transformers/test_function_responses.py +72 -0
- google/genai/tests/transformers/test_schema.py +653 -0
- google/genai/tests/transformers/test_t_batch.py +286 -0
- google/genai/tests/transformers/test_t_content.py +160 -0
- google/genai/tests/transformers/test_t_contents.py +398 -0
- google/genai/tests/transformers/test_t_part.py +85 -0
- google/genai/tests/transformers/test_t_parts.py +87 -0
- google/genai/tests/transformers/test_t_tool.py +157 -0
- google/genai/tests/transformers/test_t_tools.py +195 -0
- google/genai/tests/tunings/__init__.py +16 -0
- google/genai/tests/tunings/test_cancel.py +39 -0
- google/genai/tests/tunings/test_end_to_end.py +106 -0
- google/genai/tests/tunings/test_get.py +67 -0
- google/genai/tests/tunings/test_list.py +75 -0
- google/genai/tests/tunings/test_tune.py +268 -0
- google/genai/tests/types/__init__.py +16 -0
- google/genai/tests/types/test_bytes_internal.py +271 -0
- google/genai/tests/types/test_bytes_type.py +152 -0
- google/genai/tests/types/test_future.py +101 -0
- google/genai/tests/types/test_optional_types.py +36 -0
- google/genai/tests/types/test_part_type.py +616 -0
- google/genai/tests/types/test_schema_from_json_schema.py +417 -0
- google/genai/tests/types/test_schema_json_schema.py +468 -0
- google/genai/tests/types/test_types.py +2903 -0
- google/genai/types.py +72 -0
- google/genai/version.py +1 -1
- {google_genai-1.54.0.dist-info → google_genai-1.55.0.dist-info}/METADATA +3 -1
- google_genai-1.55.0.dist-info/RECORD +345 -0
- google_genai-1.54.0.dist-info/RECORD +0 -41
- {google_genai-1.54.0.dist-info → google_genai-1.55.0.dist-info}/WHEEL +0 -0
- {google_genai-1.54.0.dist-info → google_genai-1.55.0.dist-info}/licenses/LICENSE +0 -0
- {google_genai-1.54.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
|