google-genai 1.7.0__py3-none-any.whl → 1.53.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 (42) hide show
  1. google/genai/__init__.py +4 -2
  2. google/genai/_adapters.py +55 -0
  3. google/genai/_api_client.py +1301 -299
  4. google/genai/_api_module.py +1 -1
  5. google/genai/_automatic_function_calling_util.py +54 -33
  6. google/genai/_base_transformers.py +26 -0
  7. google/genai/_base_url.py +50 -0
  8. google/genai/_common.py +560 -59
  9. google/genai/_extra_utils.py +371 -38
  10. google/genai/_live_converters.py +1467 -0
  11. google/genai/_local_tokenizer_loader.py +214 -0
  12. google/genai/_mcp_utils.py +117 -0
  13. google/genai/_operations_converters.py +394 -0
  14. google/genai/_replay_api_client.py +204 -92
  15. google/genai/_test_api_client.py +1 -1
  16. google/genai/_tokens_converters.py +520 -0
  17. google/genai/_transformers.py +633 -233
  18. google/genai/batches.py +1733 -538
  19. google/genai/caches.py +678 -1012
  20. google/genai/chats.py +48 -38
  21. google/genai/client.py +142 -15
  22. google/genai/documents.py +532 -0
  23. google/genai/errors.py +141 -35
  24. google/genai/file_search_stores.py +1296 -0
  25. google/genai/files.py +312 -744
  26. google/genai/live.py +617 -367
  27. google/genai/live_music.py +197 -0
  28. google/genai/local_tokenizer.py +395 -0
  29. google/genai/models.py +3598 -3116
  30. google/genai/operations.py +201 -362
  31. google/genai/pagers.py +23 -7
  32. google/genai/py.typed +1 -0
  33. google/genai/tokens.py +362 -0
  34. google/genai/tunings.py +1274 -496
  35. google/genai/types.py +14535 -5454
  36. google/genai/version.py +2 -2
  37. {google_genai-1.7.0.dist-info → google_genai-1.53.0.dist-info}/METADATA +736 -234
  38. google_genai-1.53.0.dist-info/RECORD +41 -0
  39. {google_genai-1.7.0.dist-info → google_genai-1.53.0.dist-info}/WHEEL +1 -1
  40. google_genai-1.7.0.dist-info/RECORD +0 -27
  41. {google_genai-1.7.0.dist-info → google_genai-1.53.0.dist-info/licenses}/LICENSE +0 -0
  42. {google_genai-1.7.0.dist-info → google_genai-1.53.0.dist-info}/top_level.txt +0 -0
google/genai/errors.py CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright 2024 Google LLC
1
+ # Copyright 2025 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -18,16 +18,18 @@
18
18
  from typing import Any, Optional, TYPE_CHECKING, Union
19
19
  import httpx
20
20
  import json
21
+ from . import _common
21
22
 
22
23
 
23
24
  if TYPE_CHECKING:
24
25
  from .replay_api_client import ReplayResponse
26
+ import aiohttp
25
27
 
26
28
 
27
29
  class APIError(Exception):
28
30
  """General errors raised by the GenAI API."""
29
31
  code: int
30
- response: Union['ReplayResponse', httpx.Response]
32
+ response: Union['ReplayResponse', httpx.Response, 'aiohttp.ClientResponse']
31
33
 
32
34
  status: Optional[str] = None
33
35
  message: Optional[str] = None
@@ -35,28 +37,15 @@ class APIError(Exception):
35
37
  def __init__(
36
38
  self,
37
39
  code: int,
38
- response: Union['ReplayResponse', httpx.Response],
40
+ response_json: Any,
41
+ response: Optional[
42
+ Union['ReplayResponse', httpx.Response, 'aiohttp.ClientResponse']
43
+ ] = None,
39
44
  ):
40
- self.response = response
41
- message = None
42
- if isinstance(response, httpx.Response):
43
- try:
44
- response_json = response.json()
45
- except (json.decoder.JSONDecodeError):
46
- message = response.text
47
- response_json = {
48
- 'message': message,
49
- 'status': response.reason_phrase,
50
- }
51
- except httpx.ResponseNotRead:
52
- message = 'Response not read'
53
- response_json = {
54
- 'message': message,
55
- 'status': response.reason_phrase,
56
- }
57
- else:
58
- response_json = response.body_segments[0].get('error', {})
45
+ if isinstance(response_json, list) and len(response_json) == 1:
46
+ response_json = response_json[0]
59
47
 
48
+ self.response = response
60
49
  self.details = response_json
61
50
  self.message = self._get_message(response_json)
62
51
  self.status = self._get_status(response_json)
@@ -64,22 +53,22 @@ class APIError(Exception):
64
53
 
65
54
  super().__init__(f'{self.code} {self.status}. {self.details}')
66
55
 
67
- def _get_status(self, response_json):
56
+ def _get_status(self, response_json: Any) -> Any:
68
57
  return response_json.get(
69
58
  'status', response_json.get('error', {}).get('status', None)
70
59
  )
71
60
 
72
- def _get_message(self, response_json):
61
+ def _get_message(self, response_json: Any) -> Any:
73
62
  return response_json.get(
74
63
  'message', response_json.get('error', {}).get('message', None)
75
64
  )
76
65
 
77
- def _get_code(self, response_json):
66
+ def _get_code(self, response_json: Any) -> Any:
78
67
  return response_json.get(
79
68
  'code', response_json.get('error', {}).get('code', None)
80
69
  )
81
70
 
82
- def _to_replay_record(self):
71
+ def _to_replay_record(self) -> _common.StringDict:
83
72
  """Returns a dictionary representation of the error for replay recording.
84
73
 
85
74
  details is not included since it may expose internal information in the
@@ -96,18 +85,133 @@ class APIError(Exception):
96
85
  @classmethod
97
86
  def raise_for_response(
98
87
  cls, response: Union['ReplayResponse', httpx.Response]
99
- ):
88
+ ) -> None:
100
89
  """Raises an error with detailed error message if the response has an error status."""
101
90
  if response.status_code == 200:
102
91
  return
103
92
 
104
- status_code = response.status_code
93
+ if isinstance(response, httpx.Response):
94
+ try:
95
+ response.read()
96
+ response_json = response.json()
97
+ except json.decoder.JSONDecodeError:
98
+ message = response.text
99
+ response_json = {
100
+ 'message': message,
101
+ 'status': response.reason_phrase,
102
+ }
103
+ else:
104
+ response_json = response.body_segments[0].get('error', {})
105
+
106
+ cls.raise_error(response.status_code, response_json, response)
107
+
108
+ @classmethod
109
+ def raise_error(
110
+ cls,
111
+ status_code: int,
112
+ response_json: Any,
113
+ response: Optional[
114
+ Union['ReplayResponse', httpx.Response, 'aiohttp.ClientResponse']
115
+ ],
116
+ ) -> None:
117
+ """Raises an appropriate APIError subclass based on the status code.
118
+
119
+ Args:
120
+ status_code: The HTTP status code of the response.
121
+ response_json: The JSON body of the response, or a dict containing error
122
+ details.
123
+ response: The original response object.
124
+
125
+ Raises:
126
+ ClientError: If the status code is in the 4xx range.
127
+ ServerError: If the status code is in the 5xx range.
128
+ APIError: For other error status codes.
129
+ """
130
+ if 400 <= status_code < 500:
131
+ raise ClientError(status_code, response_json, response)
132
+ elif 500 <= status_code < 600:
133
+ raise ServerError(status_code, response_json, response)
134
+ else:
135
+ raise cls(status_code, response_json, response)
136
+
137
+ @classmethod
138
+ async def raise_for_async_response(
139
+ cls,
140
+ response: Union[
141
+ 'ReplayResponse', httpx.Response, 'aiohttp.ClientResponse'
142
+ ],
143
+ ) -> None:
144
+ """Raises an error with detailed error message if the response has an error status."""
145
+ status_code = 0
146
+ response_json = None
147
+ if isinstance(response, httpx.Response):
148
+ if response.status_code == 200:
149
+ return
150
+ try:
151
+ await response.aread()
152
+ response_json = response.json()
153
+ except json.decoder.JSONDecodeError:
154
+ message = response.text
155
+ response_json = {
156
+ 'message': message,
157
+ 'status': response.reason_phrase,
158
+ }
159
+ status_code = response.status_code
160
+ elif hasattr(response, 'body_segments') and hasattr(
161
+ response, 'status_code'
162
+ ):
163
+ if response.status_code == 200:
164
+ return
165
+ response_json = response.body_segments[0].get('error', {})
166
+ status_code = response.status_code
167
+ else:
168
+ try:
169
+ import aiohttp # pylint: disable=g-import-not-at-top
170
+
171
+ if isinstance(response, aiohttp.ClientResponse):
172
+ if response.status == 200:
173
+ return
174
+ try:
175
+ response_json = await response.json()
176
+ except aiohttp.client_exceptions.ContentTypeError:
177
+ message = await response.text()
178
+ response_json = {
179
+ 'message': message,
180
+ 'status': response.reason,
181
+ }
182
+ status_code = response.status
183
+ else:
184
+ raise ValueError(f'Unsupported response type: {type(response)}')
185
+ except ImportError:
186
+ raise ValueError(f'Unsupported response type: {type(response)}')
187
+
188
+ await cls.raise_error_async(status_code, response_json, response)
189
+
190
+ @classmethod
191
+ async def raise_error_async(
192
+ cls, status_code: int, response_json: Any, response: Optional[
193
+ Union['ReplayResponse', httpx.Response, 'aiohttp.ClientResponse']
194
+ ]
195
+ ) -> None:
196
+ """Raises an appropriate APIError subclass based on the status code.
197
+
198
+ Args:
199
+ status_code: The HTTP status code of the response.
200
+ response_json: The JSON body of the response, or a dict containing error
201
+ details.
202
+ response: The original response object.
203
+
204
+ Raises:
205
+ ClientError: If the status code is in the 4xx range.
206
+ ServerError: If the status code is in the 5xx range.
207
+ APIError: For other error status codes.
208
+ """
105
209
  if 400 <= status_code < 500:
106
- raise ClientError(status_code, response)
210
+ raise ClientError(status_code, response_json, response)
107
211
  elif 500 <= status_code < 600:
108
- raise ServerError(status_code, response)
212
+ raise ServerError(status_code, response_json, response)
109
213
  else:
110
- raise cls(status_code, response)
214
+ raise cls(status_code, response_json, response)
111
215
 
112
216
 
113
217
  class ClientError(APIError):
@@ -122,19 +226,21 @@ class ServerError(APIError):
122
226
 
123
227
  class UnknownFunctionCallArgumentError(ValueError):
124
228
  """Raised when the function call argument cannot be converted to the parameter annotation."""
125
-
126
229
  pass
127
230
 
128
231
 
129
232
  class UnsupportedFunctionError(ValueError):
130
233
  """Raised when the function is not supported."""
234
+ pass
131
235
 
132
236
 
133
237
  class FunctionInvocationError(ValueError):
134
238
  """Raised when the function cannot be invoked with the given arguments."""
135
-
136
239
  pass
137
240
 
138
241
 
139
- class ExperimentalWarning(Warning):
140
- """Warning for experimental features."""
242
+ class UnknownApiResponseError(ValueError):
243
+ """Raised when the response from the API cannot be parsed as JSON."""
244
+ pass
245
+
246
+ ExperimentalWarning = _common.ExperimentalWarning