|
20 | 20 | import mimetypes |
21 | 21 | import os |
22 | 22 | import pathlib |
23 | | -from typing import Any, Optional, Union |
| 23 | +from typing import Any, Optional, Union, List |
24 | 24 | from urllib.parse import urlencode |
25 | 25 | from . import _api_module |
26 | 26 | from . import _common |
@@ -697,6 +697,69 @@ def upload( |
697 | 697 | kwargs=config_model.model_dump() if config else {}, |
698 | 698 | ) |
699 | 699 |
|
| 700 | + def upload_many( |
| 701 | + self, |
| 702 | + *, |
| 703 | + files: List[Union[str, pathlib.Path, os.PathLike, io.IOBase]], |
| 704 | + configs: Optional[List[Optional[types.UploadFileConfigOrDict]]] = None, |
| 705 | + ) -> List[types.File]: |
| 706 | + """Uploads multiple files using a supported file service. |
| 707 | +
|
| 708 | + Args: |
| 709 | + files: A list of paths to files or `IOBase` objects to be uploaded. Each file |
| 710 | + must follow the same requirements as the single file upload method. If it's an |
| 711 | + IOBase object, it must be opened in blocking (the default) mode and |
| 712 | + binary mode. In other words, do not use non-blocking mode or text mode. |
| 713 | + The given stream must be seekable, that is, it must be able to call |
| 714 | + `seek()` on 'path'. |
| 715 | + configs: Optional list of configurations for each file. If provided, must have |
| 716 | + the same length as the files list. Each config can contain parameters to set |
| 717 | + `display_name`, `mime_type`, and `name`. |
| 718 | +
|
| 719 | + Returns: |
| 720 | + A list of uploaded File objects. |
| 721 | +
|
| 722 | + Raises: |
| 723 | + ValueError: If the number of configs doesn't match the number of files. |
| 724 | + FileNotFoundError: If any of the file paths are invalid. |
| 725 | + ValueError: If the mime type cannot be determined for any file. |
| 726 | + ValueError: If any file is not opened in binary mode. |
| 727 | + ValueError: If this method is called with a Vertex AI client. |
| 728 | +
|
| 729 | + Example: |
| 730 | + ```python |
| 731 | + files = client.files.upload_many( |
| 732 | + files=["file1.txt", "file2.txt"], |
| 733 | + configs=[ |
| 734 | + {"display_name": "First File"}, |
| 735 | + {"display_name": "Second File"} |
| 736 | + ] |
| 737 | + ) |
| 738 | + ``` |
| 739 | + """ |
| 740 | + if self._api_client.vertexai: |
| 741 | + raise ValueError( |
| 742 | + 'This method is only supported in the Gemini Developer client.' |
| 743 | + ) |
| 744 | + |
| 745 | + if not files: |
| 746 | + return [] |
| 747 | + |
| 748 | + if configs is not None and len(configs) != len(files): |
| 749 | + raise ValueError( |
| 750 | + 'The number of configs must match the number of files' |
| 751 | + ) |
| 752 | + |
| 753 | + if configs is None: |
| 754 | + configs = [None] * len(files) |
| 755 | + |
| 756 | + uploaded_files = [] |
| 757 | + for file, config in zip(files, configs): |
| 758 | + uploaded_file = self.upload(file=file, config=config) |
| 759 | + uploaded_files.append(uploaded_file) |
| 760 | + |
| 761 | + return uploaded_files |
| 762 | + |
700 | 763 | def list( |
701 | 764 | self, *, config: Optional[types.ListFilesConfigOrDict] = None |
702 | 765 | ) -> Pager[types.File]: |
@@ -1160,6 +1223,69 @@ async def upload( |
1160 | 1223 | kwargs=config_model.model_dump() if config else {}, |
1161 | 1224 | ) |
1162 | 1225 |
|
| 1226 | + async def upload_many( |
| 1227 | + self, |
| 1228 | + *, |
| 1229 | + files: List[Union[str, pathlib.Path, os.PathLike, io.IOBase]], |
| 1230 | + configs: Optional[List[Optional[types.UploadFileConfigOrDict]]] = None, |
| 1231 | + ) -> List[types.File]: |
| 1232 | + """Uploads multiple files asynchronously using a supported file service. |
| 1233 | +
|
| 1234 | + Args: |
| 1235 | + files: A list of paths to files or `IOBase` objects to be uploaded. Each file |
| 1236 | + must follow the same requirements as the single file upload method. If it's an |
| 1237 | + IOBase object, it must be opened in blocking (the default) mode and |
| 1238 | + binary mode. In other words, do not use non-blocking mode or text mode. |
| 1239 | + The given stream must be seekable, that is, it must be able to call |
| 1240 | + `seek()` on 'path'. |
| 1241 | + configs: Optional list of configurations for each file. If provided, must have |
| 1242 | + the same length as the files list. Each config can contain parameters to set |
| 1243 | + `display_name`, `mime_type`, and `name`. |
| 1244 | +
|
| 1245 | + Returns: |
| 1246 | + A list of uploaded File objects. |
| 1247 | +
|
| 1248 | + Raises: |
| 1249 | + ValueError: If the number of configs doesn't match the number of files. |
| 1250 | + FileNotFoundError: If any of the file paths are invalid. |
| 1251 | + ValueError: If the mime type cannot be determined for any file. |
| 1252 | + ValueError: If any file is not opened in binary mode. |
| 1253 | + ValueError: If this method is called with a Vertex AI client. |
| 1254 | +
|
| 1255 | + Example: |
| 1256 | + ```python |
| 1257 | + files = await client.aio.files.upload_many( |
| 1258 | + files=["file1.txt", "file2.txt"], |
| 1259 | + configs=[ |
| 1260 | + {"display_name": "First File"}, |
| 1261 | + {"display_name": "Second File"} |
| 1262 | + ] |
| 1263 | + ) |
| 1264 | + ``` |
| 1265 | + """ |
| 1266 | + if self._api_client.vertexai: |
| 1267 | + raise ValueError( |
| 1268 | + 'This method is only supported in the Gemini Developer client.' |
| 1269 | + ) |
| 1270 | + |
| 1271 | + if not files: |
| 1272 | + return [] |
| 1273 | + |
| 1274 | + if configs is not None and len(configs) != len(files): |
| 1275 | + raise ValueError( |
| 1276 | + 'The number of configs must match the number of files' |
| 1277 | + ) |
| 1278 | + |
| 1279 | + if configs is None: |
| 1280 | + configs = [None] * len(files) |
| 1281 | + |
| 1282 | + uploaded_files = [] |
| 1283 | + for file, config in zip(files, configs): |
| 1284 | + uploaded_file = await self.upload(file=file, config=config) |
| 1285 | + uploaded_files.append(uploaded_file) |
| 1286 | + |
| 1287 | + return uploaded_files |
| 1288 | + |
1163 | 1289 | async def list( |
1164 | 1290 | self, *, config: Optional[types.ListFilesConfigOrDict] = None |
1165 | 1291 | ) -> AsyncPager[types.File]: |
|
0 commit comments