dtlpy 1.90.37__py3-none-any.whl → 1.91.37__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/__version__.py +1 -1
- dtlpy/assets/lock_open.png +0 -0
- dtlpy/entities/analytic.py +118 -98
- dtlpy/entities/annotation.py +22 -31
- dtlpy/entities/annotation_collection.py +19 -21
- dtlpy/entities/app.py +13 -3
- dtlpy/entities/assignment.py +6 -0
- dtlpy/entities/base_entity.py +0 -24
- dtlpy/entities/dataset.py +1 -1
- dtlpy/entities/dpk.py +15 -0
- dtlpy/entities/execution.py +13 -1
- dtlpy/entities/filters.py +85 -6
- dtlpy/entities/integration.py +1 -1
- dtlpy/entities/item.py +26 -0
- dtlpy/entities/node.py +38 -2
- dtlpy/entities/ontology.py +61 -0
- dtlpy/entities/package_function.py +2 -0
- dtlpy/entities/package_module.py +13 -0
- dtlpy/entities/pipeline_execution.py +14 -6
- dtlpy/entities/prompt_item.py +10 -0
- dtlpy/entities/recipe.py +37 -0
- dtlpy/entities/service.py +31 -2
- dtlpy/ml/base_model_adapter.py +92 -2
- dtlpy/repositories/apps.py +12 -12
- dtlpy/repositories/assignments.py +1 -1
- dtlpy/repositories/datasets.py +1 -1
- dtlpy/repositories/dpks.py +29 -0
- dtlpy/repositories/executions.py +27 -30
- dtlpy/repositories/features.py +4 -1
- dtlpy/repositories/packages.py +6 -3
- dtlpy/repositories/pipeline_executions.py +5 -5
- dtlpy/repositories/services.py +28 -7
- dtlpy/repositories/tasks.py +8 -2
- dtlpy/repositories/uploader.py +2 -2
- dtlpy/services/api_client.py +15 -9
- {dtlpy-1.90.37.dist-info → dtlpy-1.91.37.dist-info}/METADATA +2 -2
- {dtlpy-1.90.37.dist-info → dtlpy-1.91.37.dist-info}/RECORD +50 -45
- tests/assets/__init__.py +0 -0
- tests/assets/models_flow/__init__.py +0 -0
- tests/assets/models_flow/failedmain.py +52 -0
- tests/assets/models_flow/main.py +51 -0
- tests/assets/models_flow/main_model.py +54 -0
- tests/features/environment.py +38 -1
- {dtlpy-1.90.37.data → dtlpy-1.91.37.data}/scripts/dlp +0 -0
- {dtlpy-1.90.37.data → dtlpy-1.91.37.data}/scripts/dlp.bat +0 -0
- {dtlpy-1.90.37.data → dtlpy-1.91.37.data}/scripts/dlp.py +0 -0
- {dtlpy-1.90.37.dist-info → dtlpy-1.91.37.dist-info}/LICENSE +0 -0
- {dtlpy-1.90.37.dist-info → dtlpy-1.91.37.dist-info}/WHEEL +0 -0
- {dtlpy-1.90.37.dist-info → dtlpy-1.91.37.dist-info}/entry_points.txt +0 -0
- {dtlpy-1.90.37.dist-info → dtlpy-1.91.37.dist-info}/top_level.txt +0 -0
dtlpy/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
version = '1.
|
|
1
|
+
version = '1.91.37'
|
dtlpy/assets/lock_open.png
CHANGED
|
Binary file
|
dtlpy/entities/analytic.py
CHANGED
|
@@ -14,6 +14,7 @@ class BaseSample:
|
|
|
14
14
|
event_type,
|
|
15
15
|
action,
|
|
16
16
|
status,
|
|
17
|
+
other_keys: dict = None
|
|
17
18
|
):
|
|
18
19
|
self.start_time = start_time
|
|
19
20
|
self.end_time = end_time
|
|
@@ -23,6 +24,31 @@ class BaseSample:
|
|
|
23
24
|
self.event_type = event_type
|
|
24
25
|
self.action = action
|
|
25
26
|
self.status = status
|
|
27
|
+
self.other_keys = other_keys
|
|
28
|
+
|
|
29
|
+
def to_json(self):
|
|
30
|
+
_json = {
|
|
31
|
+
'startTime': self.start_time,
|
|
32
|
+
'endTime': self.end_time,
|
|
33
|
+
'context': {
|
|
34
|
+
'projectId': self.project_id,
|
|
35
|
+
'projectOrgId': self.org_id,
|
|
36
|
+
'pipelineId': self.pipeline_id
|
|
37
|
+
},
|
|
38
|
+
'eventType': self.event_type,
|
|
39
|
+
'action': self.action,
|
|
40
|
+
'data': {
|
|
41
|
+
'status': self.status
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if self.other_keys is not None:
|
|
45
|
+
if 'context' in self.other_keys:
|
|
46
|
+
_json['context'].update(self.other_keys['context'])
|
|
47
|
+
if 'data' in self.other_keys:
|
|
48
|
+
_json['data'].update(self.other_keys['data'])
|
|
49
|
+
_json.update({k: v for k, v in self.other_keys.items() if k not in ['context', 'data']})
|
|
50
|
+
|
|
51
|
+
return _json
|
|
26
52
|
|
|
27
53
|
|
|
28
54
|
class ServiceSample(BaseSample):
|
|
@@ -47,16 +73,21 @@ class ServiceSample(BaseSample):
|
|
|
47
73
|
queue_size=None,
|
|
48
74
|
num_executions=None,
|
|
49
75
|
service_type: entities.ServiceType = None,
|
|
50
|
-
interval: int = None
|
|
76
|
+
interval: int = None,
|
|
77
|
+
driver_id: str = None,
|
|
78
|
+
other_keys: dict = None
|
|
51
79
|
):
|
|
52
|
-
super().__init__(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
80
|
+
super().__init__(
|
|
81
|
+
start_time=start_time,
|
|
82
|
+
end_time=end_time,
|
|
83
|
+
project_id=project_id,
|
|
84
|
+
org_id=org_id,
|
|
85
|
+
pipeline_id=pipeline_id,
|
|
86
|
+
event_type=event_type,
|
|
87
|
+
action=action,
|
|
88
|
+
status=status,
|
|
89
|
+
other_keys=other_keys
|
|
90
|
+
)
|
|
60
91
|
self.user_id = user_id
|
|
61
92
|
self.pipeline_node_id = pipeline_node_id
|
|
62
93
|
self.service_id = service_id
|
|
@@ -70,38 +101,32 @@ class ServiceSample(BaseSample):
|
|
|
70
101
|
self.num_executions = num_executions
|
|
71
102
|
self.service_type = service_type if service_type is not None else entities.ServiceType.REGULAR
|
|
72
103
|
self.interval = interval
|
|
104
|
+
self.driver_id = driver_id
|
|
73
105
|
|
|
74
106
|
def to_json(self):
|
|
75
|
-
_json =
|
|
76
|
-
|
|
77
|
-
'
|
|
78
|
-
'
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
'
|
|
90
|
-
'
|
|
91
|
-
'
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
'ram': self.ram,
|
|
97
|
-
'queueSize': self.queue_size,
|
|
98
|
-
'numExecutions': self.num_executions,
|
|
99
|
-
'interval': self.interval
|
|
100
|
-
}
|
|
101
|
-
}
|
|
107
|
+
_json = super().to_json()
|
|
108
|
+
_json['context'].update({
|
|
109
|
+
'userId': self.user_id,
|
|
110
|
+
'pipelineNodeId': self.pipeline_node_id,
|
|
111
|
+
'serviceId': self.service_id,
|
|
112
|
+
'podId': self.pod_id,
|
|
113
|
+
'podType': self.pod_type,
|
|
114
|
+
'serviceType': self.service_type
|
|
115
|
+
})
|
|
116
|
+
_json['data'].update({
|
|
117
|
+
'numRestarts': self.num_restarts,
|
|
118
|
+
'cpu': self.cpu,
|
|
119
|
+
'ram': self.ram,
|
|
120
|
+
'queueSize': self.queue_size,
|
|
121
|
+
'numExecutions': self.num_executions,
|
|
122
|
+
'interval': self.interval,
|
|
123
|
+
'driverId': self.driver_id
|
|
124
|
+
})
|
|
125
|
+
_json.update({
|
|
126
|
+
'entityType': self.entity_type
|
|
127
|
+
})
|
|
102
128
|
_json['context'] = {k: v for k, v in _json['context'].items() if v is not None}
|
|
103
129
|
_json['data'] = {k: v for k, v in _json['data'].items() if v is not None}
|
|
104
|
-
|
|
105
130
|
return {k: v for k, v in _json.items() if v is not None}
|
|
106
131
|
|
|
107
132
|
@classmethod
|
|
@@ -127,6 +152,8 @@ class ServiceSample(BaseSample):
|
|
|
127
152
|
queue_size=_json.get('data', {}).get('queueSize', None),
|
|
128
153
|
num_executions=_json.get('data', {}).get('numExecutions', None),
|
|
129
154
|
service_type=_json.get('type', entities.ServiceType.REGULAR),
|
|
155
|
+
interval=_json.get('data', {}).get('interval', None),
|
|
156
|
+
driver_id=_json.get('data', {}).get('driverId', None)
|
|
130
157
|
)
|
|
131
158
|
return inst
|
|
132
159
|
|
|
@@ -149,16 +176,20 @@ class ExecutionSample(BaseSample):
|
|
|
149
176
|
execution_id=None,
|
|
150
177
|
trigger_id=None,
|
|
151
178
|
function_name=None,
|
|
152
|
-
duration=None
|
|
179
|
+
duration=None,
|
|
180
|
+
other_keys: dict = None
|
|
153
181
|
):
|
|
154
|
-
super().__init__(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
182
|
+
super().__init__(
|
|
183
|
+
start_time=start_time,
|
|
184
|
+
end_time=end_time,
|
|
185
|
+
project_id=project_id,
|
|
186
|
+
org_id=org_id,
|
|
187
|
+
pipeline_id=pipeline_id,
|
|
188
|
+
event_type=event_type,
|
|
189
|
+
action=action,
|
|
190
|
+
status=status,
|
|
191
|
+
other_keys=other_keys
|
|
192
|
+
)
|
|
162
193
|
self.user_id = user_id
|
|
163
194
|
self.account_id = account_id
|
|
164
195
|
self.pipeline_node_id = pipeline_node_id
|
|
@@ -170,30 +201,22 @@ class ExecutionSample(BaseSample):
|
|
|
170
201
|
self.duration = duration
|
|
171
202
|
|
|
172
203
|
def to_json(self):
|
|
173
|
-
_json =
|
|
174
|
-
|
|
175
|
-
'
|
|
176
|
-
'
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
'action': self.action,
|
|
190
|
-
'data': {
|
|
191
|
-
'status': self.status,
|
|
192
|
-
'functionName': self.function_name,
|
|
193
|
-
'duration': self.duration
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return _json
|
|
204
|
+
_json = super().to_json()
|
|
205
|
+
_json['context'].update({
|
|
206
|
+
'userId': self.user_id,
|
|
207
|
+
'accountId': self.account_id,
|
|
208
|
+
'pipelineNodeId': self.pipeline_node_id,
|
|
209
|
+
'pipelineExecutionId': self.pipeline_execution_id,
|
|
210
|
+
'serviceId': self.service_id,
|
|
211
|
+
'triggerId': self.trigger_id
|
|
212
|
+
})
|
|
213
|
+
_json['data'].update({
|
|
214
|
+
'functionName': self.function_name,
|
|
215
|
+
'duration': self.duration
|
|
216
|
+
})
|
|
217
|
+
_json['context'] = {k: v for k, v in _json['context'].items() if v is not None}
|
|
218
|
+
_json['data'] = {k: v for k, v in _json['data'].items() if v is not None}
|
|
219
|
+
return {k: v for k, v in _json.items() if v is not None}
|
|
197
220
|
|
|
198
221
|
@classmethod
|
|
199
222
|
def from_json(cls, _json):
|
|
@@ -234,15 +257,19 @@ class PipelineExecutionSample(BaseSample):
|
|
|
234
257
|
pipeline_execution_id=None,
|
|
235
258
|
trigger_id=None,
|
|
236
259
|
node_status=None,
|
|
260
|
+
other_keys: dict = None
|
|
237
261
|
):
|
|
238
|
-
super().__init__(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
262
|
+
super().__init__(
|
|
263
|
+
start_time=start_time,
|
|
264
|
+
end_time=end_time,
|
|
265
|
+
project_id=project_id,
|
|
266
|
+
org_id=org_id,
|
|
267
|
+
pipeline_id=pipeline_id,
|
|
268
|
+
event_type=event_type,
|
|
269
|
+
action=action,
|
|
270
|
+
status=status,
|
|
271
|
+
other_keys=other_keys
|
|
272
|
+
)
|
|
246
273
|
self.account_id = account_id
|
|
247
274
|
self.pipeline_node_id = pipeline_node_id
|
|
248
275
|
self.pipeline_execution_id = pipeline_execution_id
|
|
@@ -250,26 +277,19 @@ class PipelineExecutionSample(BaseSample):
|
|
|
250
277
|
self.node_status = node_status
|
|
251
278
|
|
|
252
279
|
def to_json(self):
|
|
253
|
-
_json =
|
|
254
|
-
|
|
255
|
-
'
|
|
256
|
-
'
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
'data': {
|
|
267
|
-
'status': self.status,
|
|
268
|
-
'nodeId': self.pipeline_node_id,
|
|
269
|
-
'nodeStatus': self.node_status
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return _json
|
|
280
|
+
_json = super().to_json()
|
|
281
|
+
_json['context'].update({
|
|
282
|
+
'accountId': self.account_id,
|
|
283
|
+
'pipelineNodeId': self.pipeline_node_id,
|
|
284
|
+
'pipelineExecutionId': self.pipeline_execution_id,
|
|
285
|
+
'triggerId': self.trigger_id
|
|
286
|
+
})
|
|
287
|
+
_json['data'].update({
|
|
288
|
+
'nodeStatus': self.node_status
|
|
289
|
+
})
|
|
290
|
+
_json['context'] = {k: v for k, v in _json['context'].items() if v is not None}
|
|
291
|
+
_json['data'] = {k: v for k, v in _json['data'].items() if v is not None}
|
|
292
|
+
return {k: v for k, v in _json.items() if v is not None}
|
|
273
293
|
|
|
274
294
|
@classmethod
|
|
275
295
|
def from_json(cls, _json):
|
dtlpy/entities/annotation.py
CHANGED
|
@@ -418,28 +418,25 @@ class Annotation(entities.BaseEntity):
|
|
|
418
418
|
def label(self, label):
|
|
419
419
|
self.annotation_definition.label = label
|
|
420
420
|
|
|
421
|
-
@property
|
|
422
|
-
def _use_attributes_2(self):
|
|
423
|
-
if self.__client_api is None and self._item is None:
|
|
424
|
-
return os.environ.get("USE_ATTRIBUTE_2", 'false') == 'true'
|
|
425
|
-
return self._client_api.attributes_mode.use_attributes_2
|
|
426
|
-
|
|
427
421
|
@property
|
|
428
422
|
def attributes(self):
|
|
429
|
-
|
|
423
|
+
if self._recipe_2_attributes or not self.annotation_definition.attributes:
|
|
424
|
+
return self._recipe_2_attributes
|
|
425
|
+
return self.annotation_definition.attributes
|
|
430
426
|
|
|
431
427
|
@attributes.setter
|
|
432
428
|
def attributes(self, attributes):
|
|
433
|
-
if
|
|
434
|
-
if not isinstance(attributes, dict):
|
|
435
|
-
raise ValueError(
|
|
436
|
-
'Attributes must be a dict. If you are using v1 attributes please use dl.use_attributes_2(False)')
|
|
429
|
+
if isinstance(attributes, dict):
|
|
437
430
|
self._recipe_2_attributes = attributes
|
|
438
|
-
|
|
439
|
-
if not isinstance(attributes, list):
|
|
440
|
-
raise ValueError(
|
|
441
|
-
'Attributes must be a list. If you are using v2 attributes please use dl.use_attributes_2(True)')
|
|
431
|
+
elif isinstance(attributes, list):
|
|
442
432
|
self.annotation_definition.attributes = attributes
|
|
433
|
+
elif attributes is None:
|
|
434
|
+
if self._recipe_2_attributes:
|
|
435
|
+
self._recipe_2_attributes = {}
|
|
436
|
+
if self.annotation_definition.attributes:
|
|
437
|
+
self.annotation_definition.attributes = []
|
|
438
|
+
else:
|
|
439
|
+
raise ValueError('Attributes must be a dictionary or a list')
|
|
443
440
|
|
|
444
441
|
@property
|
|
445
442
|
def color(self):
|
|
@@ -1362,12 +1359,8 @@ class Annotation(entities.BaseEntity):
|
|
|
1362
1359
|
object_id = _json['metadata']['system'].get('objectId', object_id)
|
|
1363
1360
|
status = _json['metadata']['system'].get('status', status)
|
|
1364
1361
|
|
|
1365
|
-
if client_api is not None:
|
|
1366
|
-
recipe_2_attributes = client_api.attributes_mode.use_attributes_2
|
|
1367
|
-
else:
|
|
1368
|
-
recipe_2_attributes = False
|
|
1369
1362
|
named_attributes = metadata.get('system', dict()).get('attributes', None)
|
|
1370
|
-
attributes = named_attributes if
|
|
1363
|
+
attributes = named_attributes if named_attributes else _json.get('attributes', None)
|
|
1371
1364
|
|
|
1372
1365
|
first_frame_attributes = attributes
|
|
1373
1366
|
first_frame_coordinates = list()
|
|
@@ -1598,7 +1591,7 @@ class Annotation(entities.BaseEntity):
|
|
|
1598
1591
|
if isinstance(self.annotation_definition, entities.Description):
|
|
1599
1592
|
_json['metadata']['system']['system'] = True
|
|
1600
1593
|
|
|
1601
|
-
if self.
|
|
1594
|
+
if self._recipe_2_attributes is not None:
|
|
1602
1595
|
_json['metadata']['system']['attributes'] = self._recipe_2_attributes
|
|
1603
1596
|
if 'attributes' in self._platform_dict:
|
|
1604
1597
|
_json['attributes'] = self._platform_dict['attributes']
|
|
@@ -1685,20 +1678,18 @@ class FrameAnnotation(entities.BaseEntity):
|
|
|
1685
1678
|
|
|
1686
1679
|
@property
|
|
1687
1680
|
def attributes(self):
|
|
1688
|
-
|
|
1681
|
+
if self._recipe_2_attributes or not self.annotation_definition.attributes:
|
|
1682
|
+
return self._recipe_2_attributes
|
|
1683
|
+
return self.annotation_definition.attributes
|
|
1689
1684
|
|
|
1690
1685
|
@attributes.setter
|
|
1691
1686
|
def attributes(self, attributes):
|
|
1692
|
-
if
|
|
1693
|
-
if not isinstance(attributes, dict):
|
|
1694
|
-
raise ValueError(
|
|
1695
|
-
'Attributes must be a dict. If you are using v1 attributes please use dl.use_attributes_2(False)')
|
|
1687
|
+
if isinstance(attributes, dict):
|
|
1696
1688
|
self._recipe_2_attributes = attributes
|
|
1697
|
-
|
|
1698
|
-
if not isinstance(attributes, list):
|
|
1699
|
-
raise ValueError(
|
|
1700
|
-
'Attributes must be a list. If you are using v2 attributes please use dl.use_attributes_2(True)')
|
|
1689
|
+
elif isinstance(attributes, list):
|
|
1701
1690
|
self.annotation_definition.attributes = attributes
|
|
1691
|
+
else:
|
|
1692
|
+
raise ValueError('Attributes must be a dictionary or a list')
|
|
1702
1693
|
|
|
1703
1694
|
@property
|
|
1704
1695
|
def geo(self):
|
|
@@ -1879,7 +1870,7 @@ class FrameAnnotation(entities.BaseEntity):
|
|
|
1879
1870
|
'data': self.coordinates
|
|
1880
1871
|
}
|
|
1881
1872
|
|
|
1882
|
-
if self.annotation.
|
|
1873
|
+
if self.annotation._recipe_2_attributes:
|
|
1883
1874
|
snapshot_dict['namedAttributes'] = self._recipe_2_attributes
|
|
1884
1875
|
else:
|
|
1885
1876
|
snapshot_dict['attributes'] = self.attributes
|
|
@@ -63,7 +63,7 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
63
63
|
"""
|
|
64
64
|
Add annotations to collection
|
|
65
65
|
|
|
66
|
-
:param annotation_definition: dl.Polygon, dl.Segmentation, dl.Point, dl.Box etc
|
|
66
|
+
:param annotation_definition: dl.Polygon, dl.Segmentation, dl.Point, dl.Box etc.
|
|
67
67
|
:param object_id: Object id (any id given by user). If video - must input to match annotations between frames
|
|
68
68
|
:param frame_num: video only, number of frame
|
|
69
69
|
:param end_frame_num: video only, the end frame of the annotation
|
|
@@ -72,12 +72,12 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
72
72
|
:param automated:
|
|
73
73
|
:param fixed: video only, mark frame as fixed
|
|
74
74
|
:param object_visible: video only, does the annotated object is visible
|
|
75
|
-
:param metadata: optional
|
|
75
|
+
:param metadata: optional, metadata dictionary for annotation
|
|
76
76
|
:param parent_id: set a parent for this annotation (parent annotation ID)
|
|
77
77
|
:param prompt_id: Connect the annotation with a specific prompt in a dl.PromptItem
|
|
78
|
-
:param model_info: optional - set model on annotation {'confidence':0 [Mandatory], (Float between 0-1)
|
|
79
|
-
'name'
|
|
80
|
-
'model_id':''[Optional]
|
|
78
|
+
:param model_info: optional - set model on annotation {'confidence': 0, # [Mandatory], (Float between 0-1)
|
|
79
|
+
'name': '', # [Optional], ('name' refers to 'model_name')
|
|
80
|
+
'model_id': ''} # [Optional]
|
|
81
81
|
:return:
|
|
82
82
|
"""
|
|
83
83
|
if model_info is not None:
|
|
@@ -163,7 +163,7 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
163
163
|
annotation_format: entities.ViewAnnotationOptions = entities.ViewAnnotationOptions.MASK,
|
|
164
164
|
label_instance_dict=None,
|
|
165
165
|
color=None,
|
|
166
|
-
alpha=1
|
|
166
|
+
alpha=1.,
|
|
167
167
|
frame_num=None):
|
|
168
168
|
"""
|
|
169
169
|
Show annotations according to annotation_format
|
|
@@ -188,8 +188,7 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
188
188
|
|
|
189
189
|
image = builder.show(image='ndarray',
|
|
190
190
|
thickness=1,
|
|
191
|
-
annotation_format=dl.VIEW_ANNOTATION_OPTIONS_MASK
|
|
192
|
-
)
|
|
191
|
+
annotation_format=dl.VIEW_ANNOTATION_OPTIONS_MASK)
|
|
193
192
|
"""
|
|
194
193
|
# if 'video' in self.item.mimetype and (annotation_format != 'json' or annotation_format != ['json']):
|
|
195
194
|
# raise PlatformException('400', 'Cannot show mask or instance of video item')
|
|
@@ -210,7 +209,7 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
210
209
|
else:
|
|
211
210
|
rest_annotations.append(annotation)
|
|
212
211
|
all_annotations = segment_annotations + rest_annotations
|
|
213
|
-
# gor over all annotations and put the id where the annotations
|
|
212
|
+
# gor over all annotations and put the id where the annotations are
|
|
214
213
|
for annotation in all_annotations:
|
|
215
214
|
# get the mask of the annotation
|
|
216
215
|
image = annotation.show(thickness=thickness,
|
|
@@ -231,7 +230,7 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
231
230
|
thickness=1,
|
|
232
231
|
annotation_format=entities.ViewAnnotationOptions.ANNOTATION_ON_IMAGE,
|
|
233
232
|
with_text=False,
|
|
234
|
-
alpha=1):
|
|
233
|
+
alpha=1.):
|
|
235
234
|
"""
|
|
236
235
|
create a video from frames
|
|
237
236
|
|
|
@@ -240,6 +239,8 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
240
239
|
:param thickness: int - thickness of the annotations
|
|
241
240
|
:param annotation_format: str - ViewAnnotationOptions - annotations format
|
|
242
241
|
:param with_text: bool - if True show the label in the output
|
|
242
|
+
:param float alpha: opacity value [0 1], default 1
|
|
243
|
+
|
|
243
244
|
"""
|
|
244
245
|
try:
|
|
245
246
|
import cv2
|
|
@@ -288,7 +289,8 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
288
289
|
if reader is not None:
|
|
289
290
|
reader.release()
|
|
290
291
|
|
|
291
|
-
|
|
292
|
+
@staticmethod
|
|
293
|
+
def _set_flip_args(orientation):
|
|
292
294
|
try:
|
|
293
295
|
import cv2
|
|
294
296
|
except (ImportError, ModuleNotFoundError):
|
|
@@ -329,10 +331,10 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
329
331
|
:param int height: height
|
|
330
332
|
:param int width: width
|
|
331
333
|
:param int thickness: thickness
|
|
332
|
-
:param bool with_text: add a text to
|
|
334
|
+
:param bool with_text: add a text to an image
|
|
333
335
|
:param int orientation: the image orientation
|
|
334
336
|
:param float alpha: opacity value [0 1], default 1
|
|
335
|
-
:return: file path of the
|
|
337
|
+
:return: file path of the download annotation
|
|
336
338
|
:rtype: str
|
|
337
339
|
|
|
338
340
|
**Example**:
|
|
@@ -521,8 +523,8 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
521
523
|
:param dict _json: platform json
|
|
522
524
|
:param dtlpy.entities.item.Item item: item
|
|
523
525
|
:param client_api: ApiClient entity
|
|
524
|
-
:param bool is_video: is video
|
|
525
|
-
:param fps: video
|
|
526
|
+
:param bool is_video: whether the item is video
|
|
527
|
+
:param fps: frame rate of the video
|
|
526
528
|
:param float height: height
|
|
527
529
|
:param float width: width
|
|
528
530
|
:param bool is_audio: is audio
|
|
@@ -614,19 +616,15 @@ class AnnotationCollection(entities.BaseEntity):
|
|
|
614
616
|
start_time = datetime.timedelta(hours=float(h), minutes=float(m), seconds=float(s)).total_seconds()
|
|
615
617
|
h, m, s = caption.end.split(':')
|
|
616
618
|
end_time = datetime.timedelta(hours=float(h), minutes=float(m), seconds=float(s)).total_seconds()
|
|
617
|
-
if self.item.fps is not None:
|
|
618
|
-
start_frame = round(start_time * self.item.fps)
|
|
619
|
-
else:
|
|
620
|
-
raise ValueError('Item do not have fps, please wait for video-preprocess to complete')
|
|
621
619
|
annotation_definition = entities.Subtitle(text=caption.text, label='Text')
|
|
622
620
|
annotation = entities.Annotation.new(
|
|
623
621
|
annotation_definition=annotation_definition,
|
|
624
|
-
frame_num=start_frame,
|
|
625
622
|
item=self.item,
|
|
626
623
|
start_time=start_time)
|
|
627
624
|
|
|
628
625
|
annotation.add_frames(annotation_definition=annotation_definition,
|
|
629
|
-
|
|
626
|
+
start_time=start_time,
|
|
627
|
+
end_time=end_time)
|
|
630
628
|
|
|
631
629
|
self.annotations.append(annotation)
|
|
632
630
|
|
dtlpy/entities/app.py
CHANGED
|
@@ -47,6 +47,7 @@ class App(entities.BaseEntity):
|
|
|
47
47
|
custom_installation = attr.ib(type=dict)
|
|
48
48
|
metadata = attr.ib(type=dict)
|
|
49
49
|
status = attr.ib(type=entities.CompositionStatus)
|
|
50
|
+
settings = attr.ib(type=dict)
|
|
50
51
|
|
|
51
52
|
# sdk
|
|
52
53
|
_project = attr.ib(type=entities.Project, repr=False)
|
|
@@ -55,10 +56,11 @@ class App(entities.BaseEntity):
|
|
|
55
56
|
|
|
56
57
|
@_repositories.default
|
|
57
58
|
def set_repositories(self):
|
|
58
|
-
reps = namedtuple('repositories', field_names=['projects', 'apps'])
|
|
59
|
+
reps = namedtuple('repositories', field_names=['projects', 'apps', 'compositions'])
|
|
59
60
|
return reps(
|
|
60
61
|
projects=repositories.Projects(client_api=self._client_api),
|
|
61
|
-
apps=repositories.Apps(client_api=self._client_api, project=self._project)
|
|
62
|
+
apps=repositories.Apps(client_api=self._client_api, project=self._project),
|
|
63
|
+
compositions=repositories.Compositions(client_api=self._client_api, project=self._project)
|
|
62
64
|
)
|
|
63
65
|
|
|
64
66
|
@property
|
|
@@ -77,6 +79,11 @@ class App(entities.BaseEntity):
|
|
|
77
79
|
assert isinstance(self._repositories.apps, repositories.Apps)
|
|
78
80
|
return self._repositories.apps
|
|
79
81
|
|
|
82
|
+
@property
|
|
83
|
+
def compositions(self):
|
|
84
|
+
assert isinstance(self._repositories.compositions, repositories.Compositions)
|
|
85
|
+
return self._repositories.compositions
|
|
86
|
+
|
|
80
87
|
def uninstall(self):
|
|
81
88
|
"""
|
|
82
89
|
Uninstall an app installed app from the project.
|
|
@@ -177,6 +184,8 @@ class App(entities.BaseEntity):
|
|
|
177
184
|
_json['metadata'] = self.metadata
|
|
178
185
|
if self.status is not None:
|
|
179
186
|
_json['status'] = self.status
|
|
187
|
+
if self.settings != {}:
|
|
188
|
+
_json['settings'] = self.settings
|
|
180
189
|
|
|
181
190
|
return _json
|
|
182
191
|
|
|
@@ -200,7 +209,8 @@ class App(entities.BaseEntity):
|
|
|
200
209
|
client_api=client_api,
|
|
201
210
|
project=project,
|
|
202
211
|
metadata=_json.get('metadata', None),
|
|
203
|
-
status=_json.get('status', None)
|
|
212
|
+
status=_json.get('status', None),
|
|
213
|
+
settings=_json.get('settings', {})
|
|
204
214
|
)
|
|
205
215
|
app.is_fetched = is_fetched
|
|
206
216
|
return app
|
dtlpy/entities/assignment.py
CHANGED
|
@@ -19,6 +19,8 @@ class Assignment(entities.BaseEntity):
|
|
|
19
19
|
metadata = attr.ib(repr=False)
|
|
20
20
|
id = attr.ib()
|
|
21
21
|
url = attr.ib(repr=False)
|
|
22
|
+
updated_at = attr.ib(repr=False)
|
|
23
|
+
updated_by = attr.ib(repr=False)
|
|
22
24
|
task_id = attr.ib(repr=False)
|
|
23
25
|
dataset_id = attr.ib(repr=False)
|
|
24
26
|
annotation_status = attr.ib(repr=False)
|
|
@@ -62,6 +64,8 @@ class Assignment(entities.BaseEntity):
|
|
|
62
64
|
metadata=metadata,
|
|
63
65
|
url=_json.get('url', None),
|
|
64
66
|
id=_json['id'],
|
|
67
|
+
updated_by=_json.get('updatedBy', None),
|
|
68
|
+
updated_at=_json.get('updatedAt', None),
|
|
65
69
|
client_api=client_api,
|
|
66
70
|
project=project,
|
|
67
71
|
dataset=dataset,
|
|
@@ -143,6 +147,8 @@ class Assignment(entities.BaseEntity):
|
|
|
143
147
|
attr.fields(Assignment)._dataset,
|
|
144
148
|
attr.fields(Assignment)._task,
|
|
145
149
|
attr.fields(Assignment).annotation_status,
|
|
150
|
+
attr.fields(Assignment).updated_at,
|
|
151
|
+
attr.fields(Assignment).updated_by,
|
|
146
152
|
attr.fields(Assignment).item_status,
|
|
147
153
|
attr.fields(Assignment).total_items,
|
|
148
154
|
attr.fields(Assignment).for_review,
|
dtlpy/entities/base_entity.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import typing_extensions
|
|
2
1
|
import functools
|
|
3
2
|
import logging
|
|
4
3
|
import enum
|
|
@@ -99,22 +98,6 @@ class DlEntity(object):
|
|
|
99
98
|
"""
|
|
100
99
|
return miscellaneous.List([self]).to_df(show_all=show_all, columns=columns)
|
|
101
100
|
|
|
102
|
-
# def __repr__(self):
|
|
103
|
-
# string = '{}('.format(self.__class__.__name__)
|
|
104
|
-
# for prop in dir(self):
|
|
105
|
-
# if isinstance(prop, DlProperty) and prop.repr is True:
|
|
106
|
-
# string += '{}={}'.format()
|
|
107
|
-
# params = json.dumps(self._dict, indent=4)
|
|
108
|
-
# return "{}({})".format(self.__class__.__name__, params)
|
|
109
|
-
|
|
110
|
-
# def __repr__(self):
|
|
111
|
-
# self.print()
|
|
112
|
-
|
|
113
|
-
# def __getattribute__(self, attr):
|
|
114
|
-
# if super(BaseEntity, self).__getattribute__(attr) is None:
|
|
115
|
-
# pass
|
|
116
|
-
# return super(BaseEntity, self).__getattribute__(attr)
|
|
117
|
-
|
|
118
101
|
|
|
119
102
|
class DlProperty:
|
|
120
103
|
def __init__(self, location=None, default='NODEFAULT', _type=None, _kls=None):
|
|
@@ -207,16 +190,9 @@ class DlProperty:
|
|
|
207
190
|
|
|
208
191
|
# instantiate dictionary to the type
|
|
209
192
|
value = self._to_instance(_dict=value)
|
|
210
|
-
|
|
211
|
-
# isinstance(value, typing_extensions.get_args(self._type))
|
|
212
193
|
return value
|
|
213
194
|
|
|
214
195
|
def __set__(self, instance, value):
|
|
215
|
-
# TODO still not working properly. need to fix this validation
|
|
216
|
-
# if not isinstance(value, typing_extensions.get_args(self._type)):
|
|
217
|
-
# logger.warning(
|
|
218
|
-
# f'Incorrect typing for type: {type(instance)}. {self.location} must be of type {self._type}. Received: {type(value)}')
|
|
219
|
-
_client_api = getattr(instance, 'client_api', None)
|
|
220
196
|
|
|
221
197
|
# validate - if validator is set
|
|
222
198
|
if self._validator is not None:
|
dtlpy/entities/dataset.py
CHANGED
|
@@ -240,7 +240,7 @@ class Dataset(entities.BaseEntity):
|
|
|
240
240
|
|
|
241
241
|
@property
|
|
242
242
|
def platform_url(self):
|
|
243
|
-
return self._client_api._get_resource_url("projects/{}/datasets/{}".format(self.project.id, self.id))
|
|
243
|
+
return self._client_api._get_resource_url("projects/{}/datasets/{}/items".format(self.project.id, self.id))
|
|
244
244
|
|
|
245
245
|
@readonly.setter
|
|
246
246
|
def readonly(self, state):
|