google-genai 1.5.0__py3-none-any.whl → 1.7.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.
@@ -26,9 +26,7 @@ import sys
26
26
  import time
27
27
  import types as builtin_types
28
28
  import typing
29
- from typing import Any, GenericAlias, Optional, Union
30
-
31
- import types as builtin_types
29
+ from typing import Any, GenericAlias, Optional, Union # type: ignore[attr-defined]
32
30
 
33
31
  if typing.TYPE_CHECKING:
34
32
  import PIL.Image
@@ -43,10 +41,11 @@ logger = logging.getLogger('google_genai._transformers')
43
41
  if sys.version_info >= (3, 10):
44
42
  VersionedUnionType = builtin_types.UnionType
45
43
  _UNION_TYPES = (typing.Union, builtin_types.UnionType)
44
+ from typing import TypeGuard
46
45
  else:
47
46
  VersionedUnionType = typing._UnionGenericAlias
48
47
  _UNION_TYPES = (typing.Union,)
49
-
48
+ from typing_extensions import TypeGuard
50
49
 
51
50
  def _resource_name(
52
51
  client: _api_client.BaseApiClient,
@@ -165,7 +164,9 @@ def t_model(client: _api_client.BaseApiClient, model: str):
165
164
  return f'models/{model}'
166
165
 
167
166
 
168
- def t_models_url(api_client: _api_client.BaseApiClient, base_models: bool) -> str:
167
+ def t_models_url(
168
+ api_client: _api_client.BaseApiClient, base_models: bool
169
+ ) -> str:
169
170
  if api_client.vertexai:
170
171
  if base_models:
171
172
  return 'publishers/google/models'
@@ -179,7 +180,8 @@ def t_models_url(api_client: _api_client.BaseApiClient, base_models: bool) -> st
179
180
 
180
181
 
181
182
  def t_extract_models(
182
- api_client: _api_client.BaseApiClient, response: dict[str, list[types.ModelDict]]
183
+ api_client: _api_client.BaseApiClient,
184
+ response: dict[str, list[types.ModelDict]],
183
185
  ) -> Optional[list[types.ModelDict]]:
184
186
  if not response:
185
187
  return []
@@ -240,9 +242,7 @@ def pil_to_blob(img) -> types.Blob:
240
242
  return types.Blob(mime_type=mime_type, data=data)
241
243
 
242
244
 
243
- def t_part(
244
- part: Optional[types.PartUnionDict]
245
- ) -> types.Part:
245
+ def t_part(part: Optional[types.PartUnionDict]) -> types.Part:
246
246
  try:
247
247
  import PIL.Image
248
248
 
@@ -268,7 +268,7 @@ def t_part(
268
268
 
269
269
 
270
270
  def t_parts(
271
- parts: Optional[Union[list[types.PartUnionDict], types.PartUnionDict]],
271
+ parts: Optional[Union[list[types.PartUnionDict], types.PartUnionDict, list[types.Part]]],
272
272
  ) -> list[types.Part]:
273
273
  #
274
274
  if parts is None or (isinstance(parts, list) and not parts):
@@ -332,22 +332,35 @@ def t_content(
332
332
  def t_contents_for_embed(
333
333
  client: _api_client.BaseApiClient,
334
334
  contents: Union[list[types.Content], list[types.ContentDict], ContentType],
335
- ):
336
- if client.vertexai and isinstance(contents, list):
337
- # TODO: Assert that only text is supported.
338
- return [t_content(client, content).parts[0].text for content in contents]
339
- elif client.vertexai:
340
- return [t_content(client, contents).parts[0].text]
341
- elif isinstance(contents, list):
342
- return [t_content(client, content) for content in contents]
335
+ ) -> Union[list[str], list[types.Content]]:
336
+ if isinstance(contents, list):
337
+ transformed_contents = [t_content(client, content) for content in contents]
343
338
  else:
344
- return [t_content(client, contents)]
339
+ transformed_contents = [t_content(client, contents)]
340
+
341
+ if client.vertexai:
342
+ text_parts = []
343
+ for content in transformed_contents:
344
+ if content is not None:
345
+ if isinstance(content, dict):
346
+ content = types.Content.model_validate(content)
347
+ if content.parts is not None:
348
+ for part in content.parts:
349
+ if part.text:
350
+ text_parts.append(part.text)
351
+ else:
352
+ logger.warning(
353
+ f'Non-text part found, only returning text parts.'
354
+ )
355
+ return text_parts
356
+ else:
357
+ return transformed_contents
345
358
 
346
359
 
347
360
  def t_contents(
348
361
  client: _api_client.BaseApiClient,
349
362
  contents: Optional[
350
- Union[types.ContentListUnion, types.ContentListUnionDict]
363
+ Union[types.ContentListUnion, types.ContentListUnionDict, types.Content]
351
364
  ],
352
365
  ) -> list[types.Content]:
353
366
  if contents is None or (isinstance(contents, list) and not contents):
@@ -365,7 +378,7 @@ def t_contents(
365
378
  result: list[types.Content] = []
366
379
  accumulated_parts: list[types.Part] = []
367
380
 
368
- def _is_part(part: types.PartUnionDict) -> bool:
381
+ def _is_part(part: Union[types.PartUnionDict, Any]) -> TypeGuard[types.PartUnionDict]:
369
382
  if (
370
383
  isinstance(part, str)
371
384
  or isinstance(part, types.File)
@@ -429,11 +442,11 @@ def t_contents(
429
442
  ):
430
443
  _append_accumulated_parts_as_content(result, accumulated_parts)
431
444
  if isinstance(content, list):
432
- result.append(types.UserContent(parts=content))
445
+ result.append(types.UserContent(parts=content)) # type: ignore[arg-type]
433
446
  else:
434
447
  result.append(content)
435
- elif (_is_part(content)): # type: ignore
436
- _handle_current_part(result, accumulated_parts, content) # type: ignore
448
+ elif (_is_part(content)):
449
+ _handle_current_part(result, accumulated_parts, content)
437
450
  elif isinstance(content, dict):
438
451
  # PactDict is already handled in _is_part
439
452
  result.append(types.Content.model_validate(content))
@@ -499,7 +512,7 @@ def handle_null_fields(schema: dict[str, Any]):
499
512
  schema['anyOf'].remove({'type': 'null'})
500
513
  if len(schema['anyOf']) == 1:
501
514
  # If there is only one type left after removing null, remove the anyOf field.
502
- for key,val in schema['anyOf'][0].items():
515
+ for key, val in schema['anyOf'][0].items():
503
516
  schema[key] = val
504
517
  del schema['anyOf']
505
518
 
@@ -574,7 +587,8 @@ def process_schema(
574
587
 
575
588
  if schema.get('default') is not None:
576
589
  raise ValueError(
577
- 'Default value is not supported in the response schema for the Gemini API.'
590
+ 'Default value is not supported in the response schema for the Gemini'
591
+ ' API.'
578
592
  )
579
593
 
580
594
  if schema.get('title') == 'PlaceholderLiteralEnum':
@@ -604,10 +618,6 @@ def process_schema(
604
618
 
605
619
  any_of = schema.get('anyOf', None)
606
620
  if any_of is not None:
607
- if client and not client.vertexai:
608
- raise ValueError(
609
- 'AnyOf is not supported in the response schema for the Gemini API.'
610
- )
611
621
  for sub_schema in any_of:
612
622
  # $ref is present in any_of if the schema is a union of Pydantic classes
613
623
  ref_key = sub_schema.get('$ref', None)
@@ -670,7 +680,7 @@ def process_schema(
670
680
 
671
681
 
672
682
  def _process_enum(
673
- enum: EnumMeta, client: Optional[_api_client.BaseApiClient] = None # type: ignore
683
+ enum: EnumMeta, client: _api_client.BaseApiClient
674
684
  ) -> types.Schema:
675
685
  for member in enum: # type: ignore
676
686
  if not isinstance(member.value, str):
@@ -680,7 +690,7 @@ def _process_enum(
680
690
  )
681
691
 
682
692
  class Placeholder(pydantic.BaseModel):
683
- placeholder: enum
693
+ placeholder: enum # type: ignore[valid-type]
684
694
 
685
695
  enum_schema = Placeholder.model_json_schema()
686
696
  process_schema(enum_schema, client)
@@ -688,12 +698,19 @@ def _process_enum(
688
698
  return types.Schema.model_validate(enum_schema)
689
699
 
690
700
 
701
+ def _is_type_dict_str_any(origin: Union[types.SchemaUnionDict, Any]) -> TypeGuard[dict[str, Any]]:
702
+ """Verifies the schema is of type dict[str, Any] for mypy type checking."""
703
+ return isinstance(origin, dict) and all(
704
+ isinstance(key, str) for key in origin
705
+ )
706
+
707
+
691
708
  def t_schema(
692
709
  client: _api_client.BaseApiClient, origin: Union[types.SchemaUnionDict, Any]
693
710
  ) -> Optional[types.Schema]:
694
711
  if not origin:
695
712
  return None
696
- if isinstance(origin, dict):
713
+ if isinstance(origin, dict) and _is_type_dict_str_any(origin):
697
714
  process_schema(origin, client, order_properties=False)
698
715
  return types.Schema.model_validate(origin)
699
716
  if isinstance(origin, EnumMeta):
@@ -724,7 +741,7 @@ def t_schema(
724
741
  ):
725
742
 
726
743
  class Placeholder(pydantic.BaseModel):
727
- placeholder: origin
744
+ placeholder: origin # type: ignore[valid-type]
728
745
 
729
746
  schema = Placeholder.model_json_schema()
730
747
  process_schema(schema, client)
@@ -735,7 +752,8 @@ def t_schema(
735
752
 
736
753
 
737
754
  def t_speech_config(
738
- _: _api_client.BaseApiClient, origin: Union[types.SpeechConfigUnionDict, Any]
755
+ _: _api_client.BaseApiClient,
756
+ origin: Union[types.SpeechConfigUnionDict, Any],
739
757
  ) -> Optional[types.SpeechConfig]:
740
758
  if not origin:
741
759
  return None
@@ -794,7 +812,10 @@ def t_tools(
794
812
  transformed_tool = t_tool(client, tool)
795
813
  # All functions should be merged into one tool.
796
814
  if transformed_tool is not None:
797
- if transformed_tool.function_declarations:
815
+ if (
816
+ transformed_tool.function_declarations
817
+ and function_tool.function_declarations is not None
818
+ ):
798
819
  function_tool.function_declarations += (
799
820
  transformed_tool.function_declarations
800
821
  )
@@ -896,7 +917,10 @@ def t_file_name(
896
917
  elif isinstance(name, types.Video):
897
918
  name = name.uri
898
919
  elif isinstance(name, types.GeneratedVideo):
899
- name = name.video.uri
920
+ if name.video is not None:
921
+ name = name.video.uri
922
+ else:
923
+ name = None
900
924
 
901
925
  if name is None:
902
926
  raise ValueError('File name is required.')
google/genai/batches.py CHANGED
@@ -998,6 +998,8 @@ class Batches(_api_module.BaseModule):
998
998
  for batch_job in batch_jobs:
999
999
  print(f"Batch job: {batch_job.name}, state {batch_job.state}")
1000
1000
  """
1001
+ if config is None:
1002
+ config = types.ListBatchJobsConfig()
1001
1003
  return Pager(
1002
1004
  'batch_jobs',
1003
1005
  self._list,
@@ -1373,6 +1375,8 @@ class AsyncBatches(_api_module.BaseModule):
1373
1375
  await batch_jobs_pager.next_page()
1374
1376
  print(f"next page: {batch_jobs_pager.page}")
1375
1377
  """
1378
+ if config is None:
1379
+ config = types.ListBatchJobsConfig()
1376
1380
  return AsyncPager(
1377
1381
  'batch_jobs',
1378
1382
  self._list,
google/genai/caches.py CHANGED
@@ -174,15 +174,9 @@ def _Schema_to_mldev(
174
174
  if getv(from_object, ['pattern']) is not None:
175
175
  raise ValueError('pattern parameter is not supported in Gemini API.')
176
176
 
177
- if getv(from_object, ['minimum']) is not None:
178
- raise ValueError('minimum parameter is not supported in Gemini API.')
179
-
180
177
  if getv(from_object, ['default']) is not None:
181
178
  raise ValueError('default parameter is not supported in Gemini API.')
182
179
 
183
- if getv(from_object, ['any_of']) is not None:
184
- raise ValueError('any_of parameter is not supported in Gemini API.')
185
-
186
180
  if getv(from_object, ['max_length']) is not None:
187
181
  raise ValueError('max_length parameter is not supported in Gemini API.')
188
182
 
@@ -195,12 +189,12 @@ def _Schema_to_mldev(
195
189
  if getv(from_object, ['min_properties']) is not None:
196
190
  raise ValueError('min_properties parameter is not supported in Gemini API.')
197
191
 
198
- if getv(from_object, ['maximum']) is not None:
199
- raise ValueError('maximum parameter is not supported in Gemini API.')
200
-
201
192
  if getv(from_object, ['max_properties']) is not None:
202
193
  raise ValueError('max_properties parameter is not supported in Gemini API.')
203
194
 
195
+ if getv(from_object, ['any_of']) is not None:
196
+ setv(to_object, ['anyOf'], getv(from_object, ['any_of']))
197
+
204
198
  if getv(from_object, ['description']) is not None:
205
199
  setv(to_object, ['description'], getv(from_object, ['description']))
206
200
 
@@ -216,9 +210,15 @@ def _Schema_to_mldev(
216
210
  if getv(from_object, ['max_items']) is not None:
217
211
  setv(to_object, ['maxItems'], getv(from_object, ['max_items']))
218
212
 
213
+ if getv(from_object, ['maximum']) is not None:
214
+ setv(to_object, ['maximum'], getv(from_object, ['maximum']))
215
+
219
216
  if getv(from_object, ['min_items']) is not None:
220
217
  setv(to_object, ['minItems'], getv(from_object, ['min_items']))
221
218
 
219
+ if getv(from_object, ['minimum']) is not None:
220
+ setv(to_object, ['minimum'], getv(from_object, ['minimum']))
221
+
222
222
  if getv(from_object, ['nullable']) is not None:
223
223
  setv(to_object, ['nullable'], getv(from_object, ['nullable']))
224
224
 
@@ -253,15 +253,9 @@ def _Schema_to_vertex(
253
253
  if getv(from_object, ['pattern']) is not None:
254
254
  setv(to_object, ['pattern'], getv(from_object, ['pattern']))
255
255
 
256
- if getv(from_object, ['minimum']) is not None:
257
- setv(to_object, ['minimum'], getv(from_object, ['minimum']))
258
-
259
256
  if getv(from_object, ['default']) is not None:
260
257
  setv(to_object, ['default'], getv(from_object, ['default']))
261
258
 
262
- if getv(from_object, ['any_of']) is not None:
263
- setv(to_object, ['anyOf'], getv(from_object, ['any_of']))
264
-
265
259
  if getv(from_object, ['max_length']) is not None:
266
260
  setv(to_object, ['maxLength'], getv(from_object, ['max_length']))
267
261
 
@@ -274,12 +268,12 @@ def _Schema_to_vertex(
274
268
  if getv(from_object, ['min_properties']) is not None:
275
269
  setv(to_object, ['minProperties'], getv(from_object, ['min_properties']))
276
270
 
277
- if getv(from_object, ['maximum']) is not None:
278
- setv(to_object, ['maximum'], getv(from_object, ['maximum']))
279
-
280
271
  if getv(from_object, ['max_properties']) is not None:
281
272
  setv(to_object, ['maxProperties'], getv(from_object, ['max_properties']))
282
273
 
274
+ if getv(from_object, ['any_of']) is not None:
275
+ setv(to_object, ['anyOf'], getv(from_object, ['any_of']))
276
+
283
277
  if getv(from_object, ['description']) is not None:
284
278
  setv(to_object, ['description'], getv(from_object, ['description']))
285
279
 
@@ -295,9 +289,15 @@ def _Schema_to_vertex(
295
289
  if getv(from_object, ['max_items']) is not None:
296
290
  setv(to_object, ['maxItems'], getv(from_object, ['max_items']))
297
291
 
292
+ if getv(from_object, ['maximum']) is not None:
293
+ setv(to_object, ['maximum'], getv(from_object, ['maximum']))
294
+
298
295
  if getv(from_object, ['min_items']) is not None:
299
296
  setv(to_object, ['minItems'], getv(from_object, ['min_items']))
300
297
 
298
+ if getv(from_object, ['minimum']) is not None:
299
+ setv(to_object, ['minimum'], getv(from_object, ['minimum']))
300
+
301
301
  if getv(from_object, ['nullable']) is not None:
302
302
  setv(to_object, ['nullable'], getv(from_object, ['nullable']))
303
303
 
@@ -1176,10 +1176,7 @@ class Caches(_api_module.BaseModule):
1176
1176
  model: str,
1177
1177
  config: Optional[types.CreateCachedContentConfigOrDict] = None,
1178
1178
  ) -> types.CachedContent:
1179
- """Creates cached content, this call will initialize the cached
1180
-
1181
- content in the data storage, and users need to pay for the cache data
1182
- storage.
1179
+ """Creates a cached contents resource.
1183
1180
 
1184
1181
  Usage:
1185
1182
 
@@ -1562,10 +1559,7 @@ class AsyncCaches(_api_module.BaseModule):
1562
1559
  model: str,
1563
1560
  config: Optional[types.CreateCachedContentConfigOrDict] = None,
1564
1561
  ) -> types.CachedContent:
1565
- """Creates cached content, this call will initialize the cached
1566
-
1567
- content in the data storage, and users need to pay for the cache data
1568
- storage.
1562
+ """Creates a cached contents resource.
1569
1563
 
1570
1564
  Usage:
1571
1565