dtlpy 1.107.8__py3-none-any.whl → 1.109.19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. dtlpy/__init__.py +1 -7
  2. dtlpy/__version__.py +1 -1
  3. dtlpy/entities/__init__.py +5 -4
  4. dtlpy/entities/annotation.py +28 -57
  5. dtlpy/entities/annotation_definitions/base_annotation_definition.py +6 -14
  6. dtlpy/entities/app.py +1 -1
  7. dtlpy/entities/command.py +10 -7
  8. dtlpy/entities/compute.py +77 -94
  9. dtlpy/entities/dataset.py +29 -14
  10. dtlpy/entities/dpk.py +1 -0
  11. dtlpy/entities/filters.py +7 -6
  12. dtlpy/entities/item.py +7 -14
  13. dtlpy/entities/node.py +0 -12
  14. dtlpy/entities/service.py +0 -9
  15. dtlpy/entities/service_driver.py +118 -0
  16. dtlpy/entities/trigger.py +1 -1
  17. dtlpy/new_instance.py +1 -1
  18. dtlpy/repositories/__init__.py +2 -1
  19. dtlpy/repositories/apps.py +8 -4
  20. dtlpy/repositories/collections.py +86 -34
  21. dtlpy/repositories/commands.py +14 -4
  22. dtlpy/repositories/computes.py +173 -127
  23. dtlpy/repositories/datasets.py +20 -9
  24. dtlpy/repositories/downloader.py +20 -8
  25. dtlpy/repositories/dpks.py +26 -1
  26. dtlpy/repositories/items.py +5 -2
  27. dtlpy/repositories/service_drivers.py +213 -0
  28. dtlpy/repositories/services.py +6 -0
  29. dtlpy/repositories/uploader.py +4 -0
  30. dtlpy-1.109.19.dist-info/METADATA +172 -0
  31. {dtlpy-1.107.8.dist-info → dtlpy-1.109.19.dist-info}/RECORD +39 -37
  32. tests/features/environment.py +16 -15
  33. dtlpy-1.107.8.dist-info/METADATA +0 -69
  34. {dtlpy-1.107.8.data → dtlpy-1.109.19.data}/scripts/dlp +0 -0
  35. {dtlpy-1.107.8.data → dtlpy-1.109.19.data}/scripts/dlp.bat +0 -0
  36. {dtlpy-1.107.8.data → dtlpy-1.109.19.data}/scripts/dlp.py +0 -0
  37. {dtlpy-1.107.8.dist-info → dtlpy-1.109.19.dist-info}/LICENSE +0 -0
  38. {dtlpy-1.107.8.dist-info → dtlpy-1.109.19.dist-info}/WHEEL +0 -0
  39. {dtlpy-1.107.8.dist-info → dtlpy-1.109.19.dist-info}/entry_points.txt +0 -0
  40. {dtlpy-1.107.8.dist-info → dtlpy-1.109.19.dist-info}/top_level.txt +0 -0
@@ -128,7 +128,7 @@ class Datasets:
128
128
 
129
129
  @staticmethod
130
130
  def _build_payload(filters, include_feature_vectors, include_annotations,
131
- export_type, annotation_filters, feature_vector_filters, dataset_lock, lock_timeout_sec):
131
+ export_type, annotation_filters, feature_vector_filters, dataset_lock, lock_timeout_sec, export_summary):
132
132
  valid_list = [e.value for e in entities.ExportType]
133
133
  valid_types = ', '.join(valid_list)
134
134
  if export_type not in ['json', 'zip']:
@@ -161,6 +161,9 @@ class Datasets:
161
161
  if dataset_lock:
162
162
  payload['datasetLock'] = dataset_lock
163
163
 
164
+ if export_summary:
165
+ payload['summary'] = export_summary
166
+
164
167
  if lock_timeout_sec:
165
168
  payload['lockTimeoutSec'] = lock_timeout_sec
166
169
 
@@ -636,7 +639,8 @@ class Datasets:
636
639
  export_type: entities.ExportType = entities.ExportType.JSON,
637
640
  timeout: int = 0,
638
641
  dataset_lock: bool = False,
639
- lock_timeout_sec: int = None):
642
+ lock_timeout_sec: int = None,
643
+ export_summary: bool = False):
640
644
  """
641
645
  Export dataset items and annotations.
642
646
 
@@ -654,6 +658,7 @@ class Datasets:
654
658
  :param bool include_feature_vectors: Include item feature vectors in the export
655
659
  :param bool include_annotations: Include item annotations in the export
656
660
  :param bool dataset_lock: Make dataset readonly during the export
661
+ :param bool export_summary: Get Summary of the dataset export
657
662
  :param int lock_timeout_sec: Timeout for locking the dataset during export in seconds
658
663
  :param entities.ExportType export_type: Type of export ('json' or 'zip')
659
664
  :param int timeout: Maximum time in seconds to wait for the export to complete
@@ -669,12 +674,14 @@ class Datasets:
669
674
  include_feature_vectors=True,
670
675
  include_annotations=True,
671
676
  export_type=dl.ExportType.JSON,
672
- dataset_lock=True
673
- lock_timeout_sec=300)
677
+ dataset_lock=True,
678
+ lock_timeout_sec=300,
679
+ export_summary=False)
674
680
  """
675
681
  dataset_id = self._resolve_dataset_id(dataset, dataset_name, dataset_id)
676
682
  payload = self._build_payload(filters, include_feature_vectors, include_annotations,
677
- export_type, annotation_filters, feature_vector_filters, dataset_lock, lock_timeout_sec)
683
+ export_type, annotation_filters, feature_vector_filters,
684
+ dataset_lock, lock_timeout_sec, export_summary)
678
685
 
679
686
  success, response = self._client_api.gen_request(req_type='post', path=f'/datasets/{dataset_id}/export',
680
687
  json_req=payload)
@@ -940,7 +947,8 @@ class Datasets:
940
947
  alpha: float = None,
941
948
  export_version=entities.ExportVersion.V1,
942
949
  dataset_lock: bool = False,
943
- lock_timeout_sec: int = None
950
+ lock_timeout_sec: int = None,
951
+ export_summary: bool = False,
944
952
  ) -> str:
945
953
  """
946
954
  Download dataset's annotations by filters.
@@ -968,6 +976,7 @@ class Datasets:
968
976
  :param str export_version: exported items will have original extension in filename, `V1` - no original extension in filenames
969
977
  :return: local_path of the directory where all the downloaded item
970
978
  :param bool dataset_lock: optional - default = False
979
+ :param bool export_summary: optional - default = False
971
980
  :param int lock_timeout_sec: optional
972
981
  :rtype: str
973
982
 
@@ -982,8 +991,9 @@ class Datasets:
982
991
  thickness=1,
983
992
  with_text=False,
984
993
  alpha=1,
985
- dataset_lock=False
986
- lock_timeout_sec=300
994
+ dataset_lock=False,
995
+ lock_timeout_sec=300,
996
+ export_summary=False
987
997
  )
988
998
  """
989
999
  if annotation_options is None:
@@ -1045,7 +1055,8 @@ class Datasets:
1045
1055
  filter_output_annotations=filter_output_annotations,
1046
1056
  export_version=export_version,
1047
1057
  dataset_lock=dataset_lock,
1048
- lock_timeout_sec=lock_timeout_sec
1058
+ lock_timeout_sec=lock_timeout_sec,
1059
+ export_summary=export_summary
1049
1060
  )
1050
1061
  if annotation_options:
1051
1062
  pages = dataset.items.list(filters=filters)
@@ -48,7 +48,8 @@ class Downloader:
48
48
  alpha=1,
49
49
  export_version=entities.ExportVersion.V1,
50
50
  dataset_lock=False,
51
- lock_timeout_sec=None
51
+ lock_timeout_sec=None,
52
+ export_summary=False
52
53
  ):
53
54
  """
54
55
  Download dataset by filters.
@@ -75,6 +76,7 @@ class Downloader:
75
76
  :param alpha: opacity value [0 1], default 1
76
77
  :param str export_version: exported items will have original extension in filename, `V1` - no original extension in filenames
77
78
  :param bool dataset_lock: optional - default = False
79
+ :param bool export_summary: optional - default = False
78
80
  :param int lock_timeout_sec: optional
79
81
  :return: Output (list)
80
82
  """
@@ -201,7 +203,8 @@ class Downloader:
201
203
  'filter_output_annotations': filter_output_annotations,
202
204
  'export_version': export_version,
203
205
  'dataset_lock': dataset_lock,
204
- 'lock_timeout_sec': lock_timeout_sec
206
+ 'lock_timeout_sec': lock_timeout_sec,
207
+ 'export_summary': export_summary
205
208
  })
206
209
  ###############
207
210
  # downloading #
@@ -369,7 +372,8 @@ class Downloader:
369
372
  filter_output_annotations=False,
370
373
  export_version=entities.ExportVersion.V1,
371
374
  dataset_lock=False,
372
- lock_timeout_sec=None
375
+ lock_timeout_sec=None,
376
+ export_summary=False
373
377
  ):
374
378
  """
375
379
  Download annotations json for entire dataset
@@ -384,6 +388,7 @@ class Downloader:
384
388
  :param filter_output_annotations: default - False, given an export by filter - determine if to filter out annotations
385
389
  :param str export_version: exported items will have original extension in filename, `V1` - no original extension in filenames
386
390
  :param bool dataset_lock: optional - default = False
391
+ :param bool export_summary: optional - default = False
387
392
  :param int lock_timeout_sec: optional
388
393
  :return:
389
394
  """
@@ -409,6 +414,9 @@ class Downloader:
409
414
  payload['annotations']['filter'] = filter_output_annotations
410
415
  if dataset_lock:
411
416
  payload['datasetLock'] = dataset_lock
417
+
418
+ if export_summary:
419
+ payload['summary'] = export_summary
412
420
 
413
421
  if lock_timeout_sec:
414
422
  payload['lockTimeoutSec'] = lock_timeout_sec
@@ -694,7 +702,8 @@ class Downloader:
694
702
  raise PlatformException(response)
695
703
  else:
696
704
  _, ext = os.path.splitext(item.metadata['system']['shebang']['linkInfo']['ref'].split('?')[0])
697
- local_filepath += ext
705
+ if local_filepath:
706
+ local_filepath += ext
698
707
  response = self.get_url_stream(url=url)
699
708
 
700
709
  if save_locally:
@@ -791,9 +800,12 @@ class Downloader:
791
800
  for chunk in response.iter_content(chunk_size=chunk_size):
792
801
  if chunk: # filter out keep-alive new chunks
793
802
  data.write(chunk)
794
- file_validation, start_point, chunk_resume = self.__get_next_chunk(item=item,
795
- download_progress=data,
796
- chunk_resume=chunk_resume)
803
+
804
+ file_validation = True
805
+ if not is_url:
806
+ file_validation, start_point, chunk_resume = self.__get_next_chunk(item=item,
807
+ download_progress=data,
808
+ chunk_resume=chunk_resume)
797
809
  if file_validation:
798
810
  download_done = True
799
811
  else:
@@ -804,7 +816,7 @@ class Downloader:
804
816
  data.seek(0)
805
817
  data.name = item.name
806
818
  if not save_locally and to_array:
807
- if 'image' not in item.mimetype:
819
+ if 'image' not in item.mimetype and not is_url:
808
820
  raise PlatformException(
809
821
  error="400",
810
822
  message='Download element type numpy.ndarray support for image only. '
@@ -248,7 +248,7 @@ class Dpks:
248
248
  logger.warning("the project id that provide different from the dpk project id")
249
249
 
250
250
  if local_path is None:
251
- if manifest_filepath=='dataloop.json':
251
+ if manifest_filepath == 'dataloop.json':
252
252
  local_path = os.getcwd()
253
253
  else:
254
254
  local_path = os.path.dirname(manifest_filepath)
@@ -407,3 +407,28 @@ class Dpks:
407
407
  dpk = self.__get_by_name(dpk_name=dpk_name, dpk_version=dpk_version)
408
408
 
409
409
  return dpk
410
+
411
+ def get_previews(self, dpk: entities.Dpk):
412
+ """
413
+ Get the preview of a specific dpk.
414
+
415
+ :param entities.Dpk dpk: the dpk entity to get the preview for.
416
+ :return the preview of the dpk's templates
417
+ :rtype dict
418
+
419
+ ** Example **
420
+ ..coed-block:: python
421
+ res = dl.dpks.get_previews(dpk=dpk)
422
+ """
423
+ url = '/app-registry/{}/previews'.format(dpk.id)
424
+
425
+ # request
426
+ success, response = self._client_api.gen_request(
427
+ req_type='get',
428
+ path=url
429
+ )
430
+
431
+ if not success:
432
+ raise exceptions.PlatformException(response)
433
+
434
+ return response.json()
@@ -529,7 +529,8 @@ class Items:
529
529
  alpha: float = 1,
530
530
  export_version=entities.ExportVersion.V1,
531
531
  dataset_lock: bool = False,
532
- lock_timeout_sec: int = None
532
+ lock_timeout_sec: int = None,
533
+ export_summary: bool = False,
533
534
  ):
534
535
  """
535
536
  Download dataset items by filters.
@@ -550,6 +551,7 @@ class Items:
550
551
  :param dtlpy.entities.filters.Filters annotation_filters: Filters entity to filter annotations for download
551
552
  :param bool overwrite: optional - default = False
552
553
  :param bool dataset_lock: optional - default = False
554
+ :param bool export_summary: optional - default = False
553
555
  :param int lock_timeout_sec: optional
554
556
  :param bool to_items_folder: Create 'items' folder and download items to it
555
557
  :param int thickness: optional - line thickness, if -1 annotation will be filled, default =1
@@ -599,7 +601,8 @@ class Items:
599
601
  filter_output_annotations=filter_output_annotations,
600
602
  export_version=export_version,
601
603
  dataset_lock=dataset_lock,
602
- lock_timeout_sec=lock_timeout_sec
604
+ lock_timeout_sec=lock_timeout_sec,
605
+ export_summary=export_summary
603
606
  )
604
607
 
605
608
  def upload(
@@ -0,0 +1,213 @@
1
+ from dtlpy import miscellaneous
2
+
3
+ from ..services.api_client import ApiClient
4
+ from .. import exceptions, entities
5
+ import logging
6
+
7
+ logger = logging.getLogger(name='dtlpy')
8
+
9
+ class ServiceDrivers:
10
+
11
+ def __init__(self, client_api: ApiClient):
12
+ self._client_api = client_api
13
+ self._base_url = '/serviceDrivers'
14
+
15
+ def create(
16
+ self,
17
+ name: str,
18
+ compute_id: str,
19
+ context: entities.ComputeContext,
20
+ namespace: str = None
21
+ ):
22
+ """
23
+ Create a new service driver
24
+
25
+ :param name: Service driver name
26
+ :param compute_id: Compute ID
27
+ :param context: Compute context
28
+ :param namespace: Namespace
29
+ :return: Service driver
30
+
31
+ """
32
+
33
+ payload = {
34
+ 'name': name,
35
+ 'computeId': compute_id,
36
+ 'context': context.to_json()
37
+ }
38
+ if namespace is not None:
39
+ payload['namespace'] = namespace
40
+
41
+ # request
42
+ success, response = self._client_api.gen_request(
43
+ req_type='post',
44
+ path=self._base_url,
45
+ json_req=payload
46
+ )
47
+
48
+ if not success:
49
+ raise exceptions.PlatformException(response)
50
+
51
+ service_driver = entities.ServiceDriver.from_json(
52
+ _json=response.json(),
53
+ client_api=self._client_api
54
+ )
55
+
56
+ return service_driver
57
+
58
+ def get(self, service_driver_id: str):
59
+ """
60
+ Get a service driver
61
+
62
+ :param service_driver_id: Service driver ID
63
+ :return: Service driver
64
+ """
65
+
66
+ # request
67
+ success, response = self._client_api.gen_request(
68
+ req_type='get',
69
+ path=self._base_url + '/{}'.format(service_driver_id)
70
+ )
71
+
72
+ if not success:
73
+ raise exceptions.PlatformException(response)
74
+
75
+ service_driver = entities.ServiceDriver.from_json(
76
+ _json=response.json(),
77
+ client_api=self._client_api
78
+ )
79
+
80
+ return service_driver
81
+
82
+ def delete(self, service_driver_id: str):
83
+ """
84
+ Delete a service driver
85
+
86
+ :param service_driver_id: Service driver ID
87
+ """
88
+
89
+ # request
90
+ success, response = self._client_api.gen_request(
91
+ req_type='delete',
92
+ path=self._base_url + '/{}'.format(service_driver_id)
93
+ )
94
+
95
+ if not success:
96
+ raise exceptions.PlatformException(response)
97
+
98
+ return True
99
+
100
+ def set_default(self, service_driver_id: str, org_id: str, update_existing_services=False):
101
+ """
102
+ Set a service driver as default
103
+
104
+ :param service_driver_id: Compute name
105
+ :param org_id: Organization ID
106
+ :param update_existing_services: Update existing services
107
+
108
+ :return: Service driver
109
+ """
110
+
111
+ # request
112
+ success, response = self._client_api.gen_request(
113
+ req_type='post',
114
+ path=self._base_url + '/default',
115
+ json_req={
116
+ 'organizationId': org_id,
117
+ 'updateExistingServices': update_existing_services,
118
+ 'driverName': service_driver_id
119
+ }
120
+ )
121
+
122
+ if not success:
123
+ raise exceptions.PlatformException(response)
124
+
125
+ service_driver = entities.ServiceDriver.from_json(
126
+ _json=response.json(),
127
+ client_api=self._client_api
128
+ )
129
+
130
+ return service_driver
131
+
132
+ def update(self, service_driver: entities.ServiceDriver):
133
+ """
134
+ Update a service driver
135
+
136
+ :param dtlpy.entities.service_driver.ServiceDriver service_driver: updated service driver object
137
+ :return: Service driver entity
138
+ :rtype: dtlpy.entities.service_driver.ServiceDriver
139
+ """
140
+
141
+ # request
142
+ success, response = self._client_api.gen_request(
143
+ req_type='patch',
144
+ path=self._base_url + '/{}'.format(service_driver.id),
145
+ json_req=service_driver.to_json()
146
+ )
147
+
148
+ if not success:
149
+ raise exceptions.PlatformException(response)
150
+
151
+ service_driver = entities.ServiceDriver.from_json(
152
+ _json=response.json(),
153
+ client_api=self._client_api
154
+ )
155
+
156
+ return service_driver
157
+
158
+ def _list(self, filters: entities.Filters):
159
+ url = self._base_url + '/query'
160
+ success, response = self._client_api.gen_request(req_type='POST',
161
+ path=url,
162
+ json_req=filters.prepare())
163
+ if not success:
164
+ raise exceptions.PlatformException(response)
165
+
166
+ return response.json()
167
+
168
+ def _build_entities_from_response(self, response_items) -> miscellaneous.List[entities.ServiceDriver]:
169
+ pool = self._client_api.thread_pools(pool_name='entity.create')
170
+ jobs = [None for _ in range(len(response_items))]
171
+ for i_item, item in enumerate(response_items):
172
+ jobs[i_item] = pool.submit(entities.ServiceDriver._protected_from_json,
173
+ **{'client_api': self._client_api,
174
+ '_json': item})
175
+ results = [j.result() for j in jobs]
176
+ _ = [logger.warning(r[1]) for r in results if r[0] is False]
177
+ items = miscellaneous.List([r[1] for r in results if r[0] is True])
178
+ return items
179
+
180
+ def list(self, filters: entities.Filters = None) -> entities.PagedEntities:
181
+ """
182
+ List all services drivers
183
+
184
+ :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
185
+ :return: Paged entity
186
+ :rtype: dtlpy.entities.paged_entities.PagedEntities
187
+
188
+ **Example**:
189
+
190
+ .. code-block:: python
191
+
192
+ services = dl.service_drivers.list()
193
+ """
194
+ # default filters
195
+ if filters is None:
196
+ filters = entities.Filters(resource=entities.FiltersResource.SERVICE_DRIVER)
197
+
198
+ if filters.resource != entities.FiltersResource.SERVICE_DRIVER:
199
+ raise exceptions.PlatformException(
200
+ error='400',
201
+ message='Filters resource must to be FiltersResource.SERVICE_DRIVER. Got: {!r}'.format(
202
+ filters.resource))
203
+
204
+ if not isinstance(filters, entities.Filters):
205
+ raise exceptions.PlatformException('400', 'Unknown filters type')
206
+
207
+ paged = entities.PagedEntities(items_repository=self,
208
+ filters=filters,
209
+ page_offset=filters.page,
210
+ page_size=filters.page_size,
211
+ client_api=self._client_api)
212
+ paged.get_page()
213
+ return paged
@@ -606,6 +606,7 @@ class Services:
606
606
  max_attempts: int = None,
607
607
  secrets=None,
608
608
  integrations=None,
609
+ active: bool = True,
609
610
  **kwargs
610
611
  ) -> entities.Service:
611
612
  """
@@ -633,6 +634,7 @@ class Services:
633
634
  :param bool force: optional - terminate old replicas immediately
634
635
  :param list secrets: list of the integrations ids
635
636
  :param list integrations: list of the integrations
637
+ :param bool active: optional - if true, service will be active
636
638
  :param kwargs:
637
639
  :return: Service object
638
640
  :rtype: dtlpy.entities.service.Service
@@ -686,6 +688,7 @@ class Services:
686
688
  'versions': agent_versions,
687
689
  'packageRevision': revision if revision is not None else package.version,
688
690
  'driverId': driver_id,
691
+ 'active': active
689
692
  }
690
693
 
691
694
  if secrets is not None:
@@ -1183,6 +1186,7 @@ class Services:
1183
1186
  force: bool = False,
1184
1187
  secrets: list = None,
1185
1188
  integrations: list = None,
1189
+ active: bool = True,
1186
1190
  **kwargs) -> entities.Service:
1187
1191
  """
1188
1192
  Deploy service.
@@ -1212,6 +1216,7 @@ class Services:
1212
1216
  :param bool force: optional - if true, terminate old replicas immediately
1213
1217
  :param list secrets: list of the integrations ids
1214
1218
  :param list integrations: list of the integrations
1219
+ :param bool active: if true, activate the service
1215
1220
  :param kwargs: list of additional arguments
1216
1221
  :return: Service object
1217
1222
  :rtype: dtlpy.entities.service.Service
@@ -1336,6 +1341,7 @@ class Services:
1336
1341
  on_reset=on_reset,
1337
1342
  secrets=secrets,
1338
1343
  integrations=integrations,
1344
+ active=active
1339
1345
  )
1340
1346
  if checkout:
1341
1347
  self.checkout(service=service)
@@ -155,6 +155,10 @@ class Uploader:
155
155
  remote_path = f"/{remote_path}"
156
156
  if remote_path and not remote_path.endswith("/"):
157
157
  remote_path = f"{remote_path}/"
158
+
159
+ if remote_name:
160
+ remote_name = remote_name.lstrip('/')
161
+
158
162
  if file_types is not None and not isinstance(file_types, list):
159
163
  msg = '"file_types" should be a list of file extension. e.g [".jpg", ".png"]'
160
164
  raise PlatformException(error="400", message=msg)