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/entities/app.py
CHANGED
|
@@ -1,220 +1,220 @@
|
|
|
1
|
-
from collections import namedtuple
|
|
2
|
-
import traceback
|
|
3
|
-
import logging
|
|
4
|
-
from enum import Enum
|
|
5
|
-
|
|
6
|
-
import attr
|
|
7
|
-
|
|
8
|
-
from .. import entities, repositories
|
|
9
|
-
from ..services.api_client import ApiClient
|
|
10
|
-
|
|
11
|
-
logger = logging.getLogger(name='dtlpy')
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class AppScope(str, Enum):
|
|
15
|
-
""" The scope of the app.
|
|
16
|
-
|
|
17
|
-
.. list-table::
|
|
18
|
-
:widths: 15 150
|
|
19
|
-
:header-rows: 1
|
|
20
|
-
|
|
21
|
-
* - State
|
|
22
|
-
- Description
|
|
23
|
-
* - SYSTEM
|
|
24
|
-
- Dataloop internal app
|
|
25
|
-
* - PROJECT
|
|
26
|
-
- Project app
|
|
27
|
-
"""
|
|
28
|
-
SYSTEM = 'system'
|
|
29
|
-
PROJECT = 'project'
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@attr.s
|
|
33
|
-
class App(entities.BaseEntity):
|
|
34
|
-
id = attr.ib(type=str)
|
|
35
|
-
name = attr.ib(type=str)
|
|
36
|
-
url = attr.ib(type=str)
|
|
37
|
-
created_at = attr.ib(type=str)
|
|
38
|
-
updated_at = attr.ib(type=str)
|
|
39
|
-
creator = attr.ib(type=str)
|
|
40
|
-
project_id = attr.ib(type=str)
|
|
41
|
-
org_id = attr.ib(type=str)
|
|
42
|
-
dpk_name = attr.ib(type=str)
|
|
43
|
-
dpk_version = attr.ib(type=str)
|
|
44
|
-
composition_id = attr.ib(type=str)
|
|
45
|
-
scope = attr.ib(type=str)
|
|
46
|
-
routes = attr.ib(type=dict)
|
|
47
|
-
custom_installation = attr.ib(type=dict)
|
|
48
|
-
metadata = attr.ib(type=dict)
|
|
49
|
-
status = attr.ib(type=entities.CompositionStatus)
|
|
50
|
-
settings = attr.ib(type=dict)
|
|
51
|
-
|
|
52
|
-
# sdk
|
|
53
|
-
_project = attr.ib(type=entities.Project, repr=False)
|
|
54
|
-
_client_api = attr.ib(type=ApiClient, repr=False)
|
|
55
|
-
_repositories = attr.ib(repr=False)
|
|
56
|
-
integrations = attr.ib(type=list, default=None)
|
|
57
|
-
|
|
58
|
-
@_repositories.default
|
|
59
|
-
def set_repositories(self):
|
|
60
|
-
reps = namedtuple('repositories', field_names=['projects', 'apps', 'compositions'])
|
|
61
|
-
return reps(
|
|
62
|
-
projects=repositories.Projects(client_api=self._client_api),
|
|
63
|
-
apps=repositories.Apps(client_api=self._client_api, project=self._project, project_id=self.project_id),
|
|
64
|
-
compositions=repositories.Compositions(client_api=self._client_api, project=self._project)
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
def project(self):
|
|
69
|
-
if self._project is None:
|
|
70
|
-
self._project = self.projects.get(project_id=self.project_id)
|
|
71
|
-
return self._project
|
|
72
|
-
|
|
73
|
-
@property
|
|
74
|
-
def projects(self):
|
|
75
|
-
assert isinstance(self._repositories.projects, repositories.Projects)
|
|
76
|
-
return self._repositories.projects
|
|
77
|
-
|
|
78
|
-
@property
|
|
79
|
-
def apps(self):
|
|
80
|
-
assert isinstance(self._repositories.apps, repositories.Apps)
|
|
81
|
-
return self._repositories.apps
|
|
82
|
-
|
|
83
|
-
@property
|
|
84
|
-
def compositions(self):
|
|
85
|
-
assert isinstance(self._repositories.compositions, repositories.Compositions)
|
|
86
|
-
return self._repositories.compositions
|
|
87
|
-
|
|
88
|
-
def uninstall(self):
|
|
89
|
-
"""
|
|
90
|
-
Uninstall an app installed app from the project.
|
|
91
|
-
|
|
92
|
-
**Example**
|
|
93
|
-
.. code-block:: python
|
|
94
|
-
succeed = app.uninstall()
|
|
95
|
-
"""
|
|
96
|
-
return self.apps.uninstall(self.id)
|
|
97
|
-
|
|
98
|
-
def update(self):
|
|
99
|
-
"""
|
|
100
|
-
Update the current app to the new configuration
|
|
101
|
-
|
|
102
|
-
:return bool whether the operation ran successfully or not
|
|
103
|
-
|
|
104
|
-
**Example**
|
|
105
|
-
.. code-block:: python
|
|
106
|
-
succeed = app.update()
|
|
107
|
-
"""
|
|
108
|
-
return self.apps.update(self)
|
|
109
|
-
|
|
110
|
-
def resume(self):
|
|
111
|
-
"""
|
|
112
|
-
Resume the current app
|
|
113
|
-
|
|
114
|
-
:return bool whether the operation ran successfully or not
|
|
115
|
-
|
|
116
|
-
**Example**
|
|
117
|
-
.. code-block:: python
|
|
118
|
-
succeed = app.resume()
|
|
119
|
-
"""
|
|
120
|
-
return self.apps.resume(self)
|
|
121
|
-
|
|
122
|
-
def pause(self):
|
|
123
|
-
"""
|
|
124
|
-
Pause the current app
|
|
125
|
-
|
|
126
|
-
:return bool whether the operation ran successfully or not
|
|
127
|
-
|
|
128
|
-
**Example**
|
|
129
|
-
.. code-block:: python
|
|
130
|
-
succeed = app.pause()
|
|
131
|
-
"""
|
|
132
|
-
return self.apps.pause(self)
|
|
133
|
-
|
|
134
|
-
@staticmethod
|
|
135
|
-
def _protected_from_json(_json, client_api, project=None, is_fetched=True):
|
|
136
|
-
"""
|
|
137
|
-
Same as from_json but with try-except to catch if error
|
|
138
|
-
|
|
139
|
-
:param _json: platform json
|
|
140
|
-
:param client_api: ApiClient entity
|
|
141
|
-
:return:
|
|
142
|
-
"""
|
|
143
|
-
try:
|
|
144
|
-
package = App.from_json(_json=_json,
|
|
145
|
-
client_api=client_api,
|
|
146
|
-
project=project,
|
|
147
|
-
is_fetched=is_fetched)
|
|
148
|
-
status = True
|
|
149
|
-
except Exception:
|
|
150
|
-
package = traceback.format_exc()
|
|
151
|
-
status = False
|
|
152
|
-
return status, package
|
|
153
|
-
|
|
154
|
-
def to_json(self):
|
|
155
|
-
_json = {}
|
|
156
|
-
if self.id is not None:
|
|
157
|
-
_json['id'] = self.id
|
|
158
|
-
if self.name is not None:
|
|
159
|
-
_json['name'] = self.name
|
|
160
|
-
if self.url is not None:
|
|
161
|
-
_json['url'] = self.url
|
|
162
|
-
if self.created_at is not None:
|
|
163
|
-
_json['createdAt'] = self.created_at
|
|
164
|
-
if self.updated_at is not None:
|
|
165
|
-
_json['updatedAt'] = self.updated_at
|
|
166
|
-
if self.creator is not None:
|
|
167
|
-
_json['creator'] = self.creator
|
|
168
|
-
if self.project_id is not None:
|
|
169
|
-
_json['projectId'] = self.project_id
|
|
170
|
-
if self.org_id is not None:
|
|
171
|
-
_json['orgId'] = self.org_id
|
|
172
|
-
if self.dpk_name is not None:
|
|
173
|
-
_json['dpkName'] = self.dpk_name
|
|
174
|
-
if self.dpk_version is not None:
|
|
175
|
-
_json['dpkVersion'] = self.dpk_version
|
|
176
|
-
if self.composition_id is not None:
|
|
177
|
-
_json['compositionId'] = self.composition_id
|
|
178
|
-
if self.scope is not None:
|
|
179
|
-
_json['scope'] = self.scope
|
|
180
|
-
if self.routes != {}:
|
|
181
|
-
_json['routes'] = self.routes
|
|
182
|
-
if self.custom_installation != {}:
|
|
183
|
-
_json['customInstallation'] = self.custom_installation
|
|
184
|
-
if self.metadata is not None:
|
|
185
|
-
_json['metadata'] = self.metadata
|
|
186
|
-
if self.status is not None:
|
|
187
|
-
_json['status'] = self.status
|
|
188
|
-
if self.settings != {}:
|
|
189
|
-
_json['settings'] = self.settings
|
|
190
|
-
if self.integrations is not None:
|
|
191
|
-
_json['integrations'] = self.integrations
|
|
192
|
-
|
|
193
|
-
return _json
|
|
194
|
-
|
|
195
|
-
@classmethod
|
|
196
|
-
def from_json(cls, _json, client_api: ApiClient, project: entities.Project=None, is_fetched=True):
|
|
197
|
-
app = cls(
|
|
198
|
-
id=_json.get('id', None),
|
|
199
|
-
name=_json.get('name', None),
|
|
200
|
-
url=_json.get('url', None),
|
|
201
|
-
created_at=_json.get('createdAt', None),
|
|
202
|
-
updated_at=_json.get('updatedAt', None),
|
|
203
|
-
creator=_json.get('creator', None),
|
|
204
|
-
project_id=_json.get('projectId', None),
|
|
205
|
-
org_id=_json.get('orgId', None),
|
|
206
|
-
dpk_name=_json.get('dpkName', None),
|
|
207
|
-
dpk_version=_json.get('dpkVersion', None),
|
|
208
|
-
composition_id=_json.get('compositionId', None),
|
|
209
|
-
scope=_json.get('scope', None),
|
|
210
|
-
routes=_json.get('routes', {}),
|
|
211
|
-
custom_installation=_json.get('customInstallation', {}),
|
|
212
|
-
client_api=client_api,
|
|
213
|
-
project=project,
|
|
214
|
-
metadata=_json.get('metadata', None),
|
|
215
|
-
status=_json.get('status', None),
|
|
216
|
-
settings=_json.get('settings', {}),
|
|
217
|
-
integrations=_json.get('integrations', None)
|
|
218
|
-
)
|
|
219
|
-
app.is_fetched = is_fetched
|
|
220
|
-
return app
|
|
1
|
+
from collections import namedtuple
|
|
2
|
+
import traceback
|
|
3
|
+
import logging
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
import attr
|
|
7
|
+
|
|
8
|
+
from .. import entities, repositories
|
|
9
|
+
from ..services.api_client import ApiClient
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(name='dtlpy')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AppScope(str, Enum):
|
|
15
|
+
""" The scope of the app.
|
|
16
|
+
|
|
17
|
+
.. list-table::
|
|
18
|
+
:widths: 15 150
|
|
19
|
+
:header-rows: 1
|
|
20
|
+
|
|
21
|
+
* - State
|
|
22
|
+
- Description
|
|
23
|
+
* - SYSTEM
|
|
24
|
+
- Dataloop internal app
|
|
25
|
+
* - PROJECT
|
|
26
|
+
- Project app
|
|
27
|
+
"""
|
|
28
|
+
SYSTEM = 'system'
|
|
29
|
+
PROJECT = 'project'
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@attr.s
|
|
33
|
+
class App(entities.BaseEntity):
|
|
34
|
+
id = attr.ib(type=str)
|
|
35
|
+
name = attr.ib(type=str)
|
|
36
|
+
url = attr.ib(type=str)
|
|
37
|
+
created_at = attr.ib(type=str)
|
|
38
|
+
updated_at = attr.ib(type=str)
|
|
39
|
+
creator = attr.ib(type=str)
|
|
40
|
+
project_id = attr.ib(type=str)
|
|
41
|
+
org_id = attr.ib(type=str)
|
|
42
|
+
dpk_name = attr.ib(type=str)
|
|
43
|
+
dpk_version = attr.ib(type=str)
|
|
44
|
+
composition_id = attr.ib(type=str)
|
|
45
|
+
scope = attr.ib(type=str)
|
|
46
|
+
routes = attr.ib(type=dict)
|
|
47
|
+
custom_installation = attr.ib(type=dict)
|
|
48
|
+
metadata = attr.ib(type=dict)
|
|
49
|
+
status = attr.ib(type=entities.CompositionStatus)
|
|
50
|
+
settings = attr.ib(type=dict)
|
|
51
|
+
|
|
52
|
+
# sdk
|
|
53
|
+
_project = attr.ib(type=entities.Project, repr=False)
|
|
54
|
+
_client_api = attr.ib(type=ApiClient, repr=False)
|
|
55
|
+
_repositories = attr.ib(repr=False)
|
|
56
|
+
integrations = attr.ib(type=list, default=None)
|
|
57
|
+
|
|
58
|
+
@_repositories.default
|
|
59
|
+
def set_repositories(self):
|
|
60
|
+
reps = namedtuple('repositories', field_names=['projects', 'apps', 'compositions'])
|
|
61
|
+
return reps(
|
|
62
|
+
projects=repositories.Projects(client_api=self._client_api),
|
|
63
|
+
apps=repositories.Apps(client_api=self._client_api, project=self._project, project_id=self.project_id),
|
|
64
|
+
compositions=repositories.Compositions(client_api=self._client_api, project=self._project)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def project(self):
|
|
69
|
+
if self._project is None:
|
|
70
|
+
self._project = self.projects.get(project_id=self.project_id)
|
|
71
|
+
return self._project
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def projects(self):
|
|
75
|
+
assert isinstance(self._repositories.projects, repositories.Projects)
|
|
76
|
+
return self._repositories.projects
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def apps(self):
|
|
80
|
+
assert isinstance(self._repositories.apps, repositories.Apps)
|
|
81
|
+
return self._repositories.apps
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def compositions(self):
|
|
85
|
+
assert isinstance(self._repositories.compositions, repositories.Compositions)
|
|
86
|
+
return self._repositories.compositions
|
|
87
|
+
|
|
88
|
+
def uninstall(self):
|
|
89
|
+
"""
|
|
90
|
+
Uninstall an app installed app from the project.
|
|
91
|
+
|
|
92
|
+
**Example**
|
|
93
|
+
.. code-block:: python
|
|
94
|
+
succeed = app.uninstall()
|
|
95
|
+
"""
|
|
96
|
+
return self.apps.uninstall(self.id)
|
|
97
|
+
|
|
98
|
+
def update(self):
|
|
99
|
+
"""
|
|
100
|
+
Update the current app to the new configuration
|
|
101
|
+
|
|
102
|
+
:return bool whether the operation ran successfully or not
|
|
103
|
+
|
|
104
|
+
**Example**
|
|
105
|
+
.. code-block:: python
|
|
106
|
+
succeed = app.update()
|
|
107
|
+
"""
|
|
108
|
+
return self.apps.update(self)
|
|
109
|
+
|
|
110
|
+
def resume(self):
|
|
111
|
+
"""
|
|
112
|
+
Resume the current app
|
|
113
|
+
|
|
114
|
+
:return bool whether the operation ran successfully or not
|
|
115
|
+
|
|
116
|
+
**Example**
|
|
117
|
+
.. code-block:: python
|
|
118
|
+
succeed = app.resume()
|
|
119
|
+
"""
|
|
120
|
+
return self.apps.resume(self)
|
|
121
|
+
|
|
122
|
+
def pause(self):
|
|
123
|
+
"""
|
|
124
|
+
Pause the current app
|
|
125
|
+
|
|
126
|
+
:return bool whether the operation ran successfully or not
|
|
127
|
+
|
|
128
|
+
**Example**
|
|
129
|
+
.. code-block:: python
|
|
130
|
+
succeed = app.pause()
|
|
131
|
+
"""
|
|
132
|
+
return self.apps.pause(self)
|
|
133
|
+
|
|
134
|
+
@staticmethod
|
|
135
|
+
def _protected_from_json(_json, client_api, project=None, is_fetched=True):
|
|
136
|
+
"""
|
|
137
|
+
Same as from_json but with try-except to catch if error
|
|
138
|
+
|
|
139
|
+
:param _json: platform json
|
|
140
|
+
:param client_api: ApiClient entity
|
|
141
|
+
:return:
|
|
142
|
+
"""
|
|
143
|
+
try:
|
|
144
|
+
package = App.from_json(_json=_json,
|
|
145
|
+
client_api=client_api,
|
|
146
|
+
project=project,
|
|
147
|
+
is_fetched=is_fetched)
|
|
148
|
+
status = True
|
|
149
|
+
except Exception:
|
|
150
|
+
package = traceback.format_exc()
|
|
151
|
+
status = False
|
|
152
|
+
return status, package
|
|
153
|
+
|
|
154
|
+
def to_json(self):
|
|
155
|
+
_json = {}
|
|
156
|
+
if self.id is not None:
|
|
157
|
+
_json['id'] = self.id
|
|
158
|
+
if self.name is not None:
|
|
159
|
+
_json['name'] = self.name
|
|
160
|
+
if self.url is not None:
|
|
161
|
+
_json['url'] = self.url
|
|
162
|
+
if self.created_at is not None:
|
|
163
|
+
_json['createdAt'] = self.created_at
|
|
164
|
+
if self.updated_at is not None:
|
|
165
|
+
_json['updatedAt'] = self.updated_at
|
|
166
|
+
if self.creator is not None:
|
|
167
|
+
_json['creator'] = self.creator
|
|
168
|
+
if self.project_id is not None:
|
|
169
|
+
_json['projectId'] = self.project_id
|
|
170
|
+
if self.org_id is not None:
|
|
171
|
+
_json['orgId'] = self.org_id
|
|
172
|
+
if self.dpk_name is not None:
|
|
173
|
+
_json['dpkName'] = self.dpk_name
|
|
174
|
+
if self.dpk_version is not None:
|
|
175
|
+
_json['dpkVersion'] = self.dpk_version
|
|
176
|
+
if self.composition_id is not None:
|
|
177
|
+
_json['compositionId'] = self.composition_id
|
|
178
|
+
if self.scope is not None:
|
|
179
|
+
_json['scope'] = self.scope
|
|
180
|
+
if self.routes != {}:
|
|
181
|
+
_json['routes'] = self.routes
|
|
182
|
+
if self.custom_installation != {}:
|
|
183
|
+
_json['customInstallation'] = self.custom_installation
|
|
184
|
+
if self.metadata is not None:
|
|
185
|
+
_json['metadata'] = self.metadata
|
|
186
|
+
if self.status is not None:
|
|
187
|
+
_json['status'] = self.status
|
|
188
|
+
if self.settings != {}:
|
|
189
|
+
_json['settings'] = self.settings
|
|
190
|
+
if self.integrations is not None:
|
|
191
|
+
_json['integrations'] = self.integrations
|
|
192
|
+
|
|
193
|
+
return _json
|
|
194
|
+
|
|
195
|
+
@classmethod
|
|
196
|
+
def from_json(cls, _json, client_api: ApiClient, project: entities.Project=None, is_fetched=True):
|
|
197
|
+
app = cls(
|
|
198
|
+
id=_json.get('id', None),
|
|
199
|
+
name=_json.get('name', None),
|
|
200
|
+
url=_json.get('url', None),
|
|
201
|
+
created_at=_json.get('createdAt', None),
|
|
202
|
+
updated_at=_json.get('updatedAt', None),
|
|
203
|
+
creator=_json.get('creator', None),
|
|
204
|
+
project_id=_json.get('projectId', None),
|
|
205
|
+
org_id=_json.get('orgId', None),
|
|
206
|
+
dpk_name=_json.get('dpkName', None),
|
|
207
|
+
dpk_version=_json.get('dpkVersion', None),
|
|
208
|
+
composition_id=_json.get('compositionId', None),
|
|
209
|
+
scope=_json.get('scope', None),
|
|
210
|
+
routes=_json.get('routes', {}),
|
|
211
|
+
custom_installation=_json.get('customInstallation', {}),
|
|
212
|
+
client_api=client_api,
|
|
213
|
+
project=project,
|
|
214
|
+
metadata=_json.get('metadata', None),
|
|
215
|
+
status=_json.get('status', None),
|
|
216
|
+
settings=_json.get('settings', {}),
|
|
217
|
+
integrations=_json.get('integrations', None)
|
|
218
|
+
)
|
|
219
|
+
app.is_fetched = is_fetched
|
|
220
|
+
return app
|
dtlpy/entities/app_module.py
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import typing
|
|
3
|
-
from enum import Enum
|
|
4
|
-
|
|
5
|
-
from .. import entities, utilities
|
|
6
|
-
|
|
7
|
-
logger = logging.getLogger(name='dtlpy')
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class AppModule(entities.PackageModule, utilities.BaseServiceRunner):
|
|
11
|
-
def __init__(self, name, description):
|
|
12
|
-
super(AppModule, self).__init__()
|
|
13
|
-
self.name = name
|
|
14
|
-
self.description = description
|
|
15
|
-
|
|
16
|
-
def init(self):
|
|
17
|
-
"""
|
|
18
|
-
Default init function
|
|
19
|
-
:return:
|
|
20
|
-
"""
|
|
21
|
-
...
|
|
22
|
-
|
|
23
|
-
###############
|
|
24
|
-
# Decorators #
|
|
25
|
-
###############
|
|
26
|
-
def set_init(self, inputs=None):
|
|
27
|
-
def decorator(func: typing.Callable):
|
|
28
|
-
setattr(self, 'init', func)
|
|
29
|
-
setattr(self, func.__name__, func)
|
|
30
|
-
init_inputs, _ = self._function_io_from_def(func=func, inputs=inputs, outputs=None)
|
|
31
|
-
self.init_inputs = AppModule._parse_io(io_list=init_inputs)
|
|
32
|
-
return func
|
|
33
|
-
|
|
34
|
-
return decorator
|
|
35
|
-
|
|
36
|
-
def add_function(self, display_name=None, inputs=None, outputs=None):
|
|
37
|
-
"""
|
|
38
|
-
Add a function to the instance to be able to run in the FaaS.
|
|
39
|
-
|
|
40
|
-
:param display_name: Display name of the function
|
|
41
|
-
:param inputs: function inputs variable definitions. dictionary with strings for name and type {name: type}
|
|
42
|
-
:param outputs: function output variable definitions. dictionary with strings for name and type {name: type}
|
|
43
|
-
:return:
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
def decorator(func: typing.Callable):
|
|
47
|
-
if display_name is None:
|
|
48
|
-
d_name = func.__name__
|
|
49
|
-
else:
|
|
50
|
-
d_name = display_name
|
|
51
|
-
module_inputs, module_outputs = self._function_io_from_def(func=func, inputs=inputs, outputs=outputs)
|
|
52
|
-
defs = {"name": func.__name__,
|
|
53
|
-
"displayName": d_name,
|
|
54
|
-
"input": AppModule._parse_io(io_list=module_inputs),
|
|
55
|
-
"output": AppModule._parse_io(io_list=module_outputs)}
|
|
56
|
-
func.__dtlpy__ = defs
|
|
57
|
-
setattr(self, func.__name__, func)
|
|
58
|
-
self.functions.append(entities.PackageFunction.from_json(defs))
|
|
59
|
-
return func
|
|
60
|
-
|
|
61
|
-
return decorator
|
|
62
|
-
|
|
63
|
-
#########
|
|
64
|
-
# Utils #
|
|
65
|
-
#########
|
|
66
|
-
@staticmethod
|
|
67
|
-
def _function_io_from_def(func, inputs, outputs):
|
|
68
|
-
input_types = typing.get_type_hints(func)
|
|
69
|
-
hint_outputs = input_types.pop('return', None)
|
|
70
|
-
|
|
71
|
-
if outputs is None:
|
|
72
|
-
if hint_outputs is not None:
|
|
73
|
-
func_outputs = {'output': hint_outputs}
|
|
74
|
-
else:
|
|
75
|
-
func_outputs = dict()
|
|
76
|
-
else:
|
|
77
|
-
func_outputs = outputs
|
|
78
|
-
if inputs is None:
|
|
79
|
-
func_inputs = {name: t for name, t in input_types.items()}
|
|
80
|
-
else:
|
|
81
|
-
func_inputs = inputs
|
|
82
|
-
return func_inputs, func_outputs
|
|
83
|
-
|
|
84
|
-
@staticmethod
|
|
85
|
-
def _function_type_mapping(io_type):
|
|
86
|
-
mapping = {'str': entities.PackageInputType.STRING}
|
|
87
|
-
if io_type in mapping:
|
|
88
|
-
return mapping[io_type]
|
|
89
|
-
else:
|
|
90
|
-
return io_type
|
|
91
|
-
|
|
92
|
-
@staticmethod
|
|
93
|
-
def _parse_io(io_list: dict):
|
|
94
|
-
output = list()
|
|
95
|
-
if io_list is not None:
|
|
96
|
-
for io_name, io_type in io_list.items():
|
|
97
|
-
if isinstance(io_type, Enum):
|
|
98
|
-
io_type = io_type.name
|
|
99
|
-
if hasattr(io_type, '__args__'):
|
|
100
|
-
io_type = io_type.__args__[0]
|
|
101
|
-
if isinstance(io_type, type):
|
|
102
|
-
io_type = io_type.__name__
|
|
103
|
-
else:
|
|
104
|
-
io_type = str(io_type)
|
|
105
|
-
output.append({"name": io_name,
|
|
106
|
-
"type": AppModule._function_type_mapping(str(io_type))})
|
|
107
|
-
return output
|
|
1
|
+
import logging
|
|
2
|
+
import typing
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
from .. import entities, utilities
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(name='dtlpy')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AppModule(entities.PackageModule, utilities.BaseServiceRunner):
|
|
11
|
+
def __init__(self, name, description):
|
|
12
|
+
super(AppModule, self).__init__()
|
|
13
|
+
self.name = name
|
|
14
|
+
self.description = description
|
|
15
|
+
|
|
16
|
+
def init(self):
|
|
17
|
+
"""
|
|
18
|
+
Default init function
|
|
19
|
+
:return:
|
|
20
|
+
"""
|
|
21
|
+
...
|
|
22
|
+
|
|
23
|
+
###############
|
|
24
|
+
# Decorators #
|
|
25
|
+
###############
|
|
26
|
+
def set_init(self, inputs=None):
|
|
27
|
+
def decorator(func: typing.Callable):
|
|
28
|
+
setattr(self, 'init', func)
|
|
29
|
+
setattr(self, func.__name__, func)
|
|
30
|
+
init_inputs, _ = self._function_io_from_def(func=func, inputs=inputs, outputs=None)
|
|
31
|
+
self.init_inputs = AppModule._parse_io(io_list=init_inputs)
|
|
32
|
+
return func
|
|
33
|
+
|
|
34
|
+
return decorator
|
|
35
|
+
|
|
36
|
+
def add_function(self, display_name=None, inputs=None, outputs=None):
|
|
37
|
+
"""
|
|
38
|
+
Add a function to the instance to be able to run in the FaaS.
|
|
39
|
+
|
|
40
|
+
:param display_name: Display name of the function
|
|
41
|
+
:param inputs: function inputs variable definitions. dictionary with strings for name and type {name: type}
|
|
42
|
+
:param outputs: function output variable definitions. dictionary with strings for name and type {name: type}
|
|
43
|
+
:return:
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def decorator(func: typing.Callable):
|
|
47
|
+
if display_name is None:
|
|
48
|
+
d_name = func.__name__
|
|
49
|
+
else:
|
|
50
|
+
d_name = display_name
|
|
51
|
+
module_inputs, module_outputs = self._function_io_from_def(func=func, inputs=inputs, outputs=outputs)
|
|
52
|
+
defs = {"name": func.__name__,
|
|
53
|
+
"displayName": d_name,
|
|
54
|
+
"input": AppModule._parse_io(io_list=module_inputs),
|
|
55
|
+
"output": AppModule._parse_io(io_list=module_outputs)}
|
|
56
|
+
func.__dtlpy__ = defs
|
|
57
|
+
setattr(self, func.__name__, func)
|
|
58
|
+
self.functions.append(entities.PackageFunction.from_json(defs))
|
|
59
|
+
return func
|
|
60
|
+
|
|
61
|
+
return decorator
|
|
62
|
+
|
|
63
|
+
#########
|
|
64
|
+
# Utils #
|
|
65
|
+
#########
|
|
66
|
+
@staticmethod
|
|
67
|
+
def _function_io_from_def(func, inputs, outputs):
|
|
68
|
+
input_types = typing.get_type_hints(func)
|
|
69
|
+
hint_outputs = input_types.pop('return', None)
|
|
70
|
+
|
|
71
|
+
if outputs is None:
|
|
72
|
+
if hint_outputs is not None:
|
|
73
|
+
func_outputs = {'output': hint_outputs}
|
|
74
|
+
else:
|
|
75
|
+
func_outputs = dict()
|
|
76
|
+
else:
|
|
77
|
+
func_outputs = outputs
|
|
78
|
+
if inputs is None:
|
|
79
|
+
func_inputs = {name: t for name, t in input_types.items()}
|
|
80
|
+
else:
|
|
81
|
+
func_inputs = inputs
|
|
82
|
+
return func_inputs, func_outputs
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def _function_type_mapping(io_type):
|
|
86
|
+
mapping = {'str': entities.PackageInputType.STRING}
|
|
87
|
+
if io_type in mapping:
|
|
88
|
+
return mapping[io_type]
|
|
89
|
+
else:
|
|
90
|
+
return io_type
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def _parse_io(io_list: dict):
|
|
94
|
+
output = list()
|
|
95
|
+
if io_list is not None:
|
|
96
|
+
for io_name, io_type in io_list.items():
|
|
97
|
+
if isinstance(io_type, Enum):
|
|
98
|
+
io_type = io_type.name
|
|
99
|
+
if hasattr(io_type, '__args__'):
|
|
100
|
+
io_type = io_type.__args__[0]
|
|
101
|
+
if isinstance(io_type, type):
|
|
102
|
+
io_type = io_type.__name__
|
|
103
|
+
else:
|
|
104
|
+
io_type = str(io_type)
|
|
105
|
+
output.append({"name": io_name,
|
|
106
|
+
"type": AppModule._function_type_mapping(str(io_type))})
|
|
107
|
+
return output
|