google-genai 0.4.0__py3-none-any.whl → 0.6.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/files.py CHANGED
@@ -13,8 +13,12 @@
13
13
  # limitations under the License.
14
14
  #
15
15
 
16
+ # Code generated by the Google Gen AI SDK generator DO NOT EDIT.
17
+
18
+ import io
16
19
  import mimetypes
17
20
  import os
21
+ import pathlib
18
22
  from typing import Optional, Union
19
23
  from urllib.parse import urlencode
20
24
  from . import _common
@@ -173,9 +177,15 @@ def _File_to_mldev(
173
177
  if getv(from_object, ['uri']) is not None:
174
178
  setv(to_object, ['uri'], getv(from_object, ['uri']))
175
179
 
180
+ if getv(from_object, ['download_uri']) is not None:
181
+ setv(to_object, ['downloadUri'], getv(from_object, ['download_uri']))
182
+
176
183
  if getv(from_object, ['state']) is not None:
177
184
  setv(to_object, ['state'], getv(from_object, ['state']))
178
185
 
186
+ if getv(from_object, ['source']) is not None:
187
+ setv(to_object, ['source'], getv(from_object, ['source']))
188
+
179
189
  if getv(from_object, ['video_metadata']) is not None:
180
190
  setv(to_object, ['videoMetadata'], getv(from_object, ['video_metadata']))
181
191
 
@@ -224,9 +234,15 @@ def _File_to_vertex(
224
234
  if getv(from_object, ['uri']) is not None:
225
235
  raise ValueError('uri parameter is not supported in Vertex AI.')
226
236
 
237
+ if getv(from_object, ['download_uri']) is not None:
238
+ raise ValueError('download_uri parameter is not supported in Vertex AI.')
239
+
227
240
  if getv(from_object, ['state']) is not None:
228
241
  raise ValueError('state parameter is not supported in Vertex AI.')
229
242
 
243
+ if getv(from_object, ['source']) is not None:
244
+ raise ValueError('source parameter is not supported in Vertex AI.')
245
+
230
246
  if getv(from_object, ['video_metadata']) is not None:
231
247
  raise ValueError('video_metadata parameter is not supported in Vertex AI.')
232
248
 
@@ -489,9 +505,15 @@ def _File_from_mldev(
489
505
  if getv(from_object, ['uri']) is not None:
490
506
  setv(to_object, ['uri'], getv(from_object, ['uri']))
491
507
 
508
+ if getv(from_object, ['downloadUri']) is not None:
509
+ setv(to_object, ['download_uri'], getv(from_object, ['downloadUri']))
510
+
492
511
  if getv(from_object, ['state']) is not None:
493
512
  setv(to_object, ['state'], getv(from_object, ['state']))
494
513
 
514
+ if getv(from_object, ['source']) is not None:
515
+ setv(to_object, ['source'], getv(from_object, ['source']))
516
+
495
517
  if getv(from_object, ['videoMetadata']) is not None:
496
518
  setv(to_object, ['video_metadata'], getv(from_object, ['videoMetadata']))
497
519
 
@@ -615,11 +637,11 @@ class Files(_common.BaseModule):
615
637
  config=config,
616
638
  )
617
639
 
618
- if self.api_client.vertexai:
640
+ if self._api_client.vertexai:
619
641
  raise ValueError('This method is only supported in the default client.')
620
642
  else:
621
643
  request_dict = _ListFilesParameters_to_mldev(
622
- self.api_client, parameter_model
644
+ self._api_client, parameter_model
623
645
  )
624
646
  path = 'files'.format_map(request_dict.get('_url'))
625
647
 
@@ -630,25 +652,25 @@ class Files(_common.BaseModule):
630
652
  config = request_dict.pop('config', None)
631
653
  http_options = config.pop('httpOptions', None) if config else None
632
654
  request_dict = _common.convert_to_dict(request_dict)
633
- request_dict = _common.apply_base64_encoding(request_dict)
655
+ request_dict = _common.encode_unserializable_types(request_dict)
634
656
 
635
- response_dict = self.api_client.request(
657
+ response_dict = self._api_client.request(
636
658
  'get', path, request_dict, http_options
637
659
  )
638
660
 
639
- if self.api_client.vertexai:
661
+ if self._api_client.vertexai:
640
662
  response_dict = _ListFilesResponse_from_vertex(
641
- self.api_client, response_dict
663
+ self._api_client, response_dict
642
664
  )
643
665
  else:
644
666
  response_dict = _ListFilesResponse_from_mldev(
645
- self.api_client, response_dict
667
+ self._api_client, response_dict
646
668
  )
647
669
 
648
670
  return_value = types.ListFilesResponse._from_response(
649
671
  response_dict, parameter_model
650
672
  )
651
- self.api_client._verify_response(return_value)
673
+ self._api_client._verify_response(return_value)
652
674
  return return_value
653
675
 
654
676
  def _create(
@@ -662,11 +684,11 @@ class Files(_common.BaseModule):
662
684
  config=config,
663
685
  )
664
686
 
665
- if self.api_client.vertexai:
687
+ if self._api_client.vertexai:
666
688
  raise ValueError('This method is only supported in the default client.')
667
689
  else:
668
690
  request_dict = _CreateFileParameters_to_mldev(
669
- self.api_client, parameter_model
691
+ self._api_client, parameter_model
670
692
  )
671
693
  path = 'upload/v1beta/files'.format_map(request_dict.get('_url'))
672
694
 
@@ -677,25 +699,25 @@ class Files(_common.BaseModule):
677
699
  config = request_dict.pop('config', None)
678
700
  http_options = config.pop('httpOptions', None) if config else None
679
701
  request_dict = _common.convert_to_dict(request_dict)
680
- request_dict = _common.apply_base64_encoding(request_dict)
702
+ request_dict = _common.encode_unserializable_types(request_dict)
681
703
 
682
- response_dict = self.api_client.request(
704
+ response_dict = self._api_client.request(
683
705
  'post', path, request_dict, http_options
684
706
  )
685
707
 
686
- if self.api_client.vertexai:
708
+ if self._api_client.vertexai:
687
709
  response_dict = _CreateFileResponse_from_vertex(
688
- self.api_client, response_dict
710
+ self._api_client, response_dict
689
711
  )
690
712
  else:
691
713
  response_dict = _CreateFileResponse_from_mldev(
692
- self.api_client, response_dict
714
+ self._api_client, response_dict
693
715
  )
694
716
 
695
717
  return_value = types.CreateFileResponse._from_response(
696
718
  response_dict, parameter_model
697
719
  )
698
- self.api_client._verify_response(return_value)
720
+ self._api_client._verify_response(return_value)
699
721
  return return_value
700
722
 
701
723
  def get(
@@ -723,11 +745,11 @@ class Files(_common.BaseModule):
723
745
  config=config,
724
746
  )
725
747
 
726
- if self.api_client.vertexai:
748
+ if self._api_client.vertexai:
727
749
  raise ValueError('This method is only supported in the default client.')
728
750
  else:
729
751
  request_dict = _GetFileParameters_to_mldev(
730
- self.api_client, parameter_model
752
+ self._api_client, parameter_model
731
753
  )
732
754
  path = 'files/{file}'.format_map(request_dict.get('_url'))
733
755
 
@@ -738,19 +760,19 @@ class Files(_common.BaseModule):
738
760
  config = request_dict.pop('config', None)
739
761
  http_options = config.pop('httpOptions', None) if config else None
740
762
  request_dict = _common.convert_to_dict(request_dict)
741
- request_dict = _common.apply_base64_encoding(request_dict)
763
+ request_dict = _common.encode_unserializable_types(request_dict)
742
764
 
743
- response_dict = self.api_client.request(
765
+ response_dict = self._api_client.request(
744
766
  'get', path, request_dict, http_options
745
767
  )
746
768
 
747
- if self.api_client.vertexai:
748
- response_dict = _File_from_vertex(self.api_client, response_dict)
769
+ if self._api_client.vertexai:
770
+ response_dict = _File_from_vertex(self._api_client, response_dict)
749
771
  else:
750
- response_dict = _File_from_mldev(self.api_client, response_dict)
772
+ response_dict = _File_from_mldev(self._api_client, response_dict)
751
773
 
752
774
  return_value = types.File._from_response(response_dict, parameter_model)
753
- self.api_client._verify_response(return_value)
775
+ self._api_client._verify_response(return_value)
754
776
  return return_value
755
777
 
756
778
  def delete(
@@ -777,11 +799,11 @@ class Files(_common.BaseModule):
777
799
  config=config,
778
800
  )
779
801
 
780
- if self.api_client.vertexai:
802
+ if self._api_client.vertexai:
781
803
  raise ValueError('This method is only supported in the default client.')
782
804
  else:
783
805
  request_dict = _DeleteFileParameters_to_mldev(
784
- self.api_client, parameter_model
806
+ self._api_client, parameter_model
785
807
  )
786
808
  path = 'files/{file}'.format_map(request_dict.get('_url'))
787
809
 
@@ -792,41 +814,43 @@ class Files(_common.BaseModule):
792
814
  config = request_dict.pop('config', None)
793
815
  http_options = config.pop('httpOptions', None) if config else None
794
816
  request_dict = _common.convert_to_dict(request_dict)
795
- request_dict = _common.apply_base64_encoding(request_dict)
817
+ request_dict = _common.encode_unserializable_types(request_dict)
796
818
 
797
- response_dict = self.api_client.request(
819
+ response_dict = self._api_client.request(
798
820
  'delete', path, request_dict, http_options
799
821
  )
800
822
 
801
- if self.api_client.vertexai:
823
+ if self._api_client.vertexai:
802
824
  response_dict = _DeleteFileResponse_from_vertex(
803
- self.api_client, response_dict
825
+ self._api_client, response_dict
804
826
  )
805
827
  else:
806
828
  response_dict = _DeleteFileResponse_from_mldev(
807
- self.api_client, response_dict
829
+ self._api_client, response_dict
808
830
  )
809
831
 
810
832
  return_value = types.DeleteFileResponse._from_response(
811
833
  response_dict, parameter_model
812
834
  )
813
- self.api_client._verify_response(return_value)
835
+ self._api_client._verify_response(return_value)
814
836
  return return_value
815
837
 
816
838
  def upload(
817
839
  self,
818
840
  *,
819
- path: str,
841
+ path: Union[str, pathlib.Path, os.PathLike, io.IOBase],
820
842
  config: Optional[types.UploadFileConfigOrDict] = None,
821
843
  ) -> types.File:
822
844
  """Calls the API to upload a file using a supported file service.
823
845
 
824
846
  Args:
825
- path: The path to the file or a file-like object (e.g. `BytesIO`) to be
826
- uploaded.
847
+ path: The path to the file or an `IOBase` object to be uploaded. If it's
848
+ an IOBase object, it must be opened in blocking mode and binary mode. In
849
+ other words, do not use non-blocking mode or text mode. The given stream
850
+ must be seekable, that is, it must be able to call seek() on 'path'.
827
851
  config: Optional parameters to set `diplay_name`, `mime_type`, and `name`.
828
852
  """
829
- if self.api_client.vertexai:
853
+ if self._api_client.vertexai:
830
854
  raise ValueError(
831
855
  'Vertex AI does not support creating files. You can upload files to'
832
856
  ' GCS files instead.'
@@ -847,17 +871,31 @@ class Files(_common.BaseModule):
847
871
  if file.name is not None and not file.name.startswith('files/'):
848
872
  file.name = f'files/{file.name}'
849
873
 
850
- fs_path = os.fspath(path)
851
- if not fs_path or not os.path.isfile(fs_path):
852
- raise FileNotFoundError(f'{path} is not a valid file path.')
853
- file.size_bytes = os.path.getsize(fs_path)
854
- if file.mime_type is None:
855
- file.mime_type, _ = mimetypes.guess_type(fs_path)
856
- if file.mime_type is None:
857
- raise ValueError(
858
- 'Unknown mime type: Could not determine the mimetype for your file\n'
859
- ' please set the `mime_type` argument'
860
- )
874
+ if isinstance(path, io.IOBase):
875
+ if file.mime_type is None:
876
+ raise ValueError(
877
+ 'Unknown mime type: Could not determine the mimetype for your'
878
+ ' file\n please set the `mime_type` argument'
879
+ )
880
+ if hasattr(path, 'mode'):
881
+ if 'b' not in path.mode:
882
+ raise ValueError('The file must be opened in binary mode.')
883
+ offset = path.tell()
884
+ path.seek(0, os.SEEK_END)
885
+ file.size_bytes = path.tell() - offset
886
+ path.seek(offset, os.SEEK_SET)
887
+ else:
888
+ fs_path = os.fspath(path)
889
+ if not fs_path or not os.path.isfile(fs_path):
890
+ raise FileNotFoundError(f'{path} is not a valid file path.')
891
+ file.size_bytes = os.path.getsize(fs_path)
892
+ if file.mime_type is None:
893
+ file.mime_type, _ = mimetypes.guess_type(fs_path)
894
+ if file.mime_type is None:
895
+ raise ValueError(
896
+ 'Unknown mime type: Could not determine the mimetype for your'
897
+ ' file\n please set the `mime_type` argument'
898
+ )
861
899
  response = {}
862
900
  if config_model and config_model.http_options:
863
901
  http_options = config_model.http_options
@@ -874,6 +912,7 @@ class Files(_common.BaseModule):
874
912
  'response_payload': response,
875
913
  }
876
914
  self._create(file=file, config={'http_options': http_options})
915
+
877
916
  if (
878
917
  'headers' not in response
879
918
  or 'X-Goog-Upload-URL' not in response['headers']
@@ -884,12 +923,17 @@ class Files(_common.BaseModule):
884
923
  )
885
924
  upload_url = response['headers']['X-Goog-Upload-URL']
886
925
 
887
- return_file = self.api_client.upload_file(
888
- fs_path, upload_url, file.size_bytes
889
- )
926
+ if isinstance(path, io.IOBase):
927
+ return_file = self._api_client.upload_file(
928
+ path, upload_url, file.size_bytes
929
+ )
930
+ else:
931
+ return_file = self._api_client.upload_file(
932
+ fs_path, upload_url, file.size_bytes
933
+ )
890
934
 
891
935
  return types.File._from_response(
892
- _File_from_mldev(self.api_client, return_file['file']), None
936
+ _File_from_mldev(self._api_client, return_file['file']), None
893
937
  )
894
938
 
895
939
  def list(
@@ -902,6 +946,74 @@ class Files(_common.BaseModule):
902
946
  config,
903
947
  )
904
948
 
949
+ def download(
950
+ self,
951
+ *,
952
+ file: Union[str, types.File],
953
+ config: Optional[types.DownloadFileConfigOrDict] = None,
954
+ ) -> bytes:
955
+ """Downloads a file's data from storage.
956
+
957
+ Files created by `upload` can't be downloaded. You can tell which files are
958
+ downloadable by checking the `source` or `download_uri` property.
959
+
960
+ Args:
961
+ file (str): A file name, uri, or file object. Identifying which file to
962
+ download.
963
+ config (DownloadFileConfigOrDict): Optional, configuration for the get
964
+ method.
965
+
966
+ Returns:
967
+ File: The file data as bytes.
968
+
969
+ Usage:
970
+
971
+ .. code-block:: python
972
+
973
+ for file client.files.list():
974
+ if file.download_uri is not None:
975
+ break
976
+ else:
977
+ raise ValueError('No files found with a `download_uri`.')
978
+ data = client.files.download(file=file)
979
+ # data = client.files.download(file=file.name)
980
+ # data = client.files.download(file=file.download_uri)
981
+ """
982
+ if self._api_client.vertexai:
983
+ raise ValueError(
984
+ 'Vertex AI does not support the Files API. Use GCS files instead.'
985
+ )
986
+
987
+ config_model = None
988
+ if config:
989
+ if isinstance(config, dict):
990
+ config_model = types.DownloadFileConfig(**config)
991
+ else:
992
+ config_model = config
993
+
994
+ if isinstance(file, types.File) and file.download_uri is None:
995
+ raise ValueError(
996
+ "Only generated files can be downloaded, uploaded files can't be "
997
+ 'downloaded. You can tell which files are downloadable by checking '
998
+ 'the `source` or `download_uri` property.'
999
+ )
1000
+ name = t.t_file_name(self, file)
1001
+
1002
+ path = f'files/{name}:download'
1003
+
1004
+ query_params = {'alt': 'media'}
1005
+ path = f'{path}?{urlencode(query_params)}'
1006
+ http_options = None
1007
+ if getv(config_model, ['http_options']) is not None:
1008
+ http_options = getv(config_model, ['http_options'])
1009
+
1010
+ data = self._api_client.download_file(
1011
+ path,
1012
+ http_options,
1013
+ )
1014
+
1015
+ return data
1016
+
905
1017
 
906
1018
  class AsyncFiles(_common.BaseModule):
907
1019
 
@@ -929,11 +1041,11 @@ class AsyncFiles(_common.BaseModule):
929
1041
  config=config,
930
1042
  )
931
1043
 
932
- if self.api_client.vertexai:
1044
+ if self._api_client.vertexai:
933
1045
  raise ValueError('This method is only supported in the default client.')
934
1046
  else:
935
1047
  request_dict = _ListFilesParameters_to_mldev(
936
- self.api_client, parameter_model
1048
+ self._api_client, parameter_model
937
1049
  )
938
1050
  path = 'files'.format_map(request_dict.get('_url'))
939
1051
 
@@ -944,25 +1056,25 @@ class AsyncFiles(_common.BaseModule):
944
1056
  config = request_dict.pop('config', None)
945
1057
  http_options = config.pop('httpOptions', None) if config else None
946
1058
  request_dict = _common.convert_to_dict(request_dict)
947
- request_dict = _common.apply_base64_encoding(request_dict)
1059
+ request_dict = _common.encode_unserializable_types(request_dict)
948
1060
 
949
- response_dict = await self.api_client.async_request(
1061
+ response_dict = await self._api_client.async_request(
950
1062
  'get', path, request_dict, http_options
951
1063
  )
952
1064
 
953
- if self.api_client.vertexai:
1065
+ if self._api_client.vertexai:
954
1066
  response_dict = _ListFilesResponse_from_vertex(
955
- self.api_client, response_dict
1067
+ self._api_client, response_dict
956
1068
  )
957
1069
  else:
958
1070
  response_dict = _ListFilesResponse_from_mldev(
959
- self.api_client, response_dict
1071
+ self._api_client, response_dict
960
1072
  )
961
1073
 
962
1074
  return_value = types.ListFilesResponse._from_response(
963
1075
  response_dict, parameter_model
964
1076
  )
965
- self.api_client._verify_response(return_value)
1077
+ self._api_client._verify_response(return_value)
966
1078
  return return_value
967
1079
 
968
1080
  async def _create(
@@ -976,11 +1088,11 @@ class AsyncFiles(_common.BaseModule):
976
1088
  config=config,
977
1089
  )
978
1090
 
979
- if self.api_client.vertexai:
1091
+ if self._api_client.vertexai:
980
1092
  raise ValueError('This method is only supported in the default client.')
981
1093
  else:
982
1094
  request_dict = _CreateFileParameters_to_mldev(
983
- self.api_client, parameter_model
1095
+ self._api_client, parameter_model
984
1096
  )
985
1097
  path = 'upload/v1beta/files'.format_map(request_dict.get('_url'))
986
1098
 
@@ -991,25 +1103,25 @@ class AsyncFiles(_common.BaseModule):
991
1103
  config = request_dict.pop('config', None)
992
1104
  http_options = config.pop('httpOptions', None) if config else None
993
1105
  request_dict = _common.convert_to_dict(request_dict)
994
- request_dict = _common.apply_base64_encoding(request_dict)
1106
+ request_dict = _common.encode_unserializable_types(request_dict)
995
1107
 
996
- response_dict = await self.api_client.async_request(
1108
+ response_dict = await self._api_client.async_request(
997
1109
  'post', path, request_dict, http_options
998
1110
  )
999
1111
 
1000
- if self.api_client.vertexai:
1112
+ if self._api_client.vertexai:
1001
1113
  response_dict = _CreateFileResponse_from_vertex(
1002
- self.api_client, response_dict
1114
+ self._api_client, response_dict
1003
1115
  )
1004
1116
  else:
1005
1117
  response_dict = _CreateFileResponse_from_mldev(
1006
- self.api_client, response_dict
1118
+ self._api_client, response_dict
1007
1119
  )
1008
1120
 
1009
1121
  return_value = types.CreateFileResponse._from_response(
1010
1122
  response_dict, parameter_model
1011
1123
  )
1012
- self.api_client._verify_response(return_value)
1124
+ self._api_client._verify_response(return_value)
1013
1125
  return return_value
1014
1126
 
1015
1127
  async def get(
@@ -1037,11 +1149,11 @@ class AsyncFiles(_common.BaseModule):
1037
1149
  config=config,
1038
1150
  )
1039
1151
 
1040
- if self.api_client.vertexai:
1152
+ if self._api_client.vertexai:
1041
1153
  raise ValueError('This method is only supported in the default client.')
1042
1154
  else:
1043
1155
  request_dict = _GetFileParameters_to_mldev(
1044
- self.api_client, parameter_model
1156
+ self._api_client, parameter_model
1045
1157
  )
1046
1158
  path = 'files/{file}'.format_map(request_dict.get('_url'))
1047
1159
 
@@ -1052,19 +1164,19 @@ class AsyncFiles(_common.BaseModule):
1052
1164
  config = request_dict.pop('config', None)
1053
1165
  http_options = config.pop('httpOptions', None) if config else None
1054
1166
  request_dict = _common.convert_to_dict(request_dict)
1055
- request_dict = _common.apply_base64_encoding(request_dict)
1167
+ request_dict = _common.encode_unserializable_types(request_dict)
1056
1168
 
1057
- response_dict = await self.api_client.async_request(
1169
+ response_dict = await self._api_client.async_request(
1058
1170
  'get', path, request_dict, http_options
1059
1171
  )
1060
1172
 
1061
- if self.api_client.vertexai:
1062
- response_dict = _File_from_vertex(self.api_client, response_dict)
1173
+ if self._api_client.vertexai:
1174
+ response_dict = _File_from_vertex(self._api_client, response_dict)
1063
1175
  else:
1064
- response_dict = _File_from_mldev(self.api_client, response_dict)
1176
+ response_dict = _File_from_mldev(self._api_client, response_dict)
1065
1177
 
1066
1178
  return_value = types.File._from_response(response_dict, parameter_model)
1067
- self.api_client._verify_response(return_value)
1179
+ self._api_client._verify_response(return_value)
1068
1180
  return return_value
1069
1181
 
1070
1182
  async def delete(
@@ -1091,11 +1203,11 @@ class AsyncFiles(_common.BaseModule):
1091
1203
  config=config,
1092
1204
  )
1093
1205
 
1094
- if self.api_client.vertexai:
1206
+ if self._api_client.vertexai:
1095
1207
  raise ValueError('This method is only supported in the default client.')
1096
1208
  else:
1097
1209
  request_dict = _DeleteFileParameters_to_mldev(
1098
- self.api_client, parameter_model
1210
+ self._api_client, parameter_model
1099
1211
  )
1100
1212
  path = 'files/{file}'.format_map(request_dict.get('_url'))
1101
1213
 
@@ -1106,41 +1218,43 @@ class AsyncFiles(_common.BaseModule):
1106
1218
  config = request_dict.pop('config', None)
1107
1219
  http_options = config.pop('httpOptions', None) if config else None
1108
1220
  request_dict = _common.convert_to_dict(request_dict)
1109
- request_dict = _common.apply_base64_encoding(request_dict)
1221
+ request_dict = _common.encode_unserializable_types(request_dict)
1110
1222
 
1111
- response_dict = await self.api_client.async_request(
1223
+ response_dict = await self._api_client.async_request(
1112
1224
  'delete', path, request_dict, http_options
1113
1225
  )
1114
1226
 
1115
- if self.api_client.vertexai:
1227
+ if self._api_client.vertexai:
1116
1228
  response_dict = _DeleteFileResponse_from_vertex(
1117
- self.api_client, response_dict
1229
+ self._api_client, response_dict
1118
1230
  )
1119
1231
  else:
1120
1232
  response_dict = _DeleteFileResponse_from_mldev(
1121
- self.api_client, response_dict
1233
+ self._api_client, response_dict
1122
1234
  )
1123
1235
 
1124
1236
  return_value = types.DeleteFileResponse._from_response(
1125
1237
  response_dict, parameter_model
1126
1238
  )
1127
- self.api_client._verify_response(return_value)
1239
+ self._api_client._verify_response(return_value)
1128
1240
  return return_value
1129
1241
 
1130
1242
  async def upload(
1131
1243
  self,
1132
1244
  *,
1133
- path: str,
1245
+ path: Union[str, pathlib.Path, os.PathLike, io.IOBase],
1134
1246
  config: Optional[types.UploadFileConfigOrDict] = None,
1135
1247
  ) -> types.File:
1136
1248
  """Calls the API to upload a file asynchronously using a supported file service.
1137
1249
 
1138
1250
  Args:
1139
- path: The path to the file or a file-like object (e.g. `BytesIO`) to be
1140
- uploaded.
1251
+ path: The path to the file or an `IOBase` object to be uploaded. If it's
1252
+ an IOBase object, it must be opened in blocking mode and binary mode. In
1253
+ other words, do not use non-blocking mode or text mode. The given stream
1254
+ must be seekable, that is, it must be able to call seek() on 'path'.
1141
1255
  config: Optional parameters to set `diplay_name`, `mime_type`, and `name`.
1142
1256
  """
1143
- if self.api_client.vertexai:
1257
+ if self._api_client.vertexai:
1144
1258
  raise ValueError(
1145
1259
  'Vertex AI does not support creating files. You can upload files to'
1146
1260
  ' GCS files instead.'
@@ -1161,17 +1275,32 @@ class AsyncFiles(_common.BaseModule):
1161
1275
  if file.name is not None and not file.name.startswith('files/'):
1162
1276
  file.name = f'files/{file.name}'
1163
1277
 
1164
- fs_path = os.fspath(path)
1165
- if not fs_path or not os.path.isfile(fs_path):
1166
- raise FileNotFoundError(f'{path} is not a valid file path.')
1167
- file.size_bytes = os.path.getsize(fs_path)
1168
- if file.mime_type is None:
1169
- file.mime_type, _ = mimetypes.guess_type(fs_path)
1170
- if file.mime_type is None:
1171
- raise ValueError(
1172
- 'Unknown mime type: Could not determine the mimetype for your file\n'
1173
- ' please set the `mime_type` argument'
1174
- )
1278
+ if isinstance(path, io.IOBase):
1279
+ if file.mime_type is None:
1280
+ raise ValueError(
1281
+ 'Unknown mime type: Could not determine the mimetype for your'
1282
+ ' file\n please set the `mime_type` argument'
1283
+ )
1284
+ if hasattr(path, 'mode'):
1285
+ if 'b' not in path.mode:
1286
+ raise ValueError('The file must be opened in binary mode.')
1287
+ offset = path.tell()
1288
+ path.seek(0, os.SEEK_END)
1289
+ file.size_bytes = path.tell() - offset
1290
+ path.seek(offset, os.SEEK_SET)
1291
+ else:
1292
+ fs_path = os.fspath(path)
1293
+ if not fs_path or not os.path.isfile(fs_path):
1294
+ raise FileNotFoundError(f'{path} is not a valid file path.')
1295
+ file.size_bytes = os.path.getsize(fs_path)
1296
+ if file.mime_type is None:
1297
+ file.mime_type, _ = mimetypes.guess_type(fs_path)
1298
+ if file.mime_type is None:
1299
+ raise ValueError(
1300
+ 'Unknown mime type: Could not determine the mimetype for your'
1301
+ ' file\n please set the `mime_type` argument'
1302
+ )
1303
+
1175
1304
  response = {}
1176
1305
  if config_model and config_model.http_options:
1177
1306
  http_options = config_model.http_options
@@ -1198,12 +1327,17 @@ class AsyncFiles(_common.BaseModule):
1198
1327
  )
1199
1328
  upload_url = response['headers']['X-Goog-Upload-URL']
1200
1329
 
1201
- return_file = await self.api_client.async_upload_file(
1202
- fs_path, upload_url, file.size_bytes
1203
- )
1330
+ if isinstance(path, io.IOBase):
1331
+ return_file = await self._api_client.async_upload_file(
1332
+ path, upload_url, file.size_bytes
1333
+ )
1334
+ else:
1335
+ return_file = await self._api_client.async_upload_file(
1336
+ fs_path, upload_url, file.size_bytes
1337
+ )
1204
1338
 
1205
1339
  return types.File._from_response(
1206
- _File_from_mldev(self.api_client, return_file['file']), None
1340
+ _File_from_mldev(self._api_client, return_file['file']), None
1207
1341
  )
1208
1342
 
1209
1343
  async def list(
@@ -1215,3 +1349,69 @@ class AsyncFiles(_common.BaseModule):
1215
1349
  await self._list(config=config),
1216
1350
  config,
1217
1351
  )
1352
+
1353
+ async def download(
1354
+ self,
1355
+ *,
1356
+ file: Union[str, types.File],
1357
+ config: Optional[types.DownloadFileConfigOrDict] = None,
1358
+ ) -> bytes:
1359
+ """Downloads a file's data from the file service.
1360
+
1361
+ The Vertex-AI implementation of the API foes not include the file service.
1362
+
1363
+ Files created by `upload` can't be downloaded. You can tell which files are
1364
+ downloadable by checking the `download_uri` property.
1365
+
1366
+ Args:
1367
+ File (str): A file name, uri, or file object. Identifying which file to
1368
+ download.
1369
+ config (DownloadFileConfigOrDict): Optional, configuration for the get
1370
+ method.
1371
+
1372
+ Returns:
1373
+ File: The file data as bytes.
1374
+
1375
+ Usage:
1376
+
1377
+ .. code-block:: python
1378
+
1379
+ for file client.files.list():
1380
+ if file.download_uri is not None:
1381
+ break
1382
+ else:
1383
+ raise ValueError('No files found with a `download_uri`.')
1384
+ data = client.files.download(file=file)
1385
+ # data = client.files.download(file=file.name)
1386
+ # data = client.files.download(file=file.uri)
1387
+ """
1388
+ if self._api_client.vertexai:
1389
+ raise ValueError(
1390
+ 'Vertex AI does not support the Files API. Use GCS files instead.'
1391
+ )
1392
+
1393
+ config_model = None
1394
+ if config:
1395
+ if isinstance(config, dict):
1396
+ config_model = types.DownloadFileConfig(**config)
1397
+ else:
1398
+ config_model = config
1399
+
1400
+ name = t.t_file_name(self, file)
1401
+
1402
+ path = f'files/{name}:download'
1403
+
1404
+ http_options = None
1405
+ if getv(config_model, ['http_options']) is not None:
1406
+ http_options = getv(config_model, ['http_options'])
1407
+
1408
+ query_params = {'alt': 'media'}
1409
+ if query_params:
1410
+ path = f'{path}?{urlencode(query_params)}'
1411
+
1412
+ data = await self._api_client.async_download_file(
1413
+ path,
1414
+ http_options,
1415
+ )
1416
+
1417
+ return data