google-genai 1.56.0__py3-none-any.whl → 1.58.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 (246) hide show
  1. google/genai/_api_client.py +49 -26
  2. google/genai/_interactions/__init__.py +3 -0
  3. google/genai/_interactions/_base_client.py +1 -1
  4. google/genai/_interactions/_client.py +57 -3
  5. google/genai/_interactions/_client_adapter.py +48 -0
  6. google/genai/_interactions/types/__init__.py +6 -0
  7. google/genai/_interactions/types/audio_content.py +2 -0
  8. google/genai/_interactions/types/audio_content_param.py +2 -0
  9. google/genai/_interactions/types/content.py +65 -0
  10. google/genai/_interactions/types/content_delta.py +10 -2
  11. google/genai/_interactions/types/content_param.py +63 -0
  12. google/genai/_interactions/types/content_start.py +5 -46
  13. google/genai/_interactions/types/content_stop.py +1 -2
  14. google/genai/_interactions/types/document_content.py +2 -0
  15. google/genai/_interactions/types/document_content_param.py +2 -0
  16. google/genai/_interactions/types/error_event.py +1 -2
  17. google/genai/_interactions/types/file_search_call_content.py +32 -0
  18. google/genai/_interactions/types/file_search_call_content_param.py +31 -0
  19. google/genai/_interactions/types/generation_config.py +4 -0
  20. google/genai/_interactions/types/generation_config_param.py +4 -0
  21. google/genai/_interactions/types/image_config.py +31 -0
  22. google/genai/_interactions/types/image_config_param.py +30 -0
  23. google/genai/_interactions/types/image_content.py +2 -0
  24. google/genai/_interactions/types/image_content_param.py +2 -0
  25. google/genai/_interactions/types/interaction.py +6 -52
  26. google/genai/_interactions/types/interaction_create_params.py +4 -22
  27. google/genai/_interactions/types/interaction_event.py +1 -2
  28. google/genai/_interactions/types/interaction_sse_event.py +5 -3
  29. google/genai/_interactions/types/interaction_status_update.py +1 -2
  30. google/genai/_interactions/types/model.py +1 -0
  31. google/genai/_interactions/types/model_param.py +1 -0
  32. google/genai/_interactions/types/turn.py +3 -44
  33. google/genai/_interactions/types/turn_param.py +4 -40
  34. google/genai/_interactions/types/usage.py +1 -1
  35. google/genai/_interactions/types/usage_param.py +1 -1
  36. google/genai/_interactions/types/video_content.py +2 -0
  37. google/genai/_interactions/types/video_content_param.py +2 -0
  38. google/genai/_live_converters.py +118 -34
  39. google/genai/_local_tokenizer_loader.py +1 -0
  40. google/genai/_tokens_converters.py +14 -14
  41. google/genai/_transformers.py +15 -21
  42. google/genai/batches.py +27 -22
  43. google/genai/caches.py +42 -42
  44. google/genai/chats.py +0 -2
  45. google/genai/client.py +61 -55
  46. google/genai/files.py +224 -0
  47. google/genai/live.py +1 -1
  48. google/genai/models.py +56 -44
  49. google/genai/tests/__init__.py +21 -0
  50. google/genai/tests/afc/__init__.py +21 -0
  51. google/genai/tests/afc/test_convert_if_exist_pydantic_model.py +309 -0
  52. google/genai/tests/afc/test_convert_number_values_for_function_call_args.py +63 -0
  53. google/genai/tests/afc/test_find_afc_incompatible_tool_indexes.py +240 -0
  54. google/genai/tests/afc/test_generate_content_stream_afc.py +530 -0
  55. google/genai/tests/afc/test_generate_content_stream_afc_thoughts.py +77 -0
  56. google/genai/tests/afc/test_get_function_map.py +176 -0
  57. google/genai/tests/afc/test_get_function_response_parts.py +277 -0
  58. google/genai/tests/afc/test_get_max_remote_calls_for_afc.py +130 -0
  59. google/genai/tests/afc/test_invoke_function_from_dict_args.py +241 -0
  60. google/genai/tests/afc/test_raise_error_for_afc_incompatible_config.py +159 -0
  61. google/genai/tests/afc/test_should_append_afc_history.py +53 -0
  62. google/genai/tests/afc/test_should_disable_afc.py +214 -0
  63. google/genai/tests/batches/__init__.py +17 -0
  64. google/genai/tests/batches/test_cancel.py +77 -0
  65. google/genai/tests/batches/test_create.py +78 -0
  66. google/genai/tests/batches/test_create_with_bigquery.py +113 -0
  67. google/genai/tests/batches/test_create_with_file.py +82 -0
  68. google/genai/tests/batches/test_create_with_gcs.py +125 -0
  69. google/genai/tests/batches/test_create_with_inlined_requests.py +255 -0
  70. google/genai/tests/batches/test_delete.py +86 -0
  71. google/genai/tests/batches/test_embedding.py +157 -0
  72. google/genai/tests/batches/test_get.py +78 -0
  73. google/genai/tests/batches/test_list.py +79 -0
  74. google/genai/tests/caches/__init__.py +17 -0
  75. google/genai/tests/caches/constants.py +29 -0
  76. google/genai/tests/caches/test_create.py +210 -0
  77. google/genai/tests/caches/test_create_custom_url.py +105 -0
  78. google/genai/tests/caches/test_delete.py +54 -0
  79. google/genai/tests/caches/test_delete_custom_url.py +52 -0
  80. google/genai/tests/caches/test_get.py +94 -0
  81. google/genai/tests/caches/test_get_custom_url.py +52 -0
  82. google/genai/tests/caches/test_list.py +68 -0
  83. google/genai/tests/caches/test_update.py +70 -0
  84. google/genai/tests/caches/test_update_custom_url.py +58 -0
  85. google/genai/tests/chats/__init__.py +1 -0
  86. google/genai/tests/chats/test_get_history.py +598 -0
  87. google/genai/tests/chats/test_send_message.py +844 -0
  88. google/genai/tests/chats/test_validate_response.py +90 -0
  89. google/genai/tests/client/__init__.py +17 -0
  90. google/genai/tests/client/test_async_stream.py +427 -0
  91. google/genai/tests/client/test_client_close.py +197 -0
  92. google/genai/tests/client/test_client_initialization.py +1687 -0
  93. google/genai/tests/client/test_client_requests.py +221 -0
  94. google/genai/tests/client/test_custom_client.py +104 -0
  95. google/genai/tests/client/test_http_options.py +178 -0
  96. google/genai/tests/client/test_replay_client_equality.py +168 -0
  97. google/genai/tests/client/test_retries.py +846 -0
  98. google/genai/tests/client/test_upload_errors.py +136 -0
  99. google/genai/tests/common/__init__.py +17 -0
  100. google/genai/tests/common/test_common.py +954 -0
  101. google/genai/tests/conftest.py +162 -0
  102. google/genai/tests/documents/__init__.py +17 -0
  103. google/genai/tests/documents/test_delete.py +51 -0
  104. google/genai/tests/documents/test_get.py +85 -0
  105. google/genai/tests/documents/test_list.py +72 -0
  106. google/genai/tests/errors/__init__.py +1 -0
  107. google/genai/tests/errors/test_api_error.py +417 -0
  108. google/genai/tests/file_search_stores/__init__.py +17 -0
  109. google/genai/tests/file_search_stores/test_create.py +66 -0
  110. google/genai/tests/file_search_stores/test_delete.py +64 -0
  111. google/genai/tests/file_search_stores/test_get.py +94 -0
  112. google/genai/tests/file_search_stores/test_import_file.py +112 -0
  113. google/genai/tests/file_search_stores/test_list.py +57 -0
  114. google/genai/tests/file_search_stores/test_upload_to_file_search_store.py +141 -0
  115. google/genai/tests/files/__init__.py +17 -0
  116. google/genai/tests/files/test_delete.py +46 -0
  117. google/genai/tests/files/test_download.py +85 -0
  118. google/genai/tests/files/test_get.py +46 -0
  119. google/genai/tests/files/test_list.py +72 -0
  120. google/genai/tests/files/test_register.py +272 -0
  121. google/genai/tests/files/test_register_table.py +70 -0
  122. google/genai/tests/files/test_upload.py +255 -0
  123. google/genai/tests/imports/test_no_optional_imports.py +28 -0
  124. google/genai/tests/interactions/test_auth.py +476 -0
  125. google/genai/tests/interactions/test_integration.py +84 -0
  126. google/genai/tests/interactions/test_paths.py +105 -0
  127. google/genai/tests/live/__init__.py +16 -0
  128. google/genai/tests/live/test_live.py +2143 -0
  129. google/genai/tests/live/test_live_music.py +362 -0
  130. google/genai/tests/live/test_live_response.py +163 -0
  131. google/genai/tests/live/test_send_client_content.py +147 -0
  132. google/genai/tests/live/test_send_realtime_input.py +268 -0
  133. google/genai/tests/live/test_send_tool_response.py +222 -0
  134. google/genai/tests/local_tokenizer/__init__.py +17 -0
  135. google/genai/tests/local_tokenizer/test_local_tokenizer.py +343 -0
  136. google/genai/tests/local_tokenizer/test_local_tokenizer_loader.py +235 -0
  137. google/genai/tests/mcp/__init__.py +17 -0
  138. google/genai/tests/mcp/test_has_mcp_tool_usage.py +89 -0
  139. google/genai/tests/mcp/test_mcp_to_gemini_tools.py +191 -0
  140. google/genai/tests/mcp/test_parse_config_for_mcp_sessions.py +201 -0
  141. google/genai/tests/mcp/test_parse_config_for_mcp_usage.py +130 -0
  142. google/genai/tests/mcp/test_set_mcp_usage_header.py +72 -0
  143. google/genai/tests/models/__init__.py +17 -0
  144. google/genai/tests/models/constants.py +8 -0
  145. google/genai/tests/models/test_compute_tokens.py +120 -0
  146. google/genai/tests/models/test_count_tokens.py +159 -0
  147. google/genai/tests/models/test_delete.py +107 -0
  148. google/genai/tests/models/test_edit_image.py +264 -0
  149. google/genai/tests/models/test_embed_content.py +94 -0
  150. google/genai/tests/models/test_function_call_streaming.py +442 -0
  151. google/genai/tests/models/test_generate_content.py +2501 -0
  152. google/genai/tests/models/test_generate_content_cached_content.py +132 -0
  153. google/genai/tests/models/test_generate_content_config_zero_value.py +103 -0
  154. google/genai/tests/models/test_generate_content_from_apikey.py +44 -0
  155. google/genai/tests/models/test_generate_content_http_options.py +40 -0
  156. google/genai/tests/models/test_generate_content_image_generation.py +143 -0
  157. google/genai/tests/models/test_generate_content_mcp.py +343 -0
  158. google/genai/tests/models/test_generate_content_media_resolution.py +97 -0
  159. google/genai/tests/models/test_generate_content_model.py +139 -0
  160. google/genai/tests/models/test_generate_content_part.py +821 -0
  161. google/genai/tests/models/test_generate_content_thought.py +76 -0
  162. google/genai/tests/models/test_generate_content_tools.py +1761 -0
  163. google/genai/tests/models/test_generate_images.py +191 -0
  164. google/genai/tests/models/test_generate_videos.py +759 -0
  165. google/genai/tests/models/test_get.py +104 -0
  166. google/genai/tests/models/test_list.py +233 -0
  167. google/genai/tests/models/test_recontext_image.py +189 -0
  168. google/genai/tests/models/test_segment_image.py +148 -0
  169. google/genai/tests/models/test_update.py +95 -0
  170. google/genai/tests/models/test_upscale_image.py +157 -0
  171. google/genai/tests/operations/__init__.py +17 -0
  172. google/genai/tests/operations/test_get.py +38 -0
  173. google/genai/tests/public_samples/__init__.py +17 -0
  174. google/genai/tests/public_samples/test_gemini_text_only.py +34 -0
  175. google/genai/tests/pytest_helper.py +246 -0
  176. google/genai/tests/shared/__init__.py +16 -0
  177. google/genai/tests/shared/batches/__init__.py +14 -0
  178. google/genai/tests/shared/batches/test_create_delete.py +57 -0
  179. google/genai/tests/shared/batches/test_create_get_cancel.py +56 -0
  180. google/genai/tests/shared/batches/test_list.py +40 -0
  181. google/genai/tests/shared/caches/__init__.py +14 -0
  182. google/genai/tests/shared/caches/test_create_get_delete.py +67 -0
  183. google/genai/tests/shared/caches/test_create_update_get.py +71 -0
  184. google/genai/tests/shared/caches/test_list.py +40 -0
  185. google/genai/tests/shared/chats/__init__.py +14 -0
  186. google/genai/tests/shared/chats/test_send_message.py +48 -0
  187. google/genai/tests/shared/chats/test_send_message_stream.py +50 -0
  188. google/genai/tests/shared/files/__init__.py +14 -0
  189. google/genai/tests/shared/files/test_list.py +41 -0
  190. google/genai/tests/shared/files/test_upload_get_delete.py +54 -0
  191. google/genai/tests/shared/models/__init__.py +14 -0
  192. google/genai/tests/shared/models/test_compute_tokens.py +41 -0
  193. google/genai/tests/shared/models/test_count_tokens.py +40 -0
  194. google/genai/tests/shared/models/test_edit_image.py +67 -0
  195. google/genai/tests/shared/models/test_embed.py +40 -0
  196. google/genai/tests/shared/models/test_generate_content.py +39 -0
  197. google/genai/tests/shared/models/test_generate_content_stream.py +54 -0
  198. google/genai/tests/shared/models/test_generate_images.py +40 -0
  199. google/genai/tests/shared/models/test_generate_videos.py +38 -0
  200. google/genai/tests/shared/models/test_list.py +37 -0
  201. google/genai/tests/shared/models/test_recontext_image.py +55 -0
  202. google/genai/tests/shared/models/test_segment_image.py +52 -0
  203. google/genai/tests/shared/models/test_upscale_image.py +52 -0
  204. google/genai/tests/shared/tunings/__init__.py +16 -0
  205. google/genai/tests/shared/tunings/test_create.py +46 -0
  206. google/genai/tests/shared/tunings/test_create_get_cancel.py +56 -0
  207. google/genai/tests/shared/tunings/test_list.py +39 -0
  208. google/genai/tests/tokens/__init__.py +16 -0
  209. google/genai/tests/tokens/test_create.py +154 -0
  210. google/genai/tests/transformers/__init__.py +17 -0
  211. google/genai/tests/transformers/test_blobs.py +84 -0
  212. google/genai/tests/transformers/test_bytes.py +15 -0
  213. google/genai/tests/transformers/test_duck_type.py +96 -0
  214. google/genai/tests/transformers/test_function_responses.py +72 -0
  215. google/genai/tests/transformers/test_schema.py +653 -0
  216. google/genai/tests/transformers/test_t_batch.py +286 -0
  217. google/genai/tests/transformers/test_t_content.py +160 -0
  218. google/genai/tests/transformers/test_t_contents.py +398 -0
  219. google/genai/tests/transformers/test_t_part.py +85 -0
  220. google/genai/tests/transformers/test_t_parts.py +87 -0
  221. google/genai/tests/transformers/test_t_tool.py +157 -0
  222. google/genai/tests/transformers/test_t_tools.py +195 -0
  223. google/genai/tests/tunings/__init__.py +16 -0
  224. google/genai/tests/tunings/test_cancel.py +39 -0
  225. google/genai/tests/tunings/test_end_to_end.py +106 -0
  226. google/genai/tests/tunings/test_get.py +67 -0
  227. google/genai/tests/tunings/test_list.py +75 -0
  228. google/genai/tests/tunings/test_tune.py +268 -0
  229. google/genai/tests/types/__init__.py +16 -0
  230. google/genai/tests/types/test_bytes_internal.py +271 -0
  231. google/genai/tests/types/test_bytes_type.py +152 -0
  232. google/genai/tests/types/test_future.py +101 -0
  233. google/genai/tests/types/test_optional_types.py +36 -0
  234. google/genai/tests/types/test_part_type.py +616 -0
  235. google/genai/tests/types/test_schema_from_json_schema.py +417 -0
  236. google/genai/tests/types/test_schema_json_schema.py +468 -0
  237. google/genai/tests/types/test_types.py +2903 -0
  238. google/genai/types.py +631 -488
  239. google/genai/version.py +1 -1
  240. {google_genai-1.56.0.dist-info → google_genai-1.58.0.dist-info}/METADATA +6 -11
  241. google_genai-1.58.0.dist-info/RECORD +358 -0
  242. google_genai-1.56.0.dist-info/RECORD +0 -162
  243. /google/genai/{_interactions/py.typed → tests/interactions/__init__.py} +0 -0
  244. {google_genai-1.56.0.dist-info → google_genai-1.58.0.dist-info}/WHEEL +0 -0
  245. {google_genai-1.56.0.dist-info → google_genai-1.58.0.dist-info}/licenses/LICENSE +0 -0
  246. {google_genai-1.56.0.dist-info → google_genai-1.58.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,272 @@
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
+ """Test files register method."""
18
+
19
+ import json
20
+ from unittest import mock
21
+
22
+ from google.auth import credentials
23
+ import httpx
24
+ import pytest
25
+
26
+ from ... import _api_client
27
+ from ... import Client
28
+ from ... import types
29
+ from .. import pytest_helper
30
+
31
+
32
+ class FakeCredentials(credentials.Credentials):
33
+
34
+ def __init__(self, token="fake_token", expired=False, quota_project_id=None):
35
+ super().__init__()
36
+ self.token = token
37
+ self._expired = expired
38
+ self._quota_project_id = quota_project_id
39
+ self.refresh_count = 0
40
+
41
+ @property
42
+ def expired(self):
43
+ return self._expired
44
+
45
+ @property
46
+ def quota_project_id(self):
47
+ return self._quota_project_id
48
+
49
+ def refresh(self, request):
50
+ self.refresh_count += 1
51
+ self.token = "refreshed_token"
52
+ self._expired = False
53
+
54
+
55
+ @mock.patch.object(_api_client.BaseApiClient, "_request_once", autospec=True)
56
+ def test_simple_token(mock_request):
57
+ client = Client(api_key="dummy_key")
58
+ captured_request = None
59
+
60
+ def side_effect(self, http_request, stream=False):
61
+ nonlocal captured_request
62
+ captured_request = http_request
63
+ return _api_client.HttpResponse(
64
+ headers={},
65
+ response_stream=[json.dumps({"files": [{"uri": "files/abc"}]})],
66
+ )
67
+
68
+ mock_request.side_effect = side_effect
69
+
70
+ with pytest_helper.exception_if_vertex(client, ValueError):
71
+ response = client.files.register_files(
72
+ auth=FakeCredentials(token="test_token"),
73
+ uris=["gs://test-bucket/test-file-1.txt"],
74
+ )
75
+
76
+ assert len(response.files) == 1
77
+ assert response.files[0].uri == "files/abc"
78
+ assert captured_request.headers["authorization"] == "Bearer test_token"
79
+
80
+
81
+ @mock.patch.object(_api_client.BaseApiClient, "_request_once", autospec=True)
82
+ def test_token_refresh(mock_request):
83
+ client = Client(api_key="dummy_key")
84
+ captured_request = None
85
+
86
+ def side_effect(self, http_request, stream=False):
87
+ nonlocal captured_request
88
+ captured_request = http_request
89
+ return _api_client.HttpResponse(
90
+ headers={},
91
+ response_stream=[json.dumps({"files": [{"uri": "files/abc"}]})],
92
+ )
93
+
94
+ mock_request.side_effect = side_effect
95
+
96
+ with pytest_helper.exception_if_vertex(client, ValueError):
97
+ creds = FakeCredentials(expired=True)
98
+ response = client.files.register_files(
99
+ auth=creds,
100
+ uris=["gs://test-bucket/test-file-1.txt"],
101
+ )
102
+ assert creds.refresh_count == 1
103
+ assert len(response.files) == 1
104
+ assert response.files[0].uri == "files/abc"
105
+ assert captured_request.headers["authorization"] == "Bearer refreshed_token"
106
+
107
+
108
+ @mock.patch.object(_api_client.BaseApiClient, "_request_once", autospec=True)
109
+ def test_quota_project(mock_request):
110
+ client = Client(api_key="dummy_key")
111
+ captured_request = None
112
+
113
+ def side_effect(self, http_request, stream=False):
114
+ nonlocal captured_request
115
+ captured_request = http_request
116
+ return _api_client.HttpResponse(
117
+ headers={},
118
+ response_stream=[json.dumps({"files": [{"uri": "files/abc"}]})],
119
+ )
120
+
121
+ mock_request.side_effect = side_effect
122
+
123
+ with pytest_helper.exception_if_vertex(client, ValueError):
124
+ creds = FakeCredentials(quota_project_id="test_project")
125
+ response = client.files.register_files(
126
+ auth=creds,
127
+ uris=["gs://test-bucket/test-file-1.txt"],
128
+ )
129
+ assert len(response.files) == 1
130
+ assert response.files[0].uri == "files/abc"
131
+ assert captured_request.headers["x-goog-user-project"] == "test_project"
132
+
133
+
134
+ @mock.patch.object(_api_client.BaseApiClient, "_request_once", autospec=True)
135
+ def test_multiple_uris(mock_request):
136
+ client = Client(api_key="dummy_key")
137
+
138
+ def side_effect(self, http_request, stream=False):
139
+ return _api_client.HttpResponse(
140
+ headers={},
141
+ response_stream=[
142
+ json.dumps({"files": [{"uri": "files/abc"}, {"uri": "files/def"}]})
143
+ ],
144
+ )
145
+
146
+ mock_request.side_effect = side_effect
147
+
148
+ with pytest_helper.exception_if_vertex(client, ValueError):
149
+ response = client.files.register_files(
150
+ auth=FakeCredentials(),
151
+ uris=[
152
+ "gs://test-bucket/test-file-1.txt",
153
+ "gs://test-bucket/test-file-2.txt",
154
+ ],
155
+ )
156
+ assert len(response.files) == 2
157
+ assert response.files[0].uri == "files/abc"
158
+ assert response.files[1].uri == "files/def"
159
+
160
+
161
+ @pytest.mark.asyncio
162
+ @mock.patch.object(
163
+ _api_client.BaseApiClient, "_async_request_once", autospec=True
164
+ )
165
+ async def test_async_single(mock_request):
166
+ client = Client(api_key="dummy_key")
167
+
168
+ async def side_effect(self, http_request, stream=False):
169
+ return _api_client.HttpResponse(
170
+ headers={},
171
+ response_stream=[json.dumps({"files": [{"uri": "files/abc"}]})],
172
+ )
173
+
174
+ mock_request.side_effect = side_effect
175
+
176
+ with pytest_helper.exception_if_vertex(client, ValueError):
177
+ response = await client.aio.files.register_files(
178
+ auth=FakeCredentials(),
179
+ uris=["gs://test-bucket/test-file-1.txt"],
180
+ )
181
+
182
+ assert len(response.files) == 1
183
+ assert response.files[0].uri == "files/abc"
184
+
185
+
186
+ @pytest.mark.asyncio
187
+ @mock.patch.object(
188
+ _api_client.BaseApiClient, "_async_request_once", autospec=True
189
+ )
190
+ async def test_async_token_refresh(mock_request):
191
+ client = Client(api_key="dummy_key")
192
+ captured_request = None
193
+
194
+ async def side_effect(self, http_request, stream=False):
195
+ nonlocal captured_request
196
+ captured_request = http_request
197
+ return _api_client.HttpResponse(
198
+ headers={},
199
+ response_stream=[json.dumps({"files": [{"uri": "files/abc"}]})],
200
+ )
201
+
202
+ mock_request.side_effect = side_effect
203
+
204
+ with pytest_helper.exception_if_vertex(client, ValueError):
205
+ creds = FakeCredentials(expired=True)
206
+ response = await client.aio.files.register_files(
207
+ auth=creds,
208
+ uris=["gs://test-bucket/test-file-1.txt"],
209
+ )
210
+ assert creds.refresh_count == 1
211
+ assert len(response.files) == 1
212
+ assert response.files[0].uri == "files/abc"
213
+ assert captured_request.headers["authorization"] == "Bearer refreshed_token"
214
+
215
+
216
+ @pytest.mark.asyncio
217
+ @mock.patch.object(
218
+ _api_client.BaseApiClient, "_async_request_once", autospec=True
219
+ )
220
+ async def test_async_quota_project(mock_request):
221
+ client = Client(api_key="dummy_key")
222
+ captured_request = None
223
+
224
+ async def side_effect(self, http_request, stream=False):
225
+ nonlocal captured_request
226
+ captured_request = http_request
227
+ return _api_client.HttpResponse(
228
+ headers={},
229
+ response_stream=[json.dumps({"files": [{"uri": "files/abc"}]})],
230
+ )
231
+
232
+ mock_request.side_effect = side_effect
233
+
234
+ with pytest_helper.exception_if_vertex(client, ValueError):
235
+ creds = FakeCredentials(quota_project_id="test_project")
236
+ response = await client.aio.files.register_files(
237
+ auth=creds,
238
+ uris=["gs://test-bucket/test-file-1.txt"],
239
+ )
240
+ assert len(response.files) == 1
241
+ assert response.files[0].uri == "files/abc"
242
+ assert captured_request.headers["x-goog-user-project"] == "test_project"
243
+
244
+
245
+ @pytest.mark.asyncio
246
+ @mock.patch.object(
247
+ _api_client.BaseApiClient, "_async_request_once", autospec=True
248
+ )
249
+ async def test_async_multiple_uris(mock_request):
250
+ client = Client(api_key="dummy_key")
251
+
252
+ async def side_effect(self, http_request, stream=False):
253
+ return _api_client.HttpResponse(
254
+ headers={},
255
+ response_stream=[
256
+ json.dumps({"files": [{"uri": "files/abc"}, {"uri": "files/def"}]})
257
+ ],
258
+ )
259
+
260
+ mock_request.side_effect = side_effect
261
+
262
+ with pytest_helper.exception_if_vertex(client, ValueError):
263
+ response = await client.aio.files.register_files(
264
+ auth=FakeCredentials(),
265
+ uris=[
266
+ "gs://test-bucket/test-file-1.txt",
267
+ "gs://test-bucket/test-file-2.txt",
268
+ ],
269
+ )
270
+ assert len(response.files) == 2
271
+ assert response.files[0].uri == "files/abc"
272
+ assert response.files[1].uri == "files/def"
@@ -0,0 +1,70 @@
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
+ """Test files get method."""
18
+
19
+ import pytest
20
+ from ... import types
21
+ from ... import Client
22
+ from ... import _api_client
23
+ from .. import pytest_helper
24
+ import google.auth
25
+
26
+
27
+ # $ gcloud config set project vertex-sdk-dev
28
+ # $ gcloud auth application-default login --no-launch-browser --scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/devstorage.read_only"
29
+ def get_headers():
30
+ try:
31
+ credentials, _ = google.auth.default()
32
+ token = _api_client.get_token_from_credentials(None, credentials)
33
+ headers = {
34
+ "Authorization": f"Bearer {token}",}
35
+ if credentials.quota_project_id:
36
+ headers["x-goog-user-project"] = credentials.quota_project_id
37
+ except google.auth.exceptions.DefaultCredentialsError:
38
+ # So this can run in replay mode without credentials.
39
+ headers = {}
40
+
41
+
42
+ test_table: list[pytest_helper.TestTableItem] = [
43
+ pytest_helper.TestTableItem(
44
+ name='test_register',
45
+ parameters=types._RegisterFilesParameters(uris=['gs://unified-genai-dev/image.jpg']),
46
+ exception_if_vertex='only supported in the Gemini Developer client',
47
+ skip_in_api_mode=(
48
+ 'The files have a TTL, they cannot be reliably retrieved for a long'
49
+ ' time.'
50
+ ),
51
+ ),
52
+ ]
53
+
54
+ pytestmark = pytest_helper.setup(
55
+ file=__file__,
56
+ globals_for_file=globals(),
57
+ test_method='files._register_files',
58
+ test_table=test_table,
59
+ http_options={
60
+ 'headers': get_headers(),
61
+ },
62
+ )
63
+
64
+
65
+ @pytest.mark.asyncio
66
+ async def test_async(client):
67
+ with pytest_helper.exception_if_vertex(client, ValueError):
68
+ files = await client.aio.files._register_files(uris=['gs://unified-genai-dev/image.jpg'])
69
+ assert files.files
70
+ assert files.files[0].mime_type == 'image/jpeg'
@@ -0,0 +1,255 @@
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
+ """Test files upload method."""
18
+
19
+
20
+ import io
21
+ import pathlib
22
+ import pytest
23
+ from ... import types
24
+ from ... import errors
25
+ from .. import pytest_helper
26
+
27
+ # Upload method is not pydantic.
28
+ test_table: list[pytest_helper.TestTableItem] = []
29
+ pytestmark = pytest_helper.setup(
30
+ file=__file__,
31
+ globals_for_file=globals(),
32
+ test_method='files.upload',
33
+ test_table=test_table,
34
+ )
35
+
36
+
37
+ def test_image_png_upload(client):
38
+ with pytest_helper.exception_if_vertex(client, ValueError):
39
+ file = client.files.upload(file='tests/data/google.png')
40
+ assert file.name.startswith('files/')
41
+
42
+ def test_image_png_upload_with_path(client):
43
+ with pytest_helper.exception_if_vertex(client, ValueError):
44
+ p = pathlib.Path('tests/data/google.png')
45
+ file = client.files.upload(
46
+ file=p,
47
+ config=types.UploadFileConfig(display_name='test_image_png_path'),
48
+ )
49
+ assert file.name.startswith('files/')
50
+
51
+ def test_image_png_upload_with_bytesio(client):
52
+ with pytest_helper.exception_if_vertex(client, ValueError):
53
+ with open('tests/data/google.png', 'rb') as f:
54
+ with io.BytesIO(f.read()) as buffer:
55
+ file = client.files.upload(
56
+ file=buffer,
57
+ config=types.UploadFileConfig(mime_type='image/png'),
58
+ )
59
+
60
+ assert file.name.startswith('files/')
61
+
62
+ def test_image_png_upload_with_fd(client):
63
+ with pytest_helper.exception_if_vertex(client, ValueError):
64
+ with open('tests/data/google.png', 'rb') as f:
65
+ file = client.files.upload(
66
+ file=f,
67
+ config=types.UploadFileConfig(mime_type='image/png'),
68
+ )
69
+
70
+ assert file.name.startswith('files/')
71
+
72
+ def test_image_png_upload_with_config(client):
73
+ with pytest_helper.exception_if_vertex(client, ValueError):
74
+ file = client.files.upload(
75
+ file='tests/data/google.png',
76
+ config=types.UploadFileConfig(display_name='test_image_png'),
77
+ )
78
+ assert file.name.startswith('files/')
79
+
80
+
81
+ def test_image_png_upload_with_config_dict(client):
82
+ with pytest_helper.exception_if_vertex(client, ValueError):
83
+ file = client.files.upload(
84
+ file='tests/data/google.png', config={'display_name': 'test_image_png'}
85
+ )
86
+ assert file.name.startswith('files/')
87
+
88
+
89
+ def test_image_jpg_upload(client):
90
+ with pytest_helper.exception_if_vertex(client, ValueError):
91
+ file = client.files.upload(file='tests/data/google.jpg')
92
+ assert file.name.startswith('files/')
93
+
94
+
95
+ def test_image_jpg_upload_with_config(client):
96
+ with pytest_helper.exception_if_vertex(client, ValueError):
97
+ file = client.files.upload(
98
+ file='tests/data/google.jpg',
99
+ config=types.UploadFileConfig(display_name='test_image_jpg'),
100
+ )
101
+ assert file.name.startswith('files/')
102
+
103
+
104
+ def test_image_jpg_upload_with_config_dict(client):
105
+ with pytest_helper.exception_if_vertex(client, ValueError):
106
+ file = client.files.upload(
107
+ file='tests/data/google.jpg', config={'display_name': 'test_image_jpg'}
108
+ )
109
+ assert file.name.startswith('files/')
110
+
111
+
112
+ def test_application_pdf_file_upload(client):
113
+ with pytest_helper.exception_if_vertex(client, ValueError):
114
+ file = client.files.upload(file='tests/data/story.pdf')
115
+ assert file.name.startswith('files/')
116
+
117
+
118
+ def test_application_pdf_upload_with_config(client):
119
+ with pytest_helper.exception_if_vertex(client, ValueError):
120
+ file = client.files.upload(
121
+ file='tests/data/story.pdf',
122
+ config=types.UploadFileConfig(display_name='test_application_pdf'),
123
+ )
124
+ assert file.name.startswith('files/')
125
+
126
+
127
+ def test_application_pdf_upload_with_config_dict(client):
128
+ with pytest_helper.exception_if_vertex(client, ValueError):
129
+ file = client.files.upload(
130
+ file='tests/data/story.pdf',
131
+ config={'display_name': 'test_application_pdf'},
132
+ )
133
+ assert file.name.startswith('files/')
134
+
135
+
136
+ def test_video_mp4_file_upload(client):
137
+ with pytest_helper.exception_if_vertex(client, ValueError):
138
+ file = client.files.upload(file='tests/data/animal.mp4')
139
+ assert file.name.startswith('files/')
140
+
141
+
142
+ def test_video_mp4_upload_with_config(client):
143
+ with pytest_helper.exception_if_vertex(client, ValueError):
144
+ file = client.files.upload(
145
+ file='tests/data/animal.mp4',
146
+ config=types.UploadFileConfig(display_name='test_video_mp4'),
147
+ )
148
+ assert file.name.startswith('files/')
149
+
150
+
151
+ def test_video_mp4_upload_with_config_dict(client):
152
+ with pytest_helper.exception_if_vertex(client, ValueError):
153
+ file = client.files.upload(
154
+ file='tests/data/animal.mp4', config={'display_name': 'test_video_mp4'}
155
+ )
156
+ assert file.name.startswith('files/')
157
+
158
+
159
+ def test_audio_m4a_file_upload(client):
160
+ with pytest_helper.exception_if_vertex(client, ValueError):
161
+ file = client.files.upload(
162
+ file='tests/data/pixel.m4a',
163
+ config=types.UploadFileConfig(mime_type='audio/mp4'),
164
+ )
165
+ assert file.name.startswith('files/')
166
+
167
+
168
+ def test_audio_m4a_upload_with_config(client):
169
+ with pytest_helper.exception_if_vertex(client, ValueError):
170
+ file = client.files.upload(
171
+ file='tests/data/pixel.m4a',
172
+ config=types.UploadFileConfig(
173
+ display_name='test_audio_m4a', mime_type='audio/mp4'
174
+ ),
175
+ )
176
+ assert file.name.startswith('files/')
177
+
178
+
179
+ def test_audio_m4a_upload_with_config_dict(client):
180
+ with pytest_helper.exception_if_vertex(client, ValueError):
181
+ file = client.files.upload(
182
+ file='tests/data/pixel.m4a',
183
+ config={'display_name': 'test_audio_m4a', 'mime_type': 'audio/mp4'},
184
+ )
185
+ assert file.name.startswith('files/')
186
+
187
+
188
+ def test_bad_mime_type(client):
189
+ with pytest_helper.exception_if_vertex(client, ValueError):
190
+ with pytest.raises(errors.APIError, match="Unsupported MIME"):
191
+ file = client.files.upload(
192
+ file=io.BytesIO(b'test'),
193
+ config={'mime_type': 'bad/mime_type'},
194
+ )
195
+
196
+
197
+ @pytest.mark.asyncio
198
+ async def test_image_upload_async(client):
199
+ with pytest_helper.exception_if_vertex(client, ValueError):
200
+ file = await client.aio.files.upload(file='tests/data/google.png')
201
+ assert file.name.startswith('files/')
202
+
203
+
204
+ @pytest.mark.asyncio
205
+ async def test_image_upload_with_config_async(client):
206
+ with pytest_helper.exception_if_vertex(client, ValueError):
207
+ file = await client.aio.files.upload(
208
+ file='tests/data/google.png',
209
+ config=types.UploadFileConfig(display_name='test_image'),
210
+ )
211
+ assert file.name.startswith('files/')
212
+
213
+
214
+ @pytest.mark.asyncio
215
+ async def test_image_upload_with_config_dict_async(client):
216
+ with pytest_helper.exception_if_vertex(client, ValueError):
217
+ file = await client.aio.files.upload(
218
+ file='tests/data/google.png',
219
+ config={
220
+ 'display_name': 'test_image',
221
+ 'http_options': {'timeout': '8000'},
222
+ },
223
+ )
224
+ assert file.name.startswith('files/')
225
+
226
+
227
+ @pytest.mark.asyncio
228
+ async def test_image_upload_with_bytesio_async(client):
229
+ with pytest_helper.exception_if_vertex(client, ValueError):
230
+ with open('tests/data/google.png', 'rb') as f:
231
+ buffer = io.BytesIO(f.read())
232
+ file = await client.aio.files.upload(
233
+ file=buffer,
234
+ config=types.UploadFileConfig(
235
+ mime_type='image/png'),
236
+ )
237
+ assert file.name.startswith('files/')
238
+
239
+
240
+ @pytest.mark.asyncio
241
+ async def test_unknown_path_upload_async(client):
242
+ with pytest_helper.exception_if_vertex(client, ValueError):
243
+ try:
244
+ await client.aio.files.upload(file='unknown_path')
245
+ except FileNotFoundError as e:
246
+ assert 'is not a valid file path' in str(e)
247
+
248
+ @pytest.mark.asyncio
249
+ async def test_bad_mime_type_async(client):
250
+ with pytest_helper.exception_if_vertex(client, ValueError):
251
+ with pytest.raises(errors.APIError, match="Unsupported MIME"):
252
+ file = await client.aio.files.upload(
253
+ file=io.BytesIO(b'test'),
254
+ config={'mime_type': 'bad/mime_type'},
255
+ )
@@ -0,0 +1,28 @@
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 pytest
18
+
19
+ IS_NOT_GITHUB_ACTIONS = os.getenv('GITHUB_ACTIONS') != 'true'
20
+
21
+
22
+ @pytest.mark.skipif(IS_NOT_GITHUB_ACTIONS,
23
+ reason='This test is only run on GitHub Actions.')
24
+ def test_library_can_be_imported_without_optional_dependencies():
25
+ """Tests that the library can be imported without optional dependencies.
26
+ """
27
+ from google import genai
28
+ from google.genai import types