dtlpy 1.114.17__py3-none-any.whl → 1.116.6__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 (238) hide show
  1. dtlpy/__init__.py +491 -491
  2. dtlpy/__version__.py +1 -1
  3. dtlpy/assets/__init__.py +26 -26
  4. dtlpy/assets/code_server/config.yaml +2 -2
  5. dtlpy/assets/code_server/installation.sh +24 -24
  6. dtlpy/assets/code_server/launch.json +13 -13
  7. dtlpy/assets/code_server/settings.json +2 -2
  8. dtlpy/assets/main.py +53 -53
  9. dtlpy/assets/main_partial.py +18 -18
  10. dtlpy/assets/mock.json +11 -11
  11. dtlpy/assets/model_adapter.py +83 -83
  12. dtlpy/assets/package.json +61 -61
  13. dtlpy/assets/package_catalog.json +29 -29
  14. dtlpy/assets/package_gitignore +307 -307
  15. dtlpy/assets/service_runners/__init__.py +33 -33
  16. dtlpy/assets/service_runners/converter.py +96 -96
  17. dtlpy/assets/service_runners/multi_method.py +49 -49
  18. dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
  19. dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
  20. dtlpy/assets/service_runners/multi_method_item.py +52 -52
  21. dtlpy/assets/service_runners/multi_method_json.py +52 -52
  22. dtlpy/assets/service_runners/single_method.py +37 -37
  23. dtlpy/assets/service_runners/single_method_annotation.py +43 -43
  24. dtlpy/assets/service_runners/single_method_dataset.py +43 -43
  25. dtlpy/assets/service_runners/single_method_item.py +41 -41
  26. dtlpy/assets/service_runners/single_method_json.py +42 -42
  27. dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
  28. dtlpy/assets/voc_annotation_template.xml +23 -23
  29. dtlpy/caches/base_cache.py +32 -32
  30. dtlpy/caches/cache.py +473 -473
  31. dtlpy/caches/dl_cache.py +201 -201
  32. dtlpy/caches/filesystem_cache.py +89 -89
  33. dtlpy/caches/redis_cache.py +84 -84
  34. dtlpy/dlp/__init__.py +20 -20
  35. dtlpy/dlp/cli_utilities.py +367 -367
  36. dtlpy/dlp/command_executor.py +764 -764
  37. dtlpy/dlp/dlp +1 -1
  38. dtlpy/dlp/dlp.bat +1 -1
  39. dtlpy/dlp/dlp.py +128 -128
  40. dtlpy/dlp/parser.py +651 -651
  41. dtlpy/entities/__init__.py +83 -83
  42. dtlpy/entities/analytic.py +347 -311
  43. dtlpy/entities/annotation.py +1879 -1879
  44. dtlpy/entities/annotation_collection.py +699 -699
  45. dtlpy/entities/annotation_definitions/__init__.py +20 -20
  46. dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
  47. dtlpy/entities/annotation_definitions/box.py +195 -195
  48. dtlpy/entities/annotation_definitions/classification.py +67 -67
  49. dtlpy/entities/annotation_definitions/comparison.py +72 -72
  50. dtlpy/entities/annotation_definitions/cube.py +204 -204
  51. dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
  52. dtlpy/entities/annotation_definitions/description.py +32 -32
  53. dtlpy/entities/annotation_definitions/ellipse.py +124 -124
  54. dtlpy/entities/annotation_definitions/free_text.py +62 -62
  55. dtlpy/entities/annotation_definitions/gis.py +69 -69
  56. dtlpy/entities/annotation_definitions/note.py +139 -139
  57. dtlpy/entities/annotation_definitions/point.py +117 -117
  58. dtlpy/entities/annotation_definitions/polygon.py +182 -182
  59. dtlpy/entities/annotation_definitions/polyline.py +111 -111
  60. dtlpy/entities/annotation_definitions/pose.py +92 -92
  61. dtlpy/entities/annotation_definitions/ref_image.py +86 -86
  62. dtlpy/entities/annotation_definitions/segmentation.py +240 -240
  63. dtlpy/entities/annotation_definitions/subtitle.py +34 -34
  64. dtlpy/entities/annotation_definitions/text.py +85 -85
  65. dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
  66. dtlpy/entities/app.py +220 -220
  67. dtlpy/entities/app_module.py +107 -107
  68. dtlpy/entities/artifact.py +174 -174
  69. dtlpy/entities/assignment.py +399 -399
  70. dtlpy/entities/base_entity.py +214 -214
  71. dtlpy/entities/bot.py +113 -113
  72. dtlpy/entities/codebase.py +292 -296
  73. dtlpy/entities/collection.py +38 -38
  74. dtlpy/entities/command.py +169 -169
  75. dtlpy/entities/compute.py +449 -442
  76. dtlpy/entities/dataset.py +1299 -1285
  77. dtlpy/entities/directory_tree.py +44 -44
  78. dtlpy/entities/dpk.py +470 -470
  79. dtlpy/entities/driver.py +235 -223
  80. dtlpy/entities/execution.py +397 -397
  81. dtlpy/entities/feature.py +124 -124
  82. dtlpy/entities/feature_set.py +145 -145
  83. dtlpy/entities/filters.py +798 -645
  84. dtlpy/entities/gis_item.py +107 -107
  85. dtlpy/entities/integration.py +184 -184
  86. dtlpy/entities/item.py +959 -953
  87. dtlpy/entities/label.py +123 -123
  88. dtlpy/entities/links.py +85 -85
  89. dtlpy/entities/message.py +175 -175
  90. dtlpy/entities/model.py +684 -684
  91. dtlpy/entities/node.py +1005 -1005
  92. dtlpy/entities/ontology.py +810 -803
  93. dtlpy/entities/organization.py +287 -287
  94. dtlpy/entities/package.py +657 -657
  95. dtlpy/entities/package_defaults.py +5 -5
  96. dtlpy/entities/package_function.py +185 -185
  97. dtlpy/entities/package_module.py +113 -113
  98. dtlpy/entities/package_slot.py +118 -118
  99. dtlpy/entities/paged_entities.py +299 -299
  100. dtlpy/entities/pipeline.py +624 -624
  101. dtlpy/entities/pipeline_execution.py +279 -279
  102. dtlpy/entities/project.py +394 -394
  103. dtlpy/entities/prompt_item.py +505 -499
  104. dtlpy/entities/recipe.py +301 -301
  105. dtlpy/entities/reflect_dict.py +102 -102
  106. dtlpy/entities/resource_execution.py +138 -138
  107. dtlpy/entities/service.py +963 -958
  108. dtlpy/entities/service_driver.py +117 -117
  109. dtlpy/entities/setting.py +294 -294
  110. dtlpy/entities/task.py +495 -495
  111. dtlpy/entities/time_series.py +143 -143
  112. dtlpy/entities/trigger.py +426 -426
  113. dtlpy/entities/user.py +118 -118
  114. dtlpy/entities/webhook.py +124 -124
  115. dtlpy/examples/__init__.py +19 -19
  116. dtlpy/examples/add_labels.py +135 -135
  117. dtlpy/examples/add_metadata_to_item.py +21 -21
  118. dtlpy/examples/annotate_items_using_model.py +65 -65
  119. dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
  120. dtlpy/examples/annotations_convert_to_voc.py +9 -9
  121. dtlpy/examples/annotations_convert_to_yolo.py +9 -9
  122. dtlpy/examples/convert_annotation_types.py +51 -51
  123. dtlpy/examples/converter.py +143 -143
  124. dtlpy/examples/copy_annotations.py +22 -22
  125. dtlpy/examples/copy_folder.py +31 -31
  126. dtlpy/examples/create_annotations.py +51 -51
  127. dtlpy/examples/create_video_annotations.py +83 -83
  128. dtlpy/examples/delete_annotations.py +26 -26
  129. dtlpy/examples/filters.py +113 -113
  130. dtlpy/examples/move_item.py +23 -23
  131. dtlpy/examples/play_video_annotation.py +13 -13
  132. dtlpy/examples/show_item_and_mask.py +53 -53
  133. dtlpy/examples/triggers.py +49 -49
  134. dtlpy/examples/upload_batch_of_items.py +20 -20
  135. dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
  136. dtlpy/examples/upload_items_with_modalities.py +43 -43
  137. dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
  138. dtlpy/examples/upload_yolo_format_annotations.py +70 -70
  139. dtlpy/exceptions.py +125 -125
  140. dtlpy/miscellaneous/__init__.py +20 -20
  141. dtlpy/miscellaneous/dict_differ.py +95 -95
  142. dtlpy/miscellaneous/git_utils.py +217 -217
  143. dtlpy/miscellaneous/json_utils.py +14 -14
  144. dtlpy/miscellaneous/list_print.py +105 -105
  145. dtlpy/miscellaneous/zipping.py +130 -130
  146. dtlpy/ml/__init__.py +20 -20
  147. dtlpy/ml/base_feature_extractor_adapter.py +27 -27
  148. dtlpy/ml/base_model_adapter.py +1257 -1086
  149. dtlpy/ml/metrics.py +461 -461
  150. dtlpy/ml/predictions_utils.py +274 -274
  151. dtlpy/ml/summary_writer.py +57 -57
  152. dtlpy/ml/train_utils.py +60 -60
  153. dtlpy/new_instance.py +252 -252
  154. dtlpy/repositories/__init__.py +56 -56
  155. dtlpy/repositories/analytics.py +85 -85
  156. dtlpy/repositories/annotations.py +916 -916
  157. dtlpy/repositories/apps.py +383 -383
  158. dtlpy/repositories/artifacts.py +452 -452
  159. dtlpy/repositories/assignments.py +599 -599
  160. dtlpy/repositories/bots.py +213 -213
  161. dtlpy/repositories/codebases.py +559 -559
  162. dtlpy/repositories/collections.py +332 -332
  163. dtlpy/repositories/commands.py +152 -158
  164. dtlpy/repositories/compositions.py +61 -61
  165. dtlpy/repositories/computes.py +439 -435
  166. dtlpy/repositories/datasets.py +1504 -1291
  167. dtlpy/repositories/downloader.py +976 -903
  168. dtlpy/repositories/dpks.py +433 -433
  169. dtlpy/repositories/drivers.py +482 -470
  170. dtlpy/repositories/executions.py +815 -817
  171. dtlpy/repositories/feature_sets.py +226 -226
  172. dtlpy/repositories/features.py +255 -238
  173. dtlpy/repositories/integrations.py +484 -484
  174. dtlpy/repositories/items.py +912 -909
  175. dtlpy/repositories/messages.py +94 -94
  176. dtlpy/repositories/models.py +1000 -988
  177. dtlpy/repositories/nodes.py +80 -80
  178. dtlpy/repositories/ontologies.py +511 -511
  179. dtlpy/repositories/organizations.py +525 -525
  180. dtlpy/repositories/packages.py +1941 -1941
  181. dtlpy/repositories/pipeline_executions.py +451 -451
  182. dtlpy/repositories/pipelines.py +640 -640
  183. dtlpy/repositories/projects.py +539 -539
  184. dtlpy/repositories/recipes.py +419 -399
  185. dtlpy/repositories/resource_executions.py +137 -137
  186. dtlpy/repositories/schema.py +120 -120
  187. dtlpy/repositories/service_drivers.py +213 -213
  188. dtlpy/repositories/services.py +1704 -1704
  189. dtlpy/repositories/settings.py +339 -339
  190. dtlpy/repositories/tasks.py +1477 -1477
  191. dtlpy/repositories/times_series.py +278 -278
  192. dtlpy/repositories/triggers.py +536 -536
  193. dtlpy/repositories/upload_element.py +257 -257
  194. dtlpy/repositories/uploader.py +661 -651
  195. dtlpy/repositories/webhooks.py +249 -249
  196. dtlpy/services/__init__.py +22 -22
  197. dtlpy/services/aihttp_retry.py +131 -131
  198. dtlpy/services/api_client.py +1785 -1782
  199. dtlpy/services/api_reference.py +40 -40
  200. dtlpy/services/async_utils.py +133 -133
  201. dtlpy/services/calls_counter.py +44 -44
  202. dtlpy/services/check_sdk.py +68 -68
  203. dtlpy/services/cookie.py +115 -115
  204. dtlpy/services/create_logger.py +156 -156
  205. dtlpy/services/events.py +84 -84
  206. dtlpy/services/logins.py +235 -235
  207. dtlpy/services/reporter.py +256 -256
  208. dtlpy/services/service_defaults.py +91 -91
  209. dtlpy/utilities/__init__.py +20 -20
  210. dtlpy/utilities/annotations/__init__.py +16 -16
  211. dtlpy/utilities/annotations/annotation_converters.py +269 -269
  212. dtlpy/utilities/base_package_runner.py +285 -264
  213. dtlpy/utilities/converter.py +1650 -1650
  214. dtlpy/utilities/dataset_generators/__init__.py +1 -1
  215. dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
  216. dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
  217. dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
  218. dtlpy/utilities/local_development/__init__.py +1 -1
  219. dtlpy/utilities/local_development/local_session.py +179 -179
  220. dtlpy/utilities/reports/__init__.py +2 -2
  221. dtlpy/utilities/reports/figures.py +343 -343
  222. dtlpy/utilities/reports/report.py +71 -71
  223. dtlpy/utilities/videos/__init__.py +17 -17
  224. dtlpy/utilities/videos/video_player.py +598 -598
  225. dtlpy/utilities/videos/videos.py +470 -470
  226. {dtlpy-1.114.17.data → dtlpy-1.116.6.data}/scripts/dlp +1 -1
  227. dtlpy-1.116.6.data/scripts/dlp.bat +2 -0
  228. {dtlpy-1.114.17.data → dtlpy-1.116.6.data}/scripts/dlp.py +128 -128
  229. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/METADATA +186 -183
  230. dtlpy-1.116.6.dist-info/RECORD +239 -0
  231. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/WHEEL +1 -1
  232. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/licenses/LICENSE +200 -200
  233. tests/features/environment.py +551 -551
  234. dtlpy/assets/__pycache__/__init__.cpython-310.pyc +0 -0
  235. dtlpy-1.114.17.data/scripts/dlp.bat +0 -2
  236. dtlpy-1.114.17.dist-info/RECORD +0 -240
  237. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/entry_points.txt +0 -0
  238. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/top_level.txt +0 -0
@@ -1,470 +1,482 @@
1
- import logging
2
- import re
3
-
4
- from .. import entities, miscellaneous, exceptions, _api_reference
5
- from ..services.api_client import ApiClient
6
-
7
- logger = logging.getLogger(name="dtlpy")
8
-
9
-
10
- class Drivers:
11
- """
12
- Drivers Repository
13
-
14
- The Drivers class allows users to manage drivers that are used to connect with external storage.
15
- Read more about external storage in our `documentation <https://dataloop.ai/docs/overview-1>`_ and `developers' docs <https://developers.dataloop.ai/tutorials/data_management/>`_.
16
- """
17
-
18
- def __init__(self, client_api: ApiClient, project: entities.Project = None):
19
- """
20
- Initialize the Drivers repository.
21
-
22
- :param ApiClient client_api: The API client instance
23
- :param Project project: Optional project entity. If not provided, will try to get from checkout
24
- """
25
- self._client_api = client_api
26
- self._project = project
27
-
28
- ############
29
- # entities #
30
- ############
31
- @property
32
- def project(self) -> entities.Project:
33
- if self._project is None:
34
- # try get checkout
35
- project = self._client_api.state_io.get("project")
36
- if project is not None:
37
- self._project = entities.Project.from_json(_json=project, client_api=self._client_api)
38
- if self._project is None:
39
- raise exceptions.PlatformException(
40
- error="2001",
41
- message="Cannot perform action WITHOUT Project entity in Drivers repository."
42
- " Please checkout or set a project",
43
- )
44
- assert isinstance(self._project, entities.Project)
45
- return self._project
46
-
47
- @project.setter
48
- def project(self, project: entities.Project):
49
- """
50
- Set the project for this Drivers repository.
51
-
52
- :param Project project: The project entity to set
53
- :raises ValueError: If the provided project is not a valid Project entity
54
- """
55
- if not isinstance(project, entities.Project):
56
- raise ValueError("Must input a valid Project entity")
57
- self._project = project
58
-
59
- ###########
60
- # methods #
61
- ###########
62
- def __get_by_id(self, driver_id) -> entities.Driver:
63
- """
64
- Get a driver by its ID from the platform.
65
-
66
- :param str driver_id: The driver ID
67
- :return: Driver object
68
- :rtype: dtlpy.entities.driver.Driver
69
- :raises PlatformException: If the driver is not found or there's an API error
70
- """
71
- success, response = self._client_api.gen_request(req_type="get", path="/drivers/{}".format(driver_id))
72
- if success:
73
- _json = response.json()
74
- driver = self._getDriverClass(_json).from_json(client_api=self._client_api, _json=_json)
75
- else:
76
- raise exceptions.PlatformException(response)
77
- return driver
78
-
79
- @_api_reference.add(path="/drivers", method="get")
80
- def list(self) -> miscellaneous.List[entities.Driver]:
81
- """
82
- Get the project's drivers list.
83
-
84
- **Prerequisites**: You must be in the role of an *owner* or *developer*.
85
-
86
- :return: List of Drivers objects
87
- :rtype: list
88
-
89
- **Example**:
90
-
91
- .. code-block:: python
92
-
93
- project.drivers.list()
94
-
95
- """
96
-
97
- success, response = self._client_api.gen_request(
98
- req_type="get", path="/drivers?projectId={}".format(self.project.id)
99
- )
100
- if not success:
101
- raise exceptions.PlatformException(response)
102
- drivers = miscellaneous.List(
103
- [
104
- self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
105
- for _json in response.json()
106
- ]
107
- )
108
- return drivers
109
-
110
- def _getDriverClass(self, _json):
111
- """
112
- Determine the appropriate driver class based on the driver type in the JSON response.
113
-
114
- :param dict _json: The JSON response containing driver information
115
- :return: The appropriate driver class (S3Driver, GcsDriver, AzureBlobDriver, or Driver)
116
- :rtype: type
117
- """
118
- driver_type = _json.get("type", None)
119
- if driver_type == entities.ExternalStorage.S3:
120
- driver_class = entities.S3Driver
121
- elif driver_type == entities.ExternalStorage.GCS:
122
- driver_class = entities.GcsDriver
123
- elif driver_type in [entities.ExternalStorage.AZUREBLOB, entities.ExternalStorage.AZURE_DATALAKE_GEN2]:
124
- driver_class = entities.AzureBlobDriver
125
- else:
126
- driver_class = entities.Driver
127
- return driver_class
128
-
129
- @_api_reference.add(path="/drivers/{id}", method="get")
130
- def get(self, driver_name: str = None, driver_id: str = None) -> entities.Driver:
131
- """
132
- Get a Driver object to use in your code.
133
-
134
- **Prerequisites**: You must be in the role of an *owner* or *developer*.
135
-
136
- You must provide at least ONE of the following params: driver_name, driver_id.
137
-
138
- :param str driver_name: optional - search by name
139
- :param str driver_id: optional - search by id
140
- :return: Driver object
141
- :rtype: dtlpy.entities.driver.Driver
142
-
143
- **Example**:
144
-
145
- .. code-block:: python
146
-
147
- project.drivers.get(driver_id='driver_id')
148
- """
149
- if driver_id is not None:
150
- driver = self.__get_by_id(driver_id)
151
- elif driver_name is not None:
152
- drivers = self.list()
153
- driver = [driver for driver in drivers if driver.name == driver_name]
154
- if not driver:
155
- # list is empty
156
- raise exceptions.PlatformException(
157
- error="404", message="Driver not found. Name: {}".format(driver_name)
158
- )
159
- # driver = None
160
- elif len(driver) > 1:
161
- # more than one matching driver
162
- raise exceptions.PlatformException(
163
- error="404", message='More than one driver with same name. Please "get" by id'
164
- )
165
- else:
166
- driver = driver[0]
167
- else:
168
- raise exceptions.PlatformException(error="400", message="Must provide an identifier (name or id) in inputs")
169
- return driver
170
-
171
- @_api_reference.add(path="/drivers", method="post")
172
- def _create_driver(self, payload: dict):
173
- """
174
- Create a driver on the platform using the provided payload.
175
-
176
- :param dict payload: The driver creation payload
177
- :return: The created driver object
178
- :rtype: dtlpy.entities.driver.Driver
179
- :raises PlatformException: If the driver creation fails
180
- """
181
- success, response = self._client_api.gen_request(req_type="post", path="/drivers", json_req=payload)
182
- if not success:
183
- raise exceptions.PlatformException(response)
184
- else:
185
- _json = response.json()
186
- return self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
187
-
188
- def create_powerscale_s3(
189
- self,
190
- name: str,
191
- integration: entities.Integration,
192
- elastic_index: str,
193
- endpoint: str,
194
- bucket_name: str,
195
- region: str,
196
- elastic_index_path: str,
197
- path: str = None,
198
- project_id: str = None,
199
- allow_external_delete: bool = False
200
- ):
201
- """
202
- Create a PowerScale S3 driver.
203
-
204
- **Prerequisites**: You must be in the role of an *owner* or *developer*.
205
-
206
- :param str name: The driver name
207
- :param Integration integration: The S3 integration to use
208
- :param str elastic_index: The elastic index for PowerScale S3 driver
209
- :param str project_id: Optional project ID. If not provided, uses the current project
210
- :param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
211
- :param str endpoint: The endpoint URL. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'
212
- :param str bucket_name: The external bucket name
213
- :param str region: The bucket region (relevant for S3)
214
- :param str elastic_index_path: The elastic index path for PowerScale S3 driver
215
- :param str path: The path to the NFS driver
216
- :return: The created PowerScale S3 driver object
217
- :rtype: dtlpy.entities.driver.Driver
218
- :raises ValueError: If the integration type is not S3
219
- :raises PlatformException: If the driver creation fails
220
-
221
- **Example**:
222
-
223
- .. code-block:: python
224
-
225
- project.drivers.create_powerscale_s3(
226
- name='powerscale_driver',
227
- integration=integration,
228
- elastic_index='my_index',
229
- elastic_index_path='my_index_path',
230
- endpoint='http://location:8765',
231
- bucket_name='my_bucket',
232
- region='us-west-1',
233
- path='my_path'
234
- )
235
- """
236
- if not integration.type == entities.IntegrationType.S3:
237
- raise ValueError("Integration type must be S3 for PowerScale S3 driver")
238
-
239
- payload = {
240
- "integrationId": integration.id,
241
- "integrationType": integration.type,
242
- "name": name,
243
- "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
244
- "type": entities.ExternalStorage.POWERSCALE_S3,
245
- "payload": {
246
- "elasticIndex": elastic_index,
247
- "endpoint": endpoint,
248
- "path": path,
249
- "elasticIndexPath": elastic_index_path,
250
- "bucketName": bucket_name,
251
- "region": region
252
- },
253
- "allowExternalDelete": allow_external_delete,
254
- "creator": self._client_api.info().get("user_email"),
255
- }
256
- return self._create_driver(payload)
257
-
258
-
259
- def create_powerscale_nfs(
260
- self,
261
- name: str,
262
- elastic_index: str,
263
- elastic_index_path: str,
264
- project_id: str = None,
265
- allow_external_delete: bool = False
266
- ):
267
- """
268
- Create a PowerScale NFS driver.
269
-
270
- **Prerequisites**: You must be in the role of an *owner* or *developer*.
271
-
272
- :param str name: The driver name
273
- :param str elastic_index: The elastic index for PowerScale NFS driver
274
- :param str project_id: Optional project ID. If not provided, uses the current project
275
- :param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
276
- :param str elastic_index_path: The elastic index path for PowerScale NFS driver
277
- :return: The created PowerScale NFS driver object
278
- :rtype: dtlpy.entities.driver.Driver
279
- :raises PlatformException: If the driver creation fails
280
-
281
- **Example**:
282
-
283
- .. code-block:: python
284
-
285
- project.drivers.create_powerscale_nfs(
286
- name='powerscale_driver',
287
- elastic_index='my_index',
288
- elastic_index_path='my_index_path',
289
- )
290
- """
291
-
292
- payload = {
293
- "name": name,
294
- "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
295
- "type": entities.ExternalStorage.POWERSCALE_NFS,
296
- "payload": {"elasticIndex": elastic_index, "elasticIndexPath": elastic_index_path},
297
- "allowExternalDelete": allow_external_delete,
298
- "creator": self._client_api.info().get("user_email"),
299
- }
300
- return self._create_driver(payload)
301
-
302
- def create_min_io(
303
- self,
304
- name: str,
305
- integration: entities.Integration,
306
- bucket_name: str,
307
- endpoint: str,
308
- project_id: str = None,
309
- allow_external_delete: bool = True,
310
- region: str = None,
311
- storage_class: str = "",
312
- path: str = "",
313
- ):
314
- """
315
- Create a MinIO driver.
316
-
317
- **Prerequisites**: You must be in the role of an *owner* or *developer*.
318
-
319
- :param str name: The driver name
320
- :param Integration integration: The S3 integration to use
321
- :param str bucket_name: The external bucket name
322
- :param str endpoint: The MinIO endpoint URL. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'
323
- :param str project_id: Optional project ID. If not provided, uses the current project
324
- :param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
325
- :param str region: The bucket region (relevant for S3)
326
- :param str storage_class: The storage class (relevant for S3)
327
- :param str path: Optional path. By default path is the root folder. Path is case sensitive
328
- :return: The created MinIO driver object
329
- :rtype: dtlpy.entities.driver.Driver
330
- :raises ValueError: If the integration type is not S3 or if the endpoint URL format is invalid
331
- :raises PlatformException: If the driver creation fails
332
-
333
- **Example**:
334
-
335
- .. code-block:: python
336
-
337
- project.drivers.create_min_io(
338
- name='minio_driver',
339
- integration=integration,
340
- bucket_name='my_bucket',
341
- endpoint='http://localhost:9000'
342
- )
343
- """
344
- if not integration.type == entities.IntegrationType.S3:
345
- raise ValueError("Integration type must be S3 for Minio driver")
346
-
347
- if not re.match(r"^https?://[A-Za-z0-9.-]+:\d+$", endpoint):
348
- raise ValueError(
349
- f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
350
- )
351
-
352
- payload = {
353
- "integrationId": integration.id,
354
- "integrationType": integration.type,
355
- "name": name,
356
- "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
357
- "type": entities.ExternalStorage.MIN_IO,
358
- "payload": {"bucketName": bucket_name, "storageClass": storage_class, "region": region, "path": path, "endpoint": endpoint},
359
- "allowExternalDelete": allow_external_delete,
360
- "creator": self._client_api.info().get("user_email"),
361
- }
362
-
363
- return self._create_driver(payload)
364
-
365
-
366
- def create(
367
- self,
368
- name: str,
369
- driver_type: entities.ExternalStorage,
370
- integration_id: str,
371
- bucket_name: str,
372
- integration_type: entities.IntegrationType,
373
- project_id: str = None,
374
- allow_external_delete: bool = True,
375
- region: str = None,
376
- storage_class: str = "",
377
- path: str = "",
378
- endpoint: str = None
379
- ):
380
- """
381
- Create a storage driver.
382
-
383
- **Prerequisites**: You must be in the role of an *owner* or *developer*.
384
-
385
- :param str name: the driver name
386
- :param ExternalStorage driver_type: dl.ExternalStorage (Enum). For all options run: list(dl.ExsternalStorage)
387
- :param str integration_id: the integration id
388
- :param str bucket_name: the external bucket name
389
- :param IntegrationType integration_type: dl.IntegrationType (Enum). For all options run: list(dl.IntegrationType)
390
- :param str project_id: project id
391
- :param bool allow_external_delete: true to allow deleting files from external storage when files are deleted in your Dataloop storage
392
- :param str region: relevant only for s3 - the bucket region
393
- :param str storage_class: relevant only for s3
394
- :param str path: Optional. By default path is the root folder. Path is case sensitive integration
395
- :param str endpoint: Optional. Custom endpoint for minio storage. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'.
396
- :return: driver object
397
- :rtype: dtlpy.entities.driver.Driver
398
-
399
- **Example**:
400
-
401
- .. code-block:: python
402
-
403
- project.drivers.create(name='driver_name',
404
- driver_type=dl.ExternalStorage.S3,
405
- integration_id='integration_id',
406
- bucket_name='bucket_name',
407
- project_id='project_id',
408
- region='ey-west-1')
409
- """
410
- if integration_type is None:
411
- integration_type = driver_type
412
- if driver_type == entities.ExternalStorage.S3:
413
- bucket_payload = "bucketName"
414
- if endpoint:
415
- if not re.match(r"^https?://[A-Za-z0-9.-]+:\d+$", endpoint):
416
- raise ValueError(
417
- f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
418
- )
419
-
420
- elif driver_type == entities.ExternalStorage.GCS:
421
- bucket_payload = "bucket"
422
- else:
423
- bucket_payload = "containerName"
424
- payload = {
425
- "integrationId": integration_id,
426
- "integrationType": integration_type,
427
- "name": name,
428
- "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
429
- "type": driver_type,
430
- "payload": {bucket_payload: bucket_name, "storageClass": storage_class, "region": region, "path": path},
431
- "allowExternalDelete": allow_external_delete,
432
- "creator": self._client_api.info().get("user_email"),
433
- }
434
-
435
- if endpoint and driver_type == entities.ExternalStorage.S3:
436
- payload["payload"]["endpoint"] = endpoint
437
-
438
- return self._create_driver(payload)
439
-
440
- @_api_reference.add(path="/drivers/{id}", method="delete")
441
- def delete(self, driver_name: str = None, driver_id: str = None, sure: bool = False, really: bool = False):
442
- """
443
- Delete a driver forever!
444
-
445
- **Prerequisites**: You must be an *owner* or *developer* to use this method.
446
-
447
- **Example**:
448
-
449
- .. code-block:: python
450
-
451
- project.drivers.delete(dataset_id='dataset_id', sure=True, really=True)
452
-
453
- :param str driver_name: optional - search by name
454
- :param str driver_id: optional - search by id
455
- :param bool sure: Are you sure you want to delete?
456
- :param bool really: Really really sure?
457
- :return: True if success
458
- :rtype: bool
459
- """
460
- if sure and really:
461
- driver = self.get(driver_name=driver_name, driver_id=driver_id)
462
- success, response = self._client_api.gen_request(req_type="delete", path="/drivers/{}".format(driver.id))
463
- if not success:
464
- raise exceptions.PlatformException(response)
465
- logger.info("Driver {!r} was deleted successfully".format(driver.name))
466
- return True
467
- else:
468
- raise exceptions.PlatformException(
469
- error="403", message="Cant delete driver from SDK. Please login to platform to delete"
470
- )
1
+ import logging
2
+ import re
3
+
4
+ from .. import entities, miscellaneous, exceptions, _api_reference
5
+ from ..services.api_client import ApiClient
6
+
7
+ logger = logging.getLogger(name="dtlpy")
8
+
9
+
10
+ class Drivers:
11
+ """
12
+ Drivers Repository
13
+
14
+ The Drivers class allows users to manage drivers that are used to connect with external storage.
15
+ Read more about external storage in our `documentation <https://dataloop.ai/docs/overview-1>`_ and `developers' docs <https://developers.dataloop.ai/tutorials/data_management/>`_.
16
+ """
17
+
18
+ def __init__(self, client_api: ApiClient, project: entities.Project = None):
19
+ """
20
+ Initialize the Drivers repository.
21
+
22
+ :param ApiClient client_api: The API client instance
23
+ :param Project project: Optional project entity. If not provided, will try to get from checkout
24
+ """
25
+ self._client_api = client_api
26
+ self._project = project
27
+
28
+ ############
29
+ # entities #
30
+ ############
31
+ @property
32
+ def project(self) -> entities.Project:
33
+ if self._project is None:
34
+ # try get checkout
35
+ project = self._client_api.state_io.get("project")
36
+ if project is not None:
37
+ self._project = entities.Project.from_json(_json=project, client_api=self._client_api)
38
+ if self._project is None:
39
+ raise exceptions.PlatformException(
40
+ error="2001",
41
+ message="Cannot perform action WITHOUT Project entity in Drivers repository."
42
+ " Please checkout or set a project",
43
+ )
44
+ assert isinstance(self._project, entities.Project)
45
+ return self._project
46
+
47
+ @project.setter
48
+ def project(self, project: entities.Project):
49
+ """
50
+ Set the project for this Drivers repository.
51
+
52
+ :param Project project: The project entity to set
53
+ :raises ValueError: If the provided project is not a valid Project entity
54
+ """
55
+ if not isinstance(project, entities.Project):
56
+ raise ValueError("Must input a valid Project entity")
57
+ self._project = project
58
+
59
+ ###########
60
+ # methods #
61
+ ###########
62
+ def __get_by_id(self, driver_id) -> entities.Driver:
63
+ """
64
+ Get a driver by its ID from the platform.
65
+
66
+ :param str driver_id: The driver ID
67
+ :return: Driver object
68
+ :rtype: dtlpy.entities.driver.Driver
69
+ :raises PlatformException: If the driver is not found or there's an API error
70
+ """
71
+ success, response = self._client_api.gen_request(req_type="get", path="/drivers/{}".format(driver_id))
72
+ if success:
73
+ _json = response.json()
74
+ driver = self._getDriverClass(_json).from_json(client_api=self._client_api, _json=_json)
75
+ else:
76
+ raise exceptions.PlatformException(response)
77
+ return driver
78
+
79
+ @_api_reference.add(path="/drivers", method="get")
80
+ def list(self) -> miscellaneous.List[entities.Driver]:
81
+ """
82
+ Get the project's drivers list.
83
+
84
+ **Prerequisites**: You must be in the role of an *owner* or *developer*.
85
+
86
+ :return: List of Drivers objects
87
+ :rtype: list
88
+
89
+ **Example**:
90
+
91
+ .. code-block:: python
92
+
93
+ project.drivers.list()
94
+
95
+ """
96
+
97
+ success, response = self._client_api.gen_request(
98
+ req_type="get", path="/drivers?projectId={}".format(self.project.id)
99
+ )
100
+ if not success:
101
+ raise exceptions.PlatformException(response)
102
+ drivers = miscellaneous.List(
103
+ [
104
+ self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
105
+ for _json in response.json()
106
+ ]
107
+ )
108
+ return drivers
109
+
110
+ def _getDriverClass(self, _json):
111
+ """
112
+ Determine the appropriate driver class based on the driver type in the JSON response.
113
+
114
+ :param dict _json: The JSON response containing driver information
115
+ :return: The appropriate driver class (S3Driver, GcsDriver, AzureBlobDriver, or Driver)
116
+ :rtype: type
117
+ """
118
+ driver_type = _json.get("type", None)
119
+ if driver_type == entities.ExternalStorage.S3:
120
+ driver_class = entities.S3Driver
121
+ elif driver_type == entities.ExternalStorage.GCS:
122
+ driver_class = entities.GcsDriver
123
+ elif driver_type in [entities.ExternalStorage.AZUREBLOB, entities.ExternalStorage.AZURE_DATALAKE_GEN2]:
124
+ driver_class = entities.AzureBlobDriver
125
+ else:
126
+ driver_class = entities.Driver
127
+ return driver_class
128
+
129
+ @_api_reference.add(path="/drivers/{id}", method="get")
130
+ def get(self, driver_name: str = None, driver_id: str = None) -> entities.Driver:
131
+ """
132
+ Get a Driver object to use in your code.
133
+
134
+ **Prerequisites**: You must be in the role of an *owner* or *developer*.
135
+
136
+ You must provide at least ONE of the following params: driver_name, driver_id.
137
+
138
+ :param str driver_name: optional - search by name
139
+ :param str driver_id: optional - search by id
140
+ :return: Driver object
141
+ :rtype: dtlpy.entities.driver.Driver
142
+
143
+ **Example**:
144
+
145
+ .. code-block:: python
146
+
147
+ project.drivers.get(driver_id='driver_id')
148
+ """
149
+ if driver_id is not None:
150
+ driver = self.__get_by_id(driver_id)
151
+ elif driver_name is not None:
152
+ drivers = self.list()
153
+ driver = [driver for driver in drivers if driver.name == driver_name]
154
+ if not driver:
155
+ # list is empty
156
+ raise exceptions.PlatformException(
157
+ error="404", message="Driver not found. Name: {}".format(driver_name)
158
+ )
159
+ # driver = None
160
+ elif len(driver) > 1:
161
+ # more than one matching driver
162
+ raise exceptions.PlatformException(
163
+ error="404", message='More than one driver with same name. Please "get" by id'
164
+ )
165
+ else:
166
+ driver = driver[0]
167
+ else:
168
+ raise exceptions.PlatformException(error="400", message="Must provide an identifier (name or id) in inputs")
169
+ return driver
170
+
171
+ @_api_reference.add(path="/drivers", method="post")
172
+ def _create_driver(self, payload: dict):
173
+ """
174
+ Create a driver on the platform using the provided payload.
175
+
176
+ :param dict payload: The driver creation payload
177
+ :return: The created driver object
178
+ :rtype: dtlpy.entities.driver.Driver
179
+ :raises PlatformException: If the driver creation fails
180
+ """
181
+ success, response = self._client_api.gen_request(req_type="post", path="/drivers", json_req=payload)
182
+ if not success:
183
+ raise exceptions.PlatformException(response)
184
+ else:
185
+ _json = response.json()
186
+ return self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
187
+
188
+ def create_powerscale_s3(
189
+ self,
190
+ name: str,
191
+ integration: entities.Integration,
192
+ elastic_index: str,
193
+ endpoint: str,
194
+ bucket_name: str,
195
+ region: str,
196
+ elastic_index_path: str,
197
+ path: str = None,
198
+ project_id: str = None,
199
+ allow_external_delete: bool = False
200
+ ):
201
+ """
202
+ Create a PowerScale S3 driver.
203
+
204
+ **Prerequisites**: You must be in the role of an *owner* or *developer*.
205
+
206
+ :param str name: The driver name
207
+ :param Integration integration: The S3 integration to use
208
+ :param str elastic_index: The elastic index for PowerScale S3 driver
209
+ :param str project_id: Optional project ID. If not provided, uses the current project
210
+ :param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
211
+ :param str endpoint: The endpoint URL. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'
212
+ :param str bucket_name: The external bucket name
213
+ :param str region: The bucket region (relevant for S3)
214
+ :param str elastic_index_path: The elastic index path for PowerScale S3 driver
215
+ :param str path: The path to the NFS driver
216
+ :return: The created PowerScale S3 driver object
217
+ :rtype: dtlpy.entities.driver.Driver
218
+ :raises ValueError: If the integration type is not S3
219
+ :raises PlatformException: If the driver creation fails
220
+
221
+ **Example**:
222
+
223
+ .. code-block:: python
224
+
225
+ project.drivers.create_powerscale_s3(
226
+ name='powerscale_driver',
227
+ integration=integration,
228
+ elastic_index='my_index',
229
+ elastic_index_path='my_index_path',
230
+ endpoint='http://location:8765',
231
+ bucket_name='my_bucket',
232
+ region='us-west-1',
233
+ path='my_path'
234
+ )
235
+ """
236
+ if not integration.type == entities.IntegrationType.S3:
237
+ raise ValueError("Integration type must be S3 for PowerScale S3 driver")
238
+
239
+ payload = {
240
+ "integrationId": integration.id,
241
+ "integrationType": integration.type,
242
+ "name": name,
243
+ "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
244
+ "type": entities.ExternalStorage.POWERSCALE_S3,
245
+ "payload": {
246
+ "elasticIndex": elastic_index,
247
+ "endpoint": endpoint,
248
+ "path": path,
249
+ "elasticIndexPath": elastic_index_path,
250
+ "bucketName": bucket_name,
251
+ "region": region
252
+ },
253
+ "allowExternalDelete": allow_external_delete,
254
+ "creator": self._client_api.info().get("user_email"),
255
+ }
256
+ return self._create_driver(payload)
257
+
258
+
259
+ def create_powerscale_nfs(
260
+ self,
261
+ name: str,
262
+ elastic_index: str,
263
+ elastic_index_path: str,
264
+ integration: entities.Integration = None,
265
+ project_id: str = None,
266
+ allow_external_delete: bool = False
267
+ ):
268
+ """
269
+ Create a PowerScale NFS driver.
270
+
271
+ **Prerequisites**: You must be in the role of an *owner* or *developer*.
272
+
273
+ :param str name: The driver name
274
+ :param str elastic_index: The elastic index for PowerScale NFS driver
275
+ :param Integration integration (optional): The S3 integration to use. If not provided, integration id will be 'system'
276
+ :param str project_id: Optional project ID. If not provided, uses the current project
277
+ :param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
278
+ :param str elastic_index_path: The elastic index path for PowerScale NFS driver
279
+ :return: The created PowerScale NFS driver object
280
+ :rtype: dtlpy.entities.driver.Driver
281
+ :raises PlatformException: If the driver creation fails
282
+
283
+ **Example**:
284
+
285
+ .. code-block:: python
286
+
287
+ project.drivers.create_powerscale_nfs(
288
+ name='powerscale_driver',
289
+ elastic_index='my_index',
290
+ elastic_index_path='my_index_path',
291
+ )
292
+ """
293
+
294
+ integration_id = 'system'
295
+ integration_type = None
296
+ if integration is not None:
297
+ if not integration.type == entities.IntegrationType.S3:
298
+ raise ValueError("Integration type must be S3 for PowerScale NFS driver")
299
+ integration_id = integration.id
300
+ integration_type = integration.type
301
+
302
+ payload = {
303
+ "integrationId": integration_id,
304
+ "integrationType": integration_type,
305
+ "name": name,
306
+ "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
307
+ "type": entities.ExternalStorage.POWERSCALE_NFS,
308
+ "payload": {"elasticIndex": elastic_index, "elasticIndexPath": elastic_index_path},
309
+ "allowExternalDelete": allow_external_delete,
310
+ "creator": self._client_api.info().get("user_email"),
311
+ }
312
+ return self._create_driver(payload)
313
+
314
+ def create_min_io(
315
+ self,
316
+ name: str,
317
+ integration: entities.Integration,
318
+ bucket_name: str,
319
+ endpoint: str,
320
+ project_id: str = None,
321
+ allow_external_delete: bool = True,
322
+ region: str = None,
323
+ storage_class: str = "",
324
+ path: str = "",
325
+ ):
326
+ """
327
+ Create a MinIO driver.
328
+
329
+ **Prerequisites**: You must be in the role of an *owner* or *developer*.
330
+
331
+ :param str name: The driver name
332
+ :param Integration integration: The S3 integration to use
333
+ :param str bucket_name: The external bucket name
334
+ :param str endpoint: The MinIO endpoint URL. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'
335
+ :param str project_id: Optional project ID. If not provided, uses the current project
336
+ :param bool allow_external_delete: True to allow deleting files from external storage when files are deleted in your Dataloop storage
337
+ :param str region: The bucket region (relevant for S3)
338
+ :param str storage_class: The storage class (relevant for S3)
339
+ :param str path: Optional path. By default path is the root folder. Path is case sensitive
340
+ :return: The created MinIO driver object
341
+ :rtype: dtlpy.entities.driver.Driver
342
+ :raises ValueError: If the integration type is not S3 or if the endpoint URL format is invalid
343
+ :raises PlatformException: If the driver creation fails
344
+
345
+ **Example**:
346
+
347
+ .. code-block:: python
348
+
349
+ project.drivers.create_min_io(
350
+ name='minio_driver',
351
+ integration=integration,
352
+ bucket_name='my_bucket',
353
+ endpoint='http://localhost:9000'
354
+ )
355
+ """
356
+ if not integration.type == entities.IntegrationType.S3:
357
+ raise ValueError("Integration type must be S3 for Minio driver")
358
+
359
+ if not re.match(r"^https?://[A-Za-z0-9.-]+:\d+$", endpoint):
360
+ raise ValueError(
361
+ f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
362
+ )
363
+
364
+ payload = {
365
+ "integrationId": integration.id,
366
+ "integrationType": integration.type,
367
+ "name": name,
368
+ "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
369
+ "type": entities.ExternalStorage.MIN_IO,
370
+ "payload": {"bucketName": bucket_name, "storageClass": storage_class, "region": region, "path": path, "endpoint": endpoint},
371
+ "allowExternalDelete": allow_external_delete,
372
+ "creator": self._client_api.info().get("user_email"),
373
+ }
374
+
375
+ return self._create_driver(payload)
376
+
377
+
378
+ def create(
379
+ self,
380
+ name: str,
381
+ driver_type: entities.ExternalStorage,
382
+ integration_id: str,
383
+ bucket_name: str,
384
+ integration_type: entities.IntegrationType,
385
+ project_id: str = None,
386
+ allow_external_delete: bool = True,
387
+ region: str = None,
388
+ storage_class: str = "",
389
+ path: str = "",
390
+ endpoint: str = None
391
+ ):
392
+ """
393
+ Create a storage driver.
394
+
395
+ **Prerequisites**: You must be in the role of an *owner* or *developer*.
396
+
397
+ :param str name: the driver name
398
+ :param ExternalStorage driver_type: dl.ExternalStorage (Enum). For all options run: list(dl.ExsternalStorage)
399
+ :param str integration_id: the integration id
400
+ :param str bucket_name: the external bucket name
401
+ :param IntegrationType integration_type: dl.IntegrationType (Enum). For all options run: list(dl.IntegrationType)
402
+ :param str project_id: project id
403
+ :param bool allow_external_delete: true to allow deleting files from external storage when files are deleted in your Dataloop storage
404
+ :param str region: relevant only for s3 - the bucket region
405
+ :param str storage_class: relevant only for s3
406
+ :param str path: Optional. By default path is the root folder. Path is case sensitive integration
407
+ :param str endpoint: Optional. Custom endpoint for minio storage. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'.
408
+ :return: driver object
409
+ :rtype: dtlpy.entities.driver.Driver
410
+
411
+ **Example**:
412
+
413
+ .. code-block:: python
414
+
415
+ project.drivers.create(name='driver_name',
416
+ driver_type=dl.ExternalStorage.S3,
417
+ integration_id='integration_id',
418
+ bucket_name='bucket_name',
419
+ project_id='project_id',
420
+ region='ey-west-1')
421
+ """
422
+ if integration_type is None:
423
+ integration_type = driver_type
424
+ if driver_type == entities.ExternalStorage.S3:
425
+ bucket_payload = "bucketName"
426
+ if endpoint:
427
+ if not re.match(r"^https?://[A-Za-z0-9.-]+:\d+$", endpoint):
428
+ raise ValueError(
429
+ f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
430
+ )
431
+
432
+ elif driver_type == entities.ExternalStorage.GCS:
433
+ bucket_payload = "bucket"
434
+ else:
435
+ bucket_payload = "containerName"
436
+ payload = {
437
+ "integrationId": integration_id,
438
+ "integrationType": integration_type,
439
+ "name": name,
440
+ "metadata": {"system": {"projectId": self.project.id if project_id is None else project_id}},
441
+ "type": driver_type,
442
+ "payload": {bucket_payload: bucket_name, "storageClass": storage_class, "region": region, "path": path},
443
+ "allowExternalDelete": allow_external_delete,
444
+ "creator": self._client_api.info().get("user_email"),
445
+ }
446
+
447
+ if endpoint and driver_type == entities.ExternalStorage.S3:
448
+ payload["payload"]["endpoint"] = endpoint
449
+
450
+ return self._create_driver(payload)
451
+
452
+ @_api_reference.add(path="/drivers/{id}", method="delete")
453
+ def delete(self, driver_name: str = None, driver_id: str = None, sure: bool = False, really: bool = False):
454
+ """
455
+ Delete a driver forever!
456
+
457
+ **Prerequisites**: You must be an *owner* or *developer* to use this method.
458
+
459
+ **Example**:
460
+
461
+ .. code-block:: python
462
+
463
+ project.drivers.delete(dataset_id='dataset_id', sure=True, really=True)
464
+
465
+ :param str driver_name: optional - search by name
466
+ :param str driver_id: optional - search by id
467
+ :param bool sure: Are you sure you want to delete?
468
+ :param bool really: Really really sure?
469
+ :return: True if success
470
+ :rtype: bool
471
+ """
472
+ if sure and really:
473
+ driver = self.get(driver_name=driver_name, driver_id=driver_id)
474
+ success, response = self._client_api.gen_request(req_type="delete", path="/drivers/{}".format(driver.id))
475
+ if not success:
476
+ raise exceptions.PlatformException(response)
477
+ logger.info("Driver {!r} was deleted successfully".format(driver.name))
478
+ return True
479
+ else:
480
+ raise exceptions.PlatformException(
481
+ error="403", message="Cant delete driver from SDK. Please login to platform to delete"
482
+ )