dtlpy 1.113.10__py3-none-any.whl → 1.114.13__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.
- dtlpy/__init__.py +488 -488
- dtlpy/__version__.py +1 -1
- dtlpy/assets/__init__.py +26 -26
- dtlpy/assets/__pycache__/__init__.cpython-38.pyc +0 -0
- dtlpy/assets/code_server/config.yaml +2 -2
- dtlpy/assets/code_server/installation.sh +24 -24
- dtlpy/assets/code_server/launch.json +13 -13
- dtlpy/assets/code_server/settings.json +2 -2
- dtlpy/assets/main.py +53 -53
- dtlpy/assets/main_partial.py +18 -18
- dtlpy/assets/mock.json +11 -11
- dtlpy/assets/model_adapter.py +83 -83
- dtlpy/assets/package.json +61 -61
- dtlpy/assets/package_catalog.json +29 -29
- dtlpy/assets/package_gitignore +307 -307
- dtlpy/assets/service_runners/__init__.py +33 -33
- dtlpy/assets/service_runners/converter.py +96 -96
- dtlpy/assets/service_runners/multi_method.py +49 -49
- dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
- dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
- dtlpy/assets/service_runners/multi_method_item.py +52 -52
- dtlpy/assets/service_runners/multi_method_json.py +52 -52
- dtlpy/assets/service_runners/single_method.py +37 -37
- dtlpy/assets/service_runners/single_method_annotation.py +43 -43
- dtlpy/assets/service_runners/single_method_dataset.py +43 -43
- dtlpy/assets/service_runners/single_method_item.py +41 -41
- dtlpy/assets/service_runners/single_method_json.py +42 -42
- dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
- dtlpy/assets/voc_annotation_template.xml +23 -23
- dtlpy/caches/base_cache.py +32 -32
- dtlpy/caches/cache.py +473 -473
- dtlpy/caches/dl_cache.py +201 -201
- dtlpy/caches/filesystem_cache.py +89 -89
- dtlpy/caches/redis_cache.py +84 -84
- dtlpy/dlp/__init__.py +20 -20
- dtlpy/dlp/cli_utilities.py +367 -367
- dtlpy/dlp/command_executor.py +764 -764
- dtlpy/dlp/dlp +1 -1
- dtlpy/dlp/dlp.bat +1 -1
- dtlpy/dlp/dlp.py +128 -128
- dtlpy/dlp/parser.py +651 -651
- dtlpy/entities/__init__.py +83 -83
- dtlpy/entities/analytic.py +311 -311
- dtlpy/entities/annotation.py +1879 -1879
- dtlpy/entities/annotation_collection.py +699 -699
- dtlpy/entities/annotation_definitions/__init__.py +20 -20
- dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
- dtlpy/entities/annotation_definitions/box.py +195 -195
- dtlpy/entities/annotation_definitions/classification.py +67 -67
- dtlpy/entities/annotation_definitions/comparison.py +72 -72
- dtlpy/entities/annotation_definitions/cube.py +204 -204
- dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
- dtlpy/entities/annotation_definitions/description.py +32 -32
- dtlpy/entities/annotation_definitions/ellipse.py +124 -124
- dtlpy/entities/annotation_definitions/free_text.py +62 -62
- dtlpy/entities/annotation_definitions/gis.py +69 -69
- dtlpy/entities/annotation_definitions/note.py +139 -139
- dtlpy/entities/annotation_definitions/point.py +117 -117
- dtlpy/entities/annotation_definitions/polygon.py +182 -182
- dtlpy/entities/annotation_definitions/polyline.py +111 -111
- dtlpy/entities/annotation_definitions/pose.py +92 -92
- dtlpy/entities/annotation_definitions/ref_image.py +86 -86
- dtlpy/entities/annotation_definitions/segmentation.py +240 -240
- dtlpy/entities/annotation_definitions/subtitle.py +34 -34
- dtlpy/entities/annotation_definitions/text.py +85 -85
- dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
- dtlpy/entities/app.py +220 -220
- dtlpy/entities/app_module.py +107 -107
- dtlpy/entities/artifact.py +174 -174
- dtlpy/entities/assignment.py +399 -399
- dtlpy/entities/base_entity.py +214 -214
- dtlpy/entities/bot.py +113 -113
- dtlpy/entities/codebase.py +296 -296
- dtlpy/entities/collection.py +38 -38
- dtlpy/entities/command.py +169 -169
- dtlpy/entities/compute.py +442 -442
- dtlpy/entities/dataset.py +1285 -1285
- dtlpy/entities/directory_tree.py +44 -44
- dtlpy/entities/dpk.py +470 -470
- dtlpy/entities/driver.py +222 -222
- dtlpy/entities/execution.py +397 -397
- dtlpy/entities/feature.py +124 -124
- dtlpy/entities/feature_set.py +145 -145
- dtlpy/entities/filters.py +641 -641
- dtlpy/entities/gis_item.py +107 -107
- dtlpy/entities/integration.py +184 -184
- dtlpy/entities/item.py +953 -953
- dtlpy/entities/label.py +123 -123
- dtlpy/entities/links.py +85 -85
- dtlpy/entities/message.py +175 -175
- dtlpy/entities/model.py +694 -691
- dtlpy/entities/node.py +1005 -1005
- dtlpy/entities/ontology.py +803 -803
- dtlpy/entities/organization.py +287 -287
- dtlpy/entities/package.py +657 -657
- dtlpy/entities/package_defaults.py +5 -5
- dtlpy/entities/package_function.py +185 -185
- dtlpy/entities/package_module.py +113 -113
- dtlpy/entities/package_slot.py +118 -118
- dtlpy/entities/paged_entities.py +290 -267
- dtlpy/entities/pipeline.py +593 -593
- dtlpy/entities/pipeline_execution.py +279 -279
- dtlpy/entities/project.py +394 -394
- dtlpy/entities/prompt_item.py +499 -499
- dtlpy/entities/recipe.py +301 -301
- dtlpy/entities/reflect_dict.py +102 -102
- dtlpy/entities/resource_execution.py +138 -138
- dtlpy/entities/service.py +958 -958
- dtlpy/entities/service_driver.py +117 -117
- dtlpy/entities/setting.py +294 -294
- dtlpy/entities/task.py +491 -491
- dtlpy/entities/time_series.py +143 -143
- dtlpy/entities/trigger.py +426 -426
- dtlpy/entities/user.py +118 -118
- dtlpy/entities/webhook.py +124 -124
- dtlpy/examples/__init__.py +19 -19
- dtlpy/examples/add_labels.py +135 -135
- dtlpy/examples/add_metadata_to_item.py +21 -21
- dtlpy/examples/annotate_items_using_model.py +65 -65
- dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
- dtlpy/examples/annotations_convert_to_voc.py +9 -9
- dtlpy/examples/annotations_convert_to_yolo.py +9 -9
- dtlpy/examples/convert_annotation_types.py +51 -51
- dtlpy/examples/converter.py +143 -143
- dtlpy/examples/copy_annotations.py +22 -22
- dtlpy/examples/copy_folder.py +31 -31
- dtlpy/examples/create_annotations.py +51 -51
- dtlpy/examples/create_video_annotations.py +83 -83
- dtlpy/examples/delete_annotations.py +26 -26
- dtlpy/examples/filters.py +113 -113
- dtlpy/examples/move_item.py +23 -23
- dtlpy/examples/play_video_annotation.py +13 -13
- dtlpy/examples/show_item_and_mask.py +53 -53
- dtlpy/examples/triggers.py +49 -49
- dtlpy/examples/upload_batch_of_items.py +20 -20
- dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
- dtlpy/examples/upload_items_with_modalities.py +43 -43
- dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
- dtlpy/examples/upload_yolo_format_annotations.py +70 -70
- dtlpy/exceptions.py +125 -125
- dtlpy/miscellaneous/__init__.py +20 -20
- dtlpy/miscellaneous/dict_differ.py +95 -95
- dtlpy/miscellaneous/git_utils.py +217 -217
- dtlpy/miscellaneous/json_utils.py +14 -14
- dtlpy/miscellaneous/list_print.py +105 -105
- dtlpy/miscellaneous/zipping.py +130 -130
- dtlpy/ml/__init__.py +20 -20
- dtlpy/ml/base_feature_extractor_adapter.py +27 -27
- dtlpy/ml/base_model_adapter.py +945 -940
- dtlpy/ml/metrics.py +461 -461
- dtlpy/ml/predictions_utils.py +274 -274
- dtlpy/ml/summary_writer.py +57 -57
- dtlpy/ml/train_utils.py +60 -60
- dtlpy/new_instance.py +252 -252
- dtlpy/repositories/__init__.py +56 -56
- dtlpy/repositories/analytics.py +85 -85
- dtlpy/repositories/annotations.py +916 -916
- dtlpy/repositories/apps.py +383 -383
- dtlpy/repositories/artifacts.py +452 -452
- dtlpy/repositories/assignments.py +599 -599
- dtlpy/repositories/bots.py +213 -213
- dtlpy/repositories/codebases.py +559 -559
- dtlpy/repositories/collections.py +332 -348
- dtlpy/repositories/commands.py +158 -158
- dtlpy/repositories/compositions.py +61 -61
- dtlpy/repositories/computes.py +434 -406
- dtlpy/repositories/datasets.py +1291 -1291
- dtlpy/repositories/downloader.py +895 -895
- dtlpy/repositories/dpks.py +433 -433
- dtlpy/repositories/drivers.py +266 -266
- dtlpy/repositories/executions.py +817 -817
- dtlpy/repositories/feature_sets.py +226 -226
- dtlpy/repositories/features.py +238 -238
- dtlpy/repositories/integrations.py +484 -484
- dtlpy/repositories/items.py +909 -915
- dtlpy/repositories/messages.py +94 -94
- dtlpy/repositories/models.py +877 -867
- dtlpy/repositories/nodes.py +80 -80
- dtlpy/repositories/ontologies.py +511 -511
- dtlpy/repositories/organizations.py +525 -525
- dtlpy/repositories/packages.py +1941 -1941
- dtlpy/repositories/pipeline_executions.py +448 -448
- dtlpy/repositories/pipelines.py +642 -642
- dtlpy/repositories/projects.py +539 -539
- dtlpy/repositories/recipes.py +399 -399
- dtlpy/repositories/resource_executions.py +137 -137
- dtlpy/repositories/schema.py +120 -120
- dtlpy/repositories/service_drivers.py +213 -213
- dtlpy/repositories/services.py +1704 -1704
- dtlpy/repositories/settings.py +339 -339
- dtlpy/repositories/tasks.py +1124 -1124
- dtlpy/repositories/times_series.py +278 -278
- dtlpy/repositories/triggers.py +536 -536
- dtlpy/repositories/upload_element.py +257 -257
- dtlpy/repositories/uploader.py +651 -651
- dtlpy/repositories/webhooks.py +249 -249
- dtlpy/services/__init__.py +22 -22
- dtlpy/services/aihttp_retry.py +131 -131
- dtlpy/services/api_client.py +1782 -1782
- dtlpy/services/api_reference.py +40 -40
- dtlpy/services/async_utils.py +133 -133
- dtlpy/services/calls_counter.py +44 -44
- dtlpy/services/check_sdk.py +68 -68
- dtlpy/services/cookie.py +115 -115
- dtlpy/services/create_logger.py +156 -156
- dtlpy/services/events.py +84 -84
- dtlpy/services/logins.py +235 -235
- dtlpy/services/reporter.py +256 -256
- dtlpy/services/service_defaults.py +91 -91
- dtlpy/utilities/__init__.py +20 -20
- dtlpy/utilities/annotations/__init__.py +16 -16
- dtlpy/utilities/annotations/annotation_converters.py +269 -269
- dtlpy/utilities/base_package_runner.py +264 -264
- dtlpy/utilities/converter.py +1650 -1650
- dtlpy/utilities/dataset_generators/__init__.py +1 -1
- dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
- dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
- dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
- dtlpy/utilities/local_development/__init__.py +1 -1
- dtlpy/utilities/local_development/local_session.py +179 -179
- dtlpy/utilities/reports/__init__.py +2 -2
- dtlpy/utilities/reports/figures.py +343 -343
- dtlpy/utilities/reports/report.py +71 -71
- dtlpy/utilities/videos/__init__.py +17 -17
- dtlpy/utilities/videos/video_player.py +598 -598
- dtlpy/utilities/videos/videos.py +470 -470
- {dtlpy-1.113.10.data → dtlpy-1.114.13.data}/scripts/dlp +1 -1
- dtlpy-1.114.13.data/scripts/dlp.bat +2 -0
- {dtlpy-1.113.10.data → dtlpy-1.114.13.data}/scripts/dlp.py +128 -128
- {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/LICENSE +200 -200
- {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/METADATA +172 -172
- dtlpy-1.114.13.dist-info/RECORD +240 -0
- {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/WHEEL +1 -1
- tests/features/environment.py +551 -550
- dtlpy-1.113.10.data/scripts/dlp.bat +0 -2
- dtlpy-1.113.10.dist-info/RECORD +0 -244
- tests/assets/__init__.py +0 -0
- tests/assets/models_flow/__init__.py +0 -0
- tests/assets/models_flow/failedmain.py +0 -52
- tests/assets/models_flow/main.py +0 -62
- tests/assets/models_flow/main_model.py +0 -54
- {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/entry_points.txt +0 -0
- {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/top_level.txt +0 -0
dtlpy/repositories/drivers.py
CHANGED
|
@@ -1,266 +1,266 @@
|
|
|
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
|
-
self._client_api = client_api
|
|
20
|
-
self._project = project
|
|
21
|
-
|
|
22
|
-
############
|
|
23
|
-
# entities #
|
|
24
|
-
############
|
|
25
|
-
@property
|
|
26
|
-
def project(self) -> entities.Project:
|
|
27
|
-
if self._project is None:
|
|
28
|
-
# try get checkout
|
|
29
|
-
project = self._client_api.state_io.get('project')
|
|
30
|
-
if project is not None:
|
|
31
|
-
self._project = entities.Project.from_json(_json=project, client_api=self._client_api)
|
|
32
|
-
if self._project is None:
|
|
33
|
-
raise exceptions.PlatformException(
|
|
34
|
-
error='2001',
|
|
35
|
-
message='Cannot perform action WITHOUT Project entity in Drivers repository.'
|
|
36
|
-
' Please checkout or set a project')
|
|
37
|
-
assert isinstance(self._project, entities.Project)
|
|
38
|
-
return self._project
|
|
39
|
-
|
|
40
|
-
@project.setter
|
|
41
|
-
def project(self, project: entities.Project):
|
|
42
|
-
if not isinstance(project, entities.Project):
|
|
43
|
-
raise ValueError('Must input a valid Project entity')
|
|
44
|
-
self._project = project
|
|
45
|
-
|
|
46
|
-
###########
|
|
47
|
-
# methods #
|
|
48
|
-
###########
|
|
49
|
-
def __get_by_id(self, driver_id) -> entities.Driver:
|
|
50
|
-
success, response = self._client_api.gen_request(req_type='get',
|
|
51
|
-
path='/drivers/{}'.format(driver_id))
|
|
52
|
-
if success:
|
|
53
|
-
_json = response.json()
|
|
54
|
-
driver = self._getDriverClass(_json).from_json(client_api=self._client_api,
|
|
55
|
-
_json=_json)
|
|
56
|
-
else:
|
|
57
|
-
raise exceptions.PlatformException(response)
|
|
58
|
-
return driver
|
|
59
|
-
|
|
60
|
-
@_api_reference.add(path='/drivers', method='get')
|
|
61
|
-
def list(self) -> miscellaneous.List[entities.Driver]:
|
|
62
|
-
"""
|
|
63
|
-
Get the project's drivers list.
|
|
64
|
-
|
|
65
|
-
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
66
|
-
|
|
67
|
-
:return: List of Drivers objects
|
|
68
|
-
:rtype: list
|
|
69
|
-
|
|
70
|
-
**Example**:
|
|
71
|
-
|
|
72
|
-
.. code-block:: python
|
|
73
|
-
|
|
74
|
-
project.drivers.list()
|
|
75
|
-
|
|
76
|
-
"""
|
|
77
|
-
|
|
78
|
-
success, response = self._client_api.gen_request(req_type='get',
|
|
79
|
-
path='/drivers?projectId={}'.format(self.project.id))
|
|
80
|
-
if not success:
|
|
81
|
-
raise exceptions.PlatformException(response)
|
|
82
|
-
drivers = miscellaneous.List([self._getDriverClass(_json).from_json(_json=_json,
|
|
83
|
-
client_api=self._client_api) for _json in
|
|
84
|
-
response.json()])
|
|
85
|
-
return drivers
|
|
86
|
-
|
|
87
|
-
def _getDriverClass(self, _json):
|
|
88
|
-
driver_type = _json.get('type', None)
|
|
89
|
-
if driver_type == entities.ExternalStorage.S3:
|
|
90
|
-
driver_class = entities.S3Driver
|
|
91
|
-
elif driver_type == entities.ExternalStorage.GCS:
|
|
92
|
-
driver_class = entities.GcsDriver
|
|
93
|
-
elif driver_type in [entities.ExternalStorage.AZUREBLOB, entities.ExternalStorage.AZURE_DATALAKE_GEN2]:
|
|
94
|
-
driver_class = entities.AzureBlobDriver
|
|
95
|
-
else:
|
|
96
|
-
driver_class = entities.Driver
|
|
97
|
-
return driver_class
|
|
98
|
-
|
|
99
|
-
@_api_reference.add(path='/drivers/{id}', method='get')
|
|
100
|
-
def get(self,
|
|
101
|
-
driver_name: str = None,
|
|
102
|
-
driver_id: str = None) -> entities.Driver:
|
|
103
|
-
"""
|
|
104
|
-
Get a Driver object to use in your code.
|
|
105
|
-
|
|
106
|
-
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
107
|
-
|
|
108
|
-
You must provide at least ONE of the following params: driver_name, driver_id.
|
|
109
|
-
|
|
110
|
-
:param str driver_name: optional - search by name
|
|
111
|
-
:param str driver_id: optional - search by id
|
|
112
|
-
:return: Driver object
|
|
113
|
-
:rtype: dtlpy.entities.driver.Driver
|
|
114
|
-
|
|
115
|
-
**Example**:
|
|
116
|
-
|
|
117
|
-
.. code-block:: python
|
|
118
|
-
|
|
119
|
-
project.drivers.get(driver_id='driver_id')
|
|
120
|
-
"""
|
|
121
|
-
if driver_id is not None:
|
|
122
|
-
driver = self.__get_by_id(driver_id)
|
|
123
|
-
elif driver_name is not None:
|
|
124
|
-
drivers = self.list()
|
|
125
|
-
driver = [driver for driver in drivers if driver.name == driver_name]
|
|
126
|
-
if not driver:
|
|
127
|
-
# list is empty
|
|
128
|
-
raise exceptions.PlatformException(error='404',
|
|
129
|
-
message='Driver not found. Name: {}'.format(driver_name))
|
|
130
|
-
# driver = None
|
|
131
|
-
elif len(driver) > 1:
|
|
132
|
-
# more than one matching driver
|
|
133
|
-
raise exceptions.PlatformException(
|
|
134
|
-
error='404',
|
|
135
|
-
message='More than one driver with same name. Please "get" by id')
|
|
136
|
-
else:
|
|
137
|
-
driver = driver[0]
|
|
138
|
-
else:
|
|
139
|
-
raise exceptions.PlatformException(
|
|
140
|
-
error='400',
|
|
141
|
-
message='Must provide an identifier (name or id) in inputs')
|
|
142
|
-
return driver
|
|
143
|
-
|
|
144
|
-
@_api_reference.add(path='/drivers', method='post')
|
|
145
|
-
def create(self,
|
|
146
|
-
name: str,
|
|
147
|
-
driver_type: entities.ExternalStorage,
|
|
148
|
-
integration_id: str,
|
|
149
|
-
bucket_name: str,
|
|
150
|
-
integration_type: entities.IntegrationType,
|
|
151
|
-
project_id: str = None,
|
|
152
|
-
allow_external_delete: bool = True,
|
|
153
|
-
region: str = None,
|
|
154
|
-
storage_class: str = "",
|
|
155
|
-
path: str = "",
|
|
156
|
-
endpoint: str = None):
|
|
157
|
-
"""
|
|
158
|
-
Create a storage driver.
|
|
159
|
-
|
|
160
|
-
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
161
|
-
|
|
162
|
-
:param str name: the driver name
|
|
163
|
-
:param ExternalStorage driver_type: dl.ExternalStorage (Enum). For all options run: list(dl.ExsternalStorage)
|
|
164
|
-
:param str integration_id: the integration id
|
|
165
|
-
:param str bucket_name: the external bucket name
|
|
166
|
-
:param IntegrationType integration_type: dl.IntegrationType (Enum). For all options run: list(dl.IntegrationType)
|
|
167
|
-
:param str project_id: project id
|
|
168
|
-
:param bool allow_external_delete: true to allow deleting files from external storage when files are deleted in your Dataloop storage
|
|
169
|
-
:param str region: relevant only for s3 - the bucket region
|
|
170
|
-
:param str storage_class: relevant only for s3
|
|
171
|
-
:param str path: Optional. By default path is the root folder. Path is case sensitive integration
|
|
172
|
-
:param endpoint path: Optional. Custom endpoint for S3 storage. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'.
|
|
173
|
-
:return: driver object
|
|
174
|
-
:rtype: dtlpy.entities.driver.Driver
|
|
175
|
-
|
|
176
|
-
**Example**:
|
|
177
|
-
|
|
178
|
-
.. code-block:: python
|
|
179
|
-
|
|
180
|
-
project.drivers.create(name='driver_name',
|
|
181
|
-
driver_type=dl.ExternalStorage.S3,
|
|
182
|
-
integration_id='integration_id',
|
|
183
|
-
bucket_name='bucket_name',
|
|
184
|
-
project_id='project_id',
|
|
185
|
-
region='ey-west-1')
|
|
186
|
-
"""
|
|
187
|
-
if integration_type is None:
|
|
188
|
-
integration_type = driver_type
|
|
189
|
-
if driver_type == entities.ExternalStorage.S3:
|
|
190
|
-
bucket_payload = 'bucketName'
|
|
191
|
-
if endpoint:
|
|
192
|
-
if not re.match(r'^https?://[A-Za-z0-9.-]+:\d+$', endpoint):
|
|
193
|
-
raise ValueError(
|
|
194
|
-
f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
|
|
195
|
-
)
|
|
196
|
-
elif driver_type == entities.ExternalStorage.GCS:
|
|
197
|
-
bucket_payload = 'bucket'
|
|
198
|
-
else:
|
|
199
|
-
bucket_payload = 'containerName'
|
|
200
|
-
payload = {
|
|
201
|
-
"integrationId": integration_id,
|
|
202
|
-
'integrationType': integration_type,
|
|
203
|
-
"name": name,
|
|
204
|
-
"metadata": {
|
|
205
|
-
"system": {
|
|
206
|
-
"projectId": self.project.id if project_id is None else project_id
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
|
-
"type": driver_type,
|
|
210
|
-
"payload": {
|
|
211
|
-
bucket_payload: bucket_name,
|
|
212
|
-
"storageClass": storage_class,
|
|
213
|
-
"region": region,
|
|
214
|
-
"path": path
|
|
215
|
-
},
|
|
216
|
-
"allowExternalDelete": allow_external_delete,
|
|
217
|
-
"creator": self._client_api.info().get('user_email')
|
|
218
|
-
}
|
|
219
|
-
if endpoint and driver_type == entities.ExternalStorage.S3:
|
|
220
|
-
payload['payload']['endpoint'] = endpoint
|
|
221
|
-
|
|
222
|
-
success, response = self._client_api.gen_request(req_type='post',
|
|
223
|
-
path='/drivers',
|
|
224
|
-
json_req=payload)
|
|
225
|
-
if not success:
|
|
226
|
-
raise exceptions.PlatformException(response)
|
|
227
|
-
else:
|
|
228
|
-
_json = response.json()
|
|
229
|
-
return self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
|
|
230
|
-
|
|
231
|
-
@_api_reference.add(path='/drivers/{id}', method='delete')
|
|
232
|
-
def delete(self,
|
|
233
|
-
driver_name: str = None,
|
|
234
|
-
driver_id: str = None,
|
|
235
|
-
sure: bool = False,
|
|
236
|
-
really: bool = False):
|
|
237
|
-
"""
|
|
238
|
-
Delete a driver forever!
|
|
239
|
-
|
|
240
|
-
**Prerequisites**: You must be an *owner* or *developer* to use this method.
|
|
241
|
-
|
|
242
|
-
**Example**:
|
|
243
|
-
|
|
244
|
-
.. code-block:: python
|
|
245
|
-
|
|
246
|
-
project.drivers.delete(dataset_id='dataset_id', sure=True, really=True)
|
|
247
|
-
|
|
248
|
-
:param str driver_name: optional - search by name
|
|
249
|
-
:param str driver_id: optional - search by id
|
|
250
|
-
:param bool sure: Are you sure you want to delete?
|
|
251
|
-
:param bool really: Really really sure?
|
|
252
|
-
:return: True if success
|
|
253
|
-
:rtype: bool
|
|
254
|
-
"""
|
|
255
|
-
if sure and really:
|
|
256
|
-
driver = self.get(driver_name=driver_name, driver_id=driver_id)
|
|
257
|
-
success, response = self._client_api.gen_request(req_type='delete',
|
|
258
|
-
path='/drivers/{}'.format(driver.id))
|
|
259
|
-
if not success:
|
|
260
|
-
raise exceptions.PlatformException(response)
|
|
261
|
-
logger.info('Driver {!r} was deleted successfully'.format(driver.name))
|
|
262
|
-
return True
|
|
263
|
-
else:
|
|
264
|
-
raise exceptions.PlatformException(
|
|
265
|
-
error='403',
|
|
266
|
-
message='Cant delete driver from SDK. Please login to platform to delete')
|
|
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
|
+
self._client_api = client_api
|
|
20
|
+
self._project = project
|
|
21
|
+
|
|
22
|
+
############
|
|
23
|
+
# entities #
|
|
24
|
+
############
|
|
25
|
+
@property
|
|
26
|
+
def project(self) -> entities.Project:
|
|
27
|
+
if self._project is None:
|
|
28
|
+
# try get checkout
|
|
29
|
+
project = self._client_api.state_io.get('project')
|
|
30
|
+
if project is not None:
|
|
31
|
+
self._project = entities.Project.from_json(_json=project, client_api=self._client_api)
|
|
32
|
+
if self._project is None:
|
|
33
|
+
raise exceptions.PlatformException(
|
|
34
|
+
error='2001',
|
|
35
|
+
message='Cannot perform action WITHOUT Project entity in Drivers repository.'
|
|
36
|
+
' Please checkout or set a project')
|
|
37
|
+
assert isinstance(self._project, entities.Project)
|
|
38
|
+
return self._project
|
|
39
|
+
|
|
40
|
+
@project.setter
|
|
41
|
+
def project(self, project: entities.Project):
|
|
42
|
+
if not isinstance(project, entities.Project):
|
|
43
|
+
raise ValueError('Must input a valid Project entity')
|
|
44
|
+
self._project = project
|
|
45
|
+
|
|
46
|
+
###########
|
|
47
|
+
# methods #
|
|
48
|
+
###########
|
|
49
|
+
def __get_by_id(self, driver_id) -> entities.Driver:
|
|
50
|
+
success, response = self._client_api.gen_request(req_type='get',
|
|
51
|
+
path='/drivers/{}'.format(driver_id))
|
|
52
|
+
if success:
|
|
53
|
+
_json = response.json()
|
|
54
|
+
driver = self._getDriverClass(_json).from_json(client_api=self._client_api,
|
|
55
|
+
_json=_json)
|
|
56
|
+
else:
|
|
57
|
+
raise exceptions.PlatformException(response)
|
|
58
|
+
return driver
|
|
59
|
+
|
|
60
|
+
@_api_reference.add(path='/drivers', method='get')
|
|
61
|
+
def list(self) -> miscellaneous.List[entities.Driver]:
|
|
62
|
+
"""
|
|
63
|
+
Get the project's drivers list.
|
|
64
|
+
|
|
65
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
66
|
+
|
|
67
|
+
:return: List of Drivers objects
|
|
68
|
+
:rtype: list
|
|
69
|
+
|
|
70
|
+
**Example**:
|
|
71
|
+
|
|
72
|
+
.. code-block:: python
|
|
73
|
+
|
|
74
|
+
project.drivers.list()
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
success, response = self._client_api.gen_request(req_type='get',
|
|
79
|
+
path='/drivers?projectId={}'.format(self.project.id))
|
|
80
|
+
if not success:
|
|
81
|
+
raise exceptions.PlatformException(response)
|
|
82
|
+
drivers = miscellaneous.List([self._getDriverClass(_json).from_json(_json=_json,
|
|
83
|
+
client_api=self._client_api) for _json in
|
|
84
|
+
response.json()])
|
|
85
|
+
return drivers
|
|
86
|
+
|
|
87
|
+
def _getDriverClass(self, _json):
|
|
88
|
+
driver_type = _json.get('type', None)
|
|
89
|
+
if driver_type == entities.ExternalStorage.S3:
|
|
90
|
+
driver_class = entities.S3Driver
|
|
91
|
+
elif driver_type == entities.ExternalStorage.GCS:
|
|
92
|
+
driver_class = entities.GcsDriver
|
|
93
|
+
elif driver_type in [entities.ExternalStorage.AZUREBLOB, entities.ExternalStorage.AZURE_DATALAKE_GEN2]:
|
|
94
|
+
driver_class = entities.AzureBlobDriver
|
|
95
|
+
else:
|
|
96
|
+
driver_class = entities.Driver
|
|
97
|
+
return driver_class
|
|
98
|
+
|
|
99
|
+
@_api_reference.add(path='/drivers/{id}', method='get')
|
|
100
|
+
def get(self,
|
|
101
|
+
driver_name: str = None,
|
|
102
|
+
driver_id: str = None) -> entities.Driver:
|
|
103
|
+
"""
|
|
104
|
+
Get a Driver object to use in your code.
|
|
105
|
+
|
|
106
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
107
|
+
|
|
108
|
+
You must provide at least ONE of the following params: driver_name, driver_id.
|
|
109
|
+
|
|
110
|
+
:param str driver_name: optional - search by name
|
|
111
|
+
:param str driver_id: optional - search by id
|
|
112
|
+
:return: Driver object
|
|
113
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
114
|
+
|
|
115
|
+
**Example**:
|
|
116
|
+
|
|
117
|
+
.. code-block:: python
|
|
118
|
+
|
|
119
|
+
project.drivers.get(driver_id='driver_id')
|
|
120
|
+
"""
|
|
121
|
+
if driver_id is not None:
|
|
122
|
+
driver = self.__get_by_id(driver_id)
|
|
123
|
+
elif driver_name is not None:
|
|
124
|
+
drivers = self.list()
|
|
125
|
+
driver = [driver for driver in drivers if driver.name == driver_name]
|
|
126
|
+
if not driver:
|
|
127
|
+
# list is empty
|
|
128
|
+
raise exceptions.PlatformException(error='404',
|
|
129
|
+
message='Driver not found. Name: {}'.format(driver_name))
|
|
130
|
+
# driver = None
|
|
131
|
+
elif len(driver) > 1:
|
|
132
|
+
# more than one matching driver
|
|
133
|
+
raise exceptions.PlatformException(
|
|
134
|
+
error='404',
|
|
135
|
+
message='More than one driver with same name. Please "get" by id')
|
|
136
|
+
else:
|
|
137
|
+
driver = driver[0]
|
|
138
|
+
else:
|
|
139
|
+
raise exceptions.PlatformException(
|
|
140
|
+
error='400',
|
|
141
|
+
message='Must provide an identifier (name or id) in inputs')
|
|
142
|
+
return driver
|
|
143
|
+
|
|
144
|
+
@_api_reference.add(path='/drivers', method='post')
|
|
145
|
+
def create(self,
|
|
146
|
+
name: str,
|
|
147
|
+
driver_type: entities.ExternalStorage,
|
|
148
|
+
integration_id: str,
|
|
149
|
+
bucket_name: str,
|
|
150
|
+
integration_type: entities.IntegrationType,
|
|
151
|
+
project_id: str = None,
|
|
152
|
+
allow_external_delete: bool = True,
|
|
153
|
+
region: str = None,
|
|
154
|
+
storage_class: str = "",
|
|
155
|
+
path: str = "",
|
|
156
|
+
endpoint: str = None):
|
|
157
|
+
"""
|
|
158
|
+
Create a storage driver.
|
|
159
|
+
|
|
160
|
+
**Prerequisites**: You must be in the role of an *owner* or *developer*.
|
|
161
|
+
|
|
162
|
+
:param str name: the driver name
|
|
163
|
+
:param ExternalStorage driver_type: dl.ExternalStorage (Enum). For all options run: list(dl.ExsternalStorage)
|
|
164
|
+
:param str integration_id: the integration id
|
|
165
|
+
:param str bucket_name: the external bucket name
|
|
166
|
+
:param IntegrationType integration_type: dl.IntegrationType (Enum). For all options run: list(dl.IntegrationType)
|
|
167
|
+
:param str project_id: project id
|
|
168
|
+
:param bool allow_external_delete: true to allow deleting files from external storage when files are deleted in your Dataloop storage
|
|
169
|
+
:param str region: relevant only for s3 - the bucket region
|
|
170
|
+
:param str storage_class: relevant only for s3
|
|
171
|
+
:param str path: Optional. By default path is the root folder. Path is case sensitive integration
|
|
172
|
+
:param endpoint path: Optional. Custom endpoint for S3 storage. Must be in the format 'http://<hostname>:<port>' or 'https://<hostname>:<port>'.
|
|
173
|
+
:return: driver object
|
|
174
|
+
:rtype: dtlpy.entities.driver.Driver
|
|
175
|
+
|
|
176
|
+
**Example**:
|
|
177
|
+
|
|
178
|
+
.. code-block:: python
|
|
179
|
+
|
|
180
|
+
project.drivers.create(name='driver_name',
|
|
181
|
+
driver_type=dl.ExternalStorage.S3,
|
|
182
|
+
integration_id='integration_id',
|
|
183
|
+
bucket_name='bucket_name',
|
|
184
|
+
project_id='project_id',
|
|
185
|
+
region='ey-west-1')
|
|
186
|
+
"""
|
|
187
|
+
if integration_type is None:
|
|
188
|
+
integration_type = driver_type
|
|
189
|
+
if driver_type == entities.ExternalStorage.S3:
|
|
190
|
+
bucket_payload = 'bucketName'
|
|
191
|
+
if endpoint:
|
|
192
|
+
if not re.match(r'^https?://[A-Za-z0-9.-]+:\d+$', endpoint):
|
|
193
|
+
raise ValueError(
|
|
194
|
+
f"Invalid endpoint URL '{endpoint}'. Must be 'http://<hostname>:<port>' or 'https://<hostname>:<port>'."
|
|
195
|
+
)
|
|
196
|
+
elif driver_type == entities.ExternalStorage.GCS:
|
|
197
|
+
bucket_payload = 'bucket'
|
|
198
|
+
else:
|
|
199
|
+
bucket_payload = 'containerName'
|
|
200
|
+
payload = {
|
|
201
|
+
"integrationId": integration_id,
|
|
202
|
+
'integrationType': integration_type,
|
|
203
|
+
"name": name,
|
|
204
|
+
"metadata": {
|
|
205
|
+
"system": {
|
|
206
|
+
"projectId": self.project.id if project_id is None else project_id
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
"type": driver_type,
|
|
210
|
+
"payload": {
|
|
211
|
+
bucket_payload: bucket_name,
|
|
212
|
+
"storageClass": storage_class,
|
|
213
|
+
"region": region,
|
|
214
|
+
"path": path
|
|
215
|
+
},
|
|
216
|
+
"allowExternalDelete": allow_external_delete,
|
|
217
|
+
"creator": self._client_api.info().get('user_email')
|
|
218
|
+
}
|
|
219
|
+
if endpoint and driver_type == entities.ExternalStorage.S3:
|
|
220
|
+
payload['payload']['endpoint'] = endpoint
|
|
221
|
+
|
|
222
|
+
success, response = self._client_api.gen_request(req_type='post',
|
|
223
|
+
path='/drivers',
|
|
224
|
+
json_req=payload)
|
|
225
|
+
if not success:
|
|
226
|
+
raise exceptions.PlatformException(response)
|
|
227
|
+
else:
|
|
228
|
+
_json = response.json()
|
|
229
|
+
return self._getDriverClass(_json).from_json(_json=_json, client_api=self._client_api)
|
|
230
|
+
|
|
231
|
+
@_api_reference.add(path='/drivers/{id}', method='delete')
|
|
232
|
+
def delete(self,
|
|
233
|
+
driver_name: str = None,
|
|
234
|
+
driver_id: str = None,
|
|
235
|
+
sure: bool = False,
|
|
236
|
+
really: bool = False):
|
|
237
|
+
"""
|
|
238
|
+
Delete a driver forever!
|
|
239
|
+
|
|
240
|
+
**Prerequisites**: You must be an *owner* or *developer* to use this method.
|
|
241
|
+
|
|
242
|
+
**Example**:
|
|
243
|
+
|
|
244
|
+
.. code-block:: python
|
|
245
|
+
|
|
246
|
+
project.drivers.delete(dataset_id='dataset_id', sure=True, really=True)
|
|
247
|
+
|
|
248
|
+
:param str driver_name: optional - search by name
|
|
249
|
+
:param str driver_id: optional - search by id
|
|
250
|
+
:param bool sure: Are you sure you want to delete?
|
|
251
|
+
:param bool really: Really really sure?
|
|
252
|
+
:return: True if success
|
|
253
|
+
:rtype: bool
|
|
254
|
+
"""
|
|
255
|
+
if sure and really:
|
|
256
|
+
driver = self.get(driver_name=driver_name, driver_id=driver_id)
|
|
257
|
+
success, response = self._client_api.gen_request(req_type='delete',
|
|
258
|
+
path='/drivers/{}'.format(driver.id))
|
|
259
|
+
if not success:
|
|
260
|
+
raise exceptions.PlatformException(response)
|
|
261
|
+
logger.info('Driver {!r} was deleted successfully'.format(driver.name))
|
|
262
|
+
return True
|
|
263
|
+
else:
|
|
264
|
+
raise exceptions.PlatformException(
|
|
265
|
+
error='403',
|
|
266
|
+
message='Cant delete driver from SDK. Please login to platform to delete')
|