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.
Files changed (243) hide show
  1. dtlpy/__init__.py +488 -488
  2. dtlpy/__version__.py +1 -1
  3. dtlpy/assets/__init__.py +26 -26
  4. dtlpy/assets/__pycache__/__init__.cpython-38.pyc +0 -0
  5. dtlpy/assets/code_server/config.yaml +2 -2
  6. dtlpy/assets/code_server/installation.sh +24 -24
  7. dtlpy/assets/code_server/launch.json +13 -13
  8. dtlpy/assets/code_server/settings.json +2 -2
  9. dtlpy/assets/main.py +53 -53
  10. dtlpy/assets/main_partial.py +18 -18
  11. dtlpy/assets/mock.json +11 -11
  12. dtlpy/assets/model_adapter.py +83 -83
  13. dtlpy/assets/package.json +61 -61
  14. dtlpy/assets/package_catalog.json +29 -29
  15. dtlpy/assets/package_gitignore +307 -307
  16. dtlpy/assets/service_runners/__init__.py +33 -33
  17. dtlpy/assets/service_runners/converter.py +96 -96
  18. dtlpy/assets/service_runners/multi_method.py +49 -49
  19. dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
  20. dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
  21. dtlpy/assets/service_runners/multi_method_item.py +52 -52
  22. dtlpy/assets/service_runners/multi_method_json.py +52 -52
  23. dtlpy/assets/service_runners/single_method.py +37 -37
  24. dtlpy/assets/service_runners/single_method_annotation.py +43 -43
  25. dtlpy/assets/service_runners/single_method_dataset.py +43 -43
  26. dtlpy/assets/service_runners/single_method_item.py +41 -41
  27. dtlpy/assets/service_runners/single_method_json.py +42 -42
  28. dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
  29. dtlpy/assets/voc_annotation_template.xml +23 -23
  30. dtlpy/caches/base_cache.py +32 -32
  31. dtlpy/caches/cache.py +473 -473
  32. dtlpy/caches/dl_cache.py +201 -201
  33. dtlpy/caches/filesystem_cache.py +89 -89
  34. dtlpy/caches/redis_cache.py +84 -84
  35. dtlpy/dlp/__init__.py +20 -20
  36. dtlpy/dlp/cli_utilities.py +367 -367
  37. dtlpy/dlp/command_executor.py +764 -764
  38. dtlpy/dlp/dlp +1 -1
  39. dtlpy/dlp/dlp.bat +1 -1
  40. dtlpy/dlp/dlp.py +128 -128
  41. dtlpy/dlp/parser.py +651 -651
  42. dtlpy/entities/__init__.py +83 -83
  43. dtlpy/entities/analytic.py +311 -311
  44. dtlpy/entities/annotation.py +1879 -1879
  45. dtlpy/entities/annotation_collection.py +699 -699
  46. dtlpy/entities/annotation_definitions/__init__.py +20 -20
  47. dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
  48. dtlpy/entities/annotation_definitions/box.py +195 -195
  49. dtlpy/entities/annotation_definitions/classification.py +67 -67
  50. dtlpy/entities/annotation_definitions/comparison.py +72 -72
  51. dtlpy/entities/annotation_definitions/cube.py +204 -204
  52. dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
  53. dtlpy/entities/annotation_definitions/description.py +32 -32
  54. dtlpy/entities/annotation_definitions/ellipse.py +124 -124
  55. dtlpy/entities/annotation_definitions/free_text.py +62 -62
  56. dtlpy/entities/annotation_definitions/gis.py +69 -69
  57. dtlpy/entities/annotation_definitions/note.py +139 -139
  58. dtlpy/entities/annotation_definitions/point.py +117 -117
  59. dtlpy/entities/annotation_definitions/polygon.py +182 -182
  60. dtlpy/entities/annotation_definitions/polyline.py +111 -111
  61. dtlpy/entities/annotation_definitions/pose.py +92 -92
  62. dtlpy/entities/annotation_definitions/ref_image.py +86 -86
  63. dtlpy/entities/annotation_definitions/segmentation.py +240 -240
  64. dtlpy/entities/annotation_definitions/subtitle.py +34 -34
  65. dtlpy/entities/annotation_definitions/text.py +85 -85
  66. dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
  67. dtlpy/entities/app.py +220 -220
  68. dtlpy/entities/app_module.py +107 -107
  69. dtlpy/entities/artifact.py +174 -174
  70. dtlpy/entities/assignment.py +399 -399
  71. dtlpy/entities/base_entity.py +214 -214
  72. dtlpy/entities/bot.py +113 -113
  73. dtlpy/entities/codebase.py +296 -296
  74. dtlpy/entities/collection.py +38 -38
  75. dtlpy/entities/command.py +169 -169
  76. dtlpy/entities/compute.py +442 -442
  77. dtlpy/entities/dataset.py +1285 -1285
  78. dtlpy/entities/directory_tree.py +44 -44
  79. dtlpy/entities/dpk.py +470 -470
  80. dtlpy/entities/driver.py +222 -222
  81. dtlpy/entities/execution.py +397 -397
  82. dtlpy/entities/feature.py +124 -124
  83. dtlpy/entities/feature_set.py +145 -145
  84. dtlpy/entities/filters.py +641 -641
  85. dtlpy/entities/gis_item.py +107 -107
  86. dtlpy/entities/integration.py +184 -184
  87. dtlpy/entities/item.py +953 -953
  88. dtlpy/entities/label.py +123 -123
  89. dtlpy/entities/links.py +85 -85
  90. dtlpy/entities/message.py +175 -175
  91. dtlpy/entities/model.py +694 -691
  92. dtlpy/entities/node.py +1005 -1005
  93. dtlpy/entities/ontology.py +803 -803
  94. dtlpy/entities/organization.py +287 -287
  95. dtlpy/entities/package.py +657 -657
  96. dtlpy/entities/package_defaults.py +5 -5
  97. dtlpy/entities/package_function.py +185 -185
  98. dtlpy/entities/package_module.py +113 -113
  99. dtlpy/entities/package_slot.py +118 -118
  100. dtlpy/entities/paged_entities.py +290 -267
  101. dtlpy/entities/pipeline.py +593 -593
  102. dtlpy/entities/pipeline_execution.py +279 -279
  103. dtlpy/entities/project.py +394 -394
  104. dtlpy/entities/prompt_item.py +499 -499
  105. dtlpy/entities/recipe.py +301 -301
  106. dtlpy/entities/reflect_dict.py +102 -102
  107. dtlpy/entities/resource_execution.py +138 -138
  108. dtlpy/entities/service.py +958 -958
  109. dtlpy/entities/service_driver.py +117 -117
  110. dtlpy/entities/setting.py +294 -294
  111. dtlpy/entities/task.py +491 -491
  112. dtlpy/entities/time_series.py +143 -143
  113. dtlpy/entities/trigger.py +426 -426
  114. dtlpy/entities/user.py +118 -118
  115. dtlpy/entities/webhook.py +124 -124
  116. dtlpy/examples/__init__.py +19 -19
  117. dtlpy/examples/add_labels.py +135 -135
  118. dtlpy/examples/add_metadata_to_item.py +21 -21
  119. dtlpy/examples/annotate_items_using_model.py +65 -65
  120. dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
  121. dtlpy/examples/annotations_convert_to_voc.py +9 -9
  122. dtlpy/examples/annotations_convert_to_yolo.py +9 -9
  123. dtlpy/examples/convert_annotation_types.py +51 -51
  124. dtlpy/examples/converter.py +143 -143
  125. dtlpy/examples/copy_annotations.py +22 -22
  126. dtlpy/examples/copy_folder.py +31 -31
  127. dtlpy/examples/create_annotations.py +51 -51
  128. dtlpy/examples/create_video_annotations.py +83 -83
  129. dtlpy/examples/delete_annotations.py +26 -26
  130. dtlpy/examples/filters.py +113 -113
  131. dtlpy/examples/move_item.py +23 -23
  132. dtlpy/examples/play_video_annotation.py +13 -13
  133. dtlpy/examples/show_item_and_mask.py +53 -53
  134. dtlpy/examples/triggers.py +49 -49
  135. dtlpy/examples/upload_batch_of_items.py +20 -20
  136. dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
  137. dtlpy/examples/upload_items_with_modalities.py +43 -43
  138. dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
  139. dtlpy/examples/upload_yolo_format_annotations.py +70 -70
  140. dtlpy/exceptions.py +125 -125
  141. dtlpy/miscellaneous/__init__.py +20 -20
  142. dtlpy/miscellaneous/dict_differ.py +95 -95
  143. dtlpy/miscellaneous/git_utils.py +217 -217
  144. dtlpy/miscellaneous/json_utils.py +14 -14
  145. dtlpy/miscellaneous/list_print.py +105 -105
  146. dtlpy/miscellaneous/zipping.py +130 -130
  147. dtlpy/ml/__init__.py +20 -20
  148. dtlpy/ml/base_feature_extractor_adapter.py +27 -27
  149. dtlpy/ml/base_model_adapter.py +945 -940
  150. dtlpy/ml/metrics.py +461 -461
  151. dtlpy/ml/predictions_utils.py +274 -274
  152. dtlpy/ml/summary_writer.py +57 -57
  153. dtlpy/ml/train_utils.py +60 -60
  154. dtlpy/new_instance.py +252 -252
  155. dtlpy/repositories/__init__.py +56 -56
  156. dtlpy/repositories/analytics.py +85 -85
  157. dtlpy/repositories/annotations.py +916 -916
  158. dtlpy/repositories/apps.py +383 -383
  159. dtlpy/repositories/artifacts.py +452 -452
  160. dtlpy/repositories/assignments.py +599 -599
  161. dtlpy/repositories/bots.py +213 -213
  162. dtlpy/repositories/codebases.py +559 -559
  163. dtlpy/repositories/collections.py +332 -348
  164. dtlpy/repositories/commands.py +158 -158
  165. dtlpy/repositories/compositions.py +61 -61
  166. dtlpy/repositories/computes.py +434 -406
  167. dtlpy/repositories/datasets.py +1291 -1291
  168. dtlpy/repositories/downloader.py +895 -895
  169. dtlpy/repositories/dpks.py +433 -433
  170. dtlpy/repositories/drivers.py +266 -266
  171. dtlpy/repositories/executions.py +817 -817
  172. dtlpy/repositories/feature_sets.py +226 -226
  173. dtlpy/repositories/features.py +238 -238
  174. dtlpy/repositories/integrations.py +484 -484
  175. dtlpy/repositories/items.py +909 -915
  176. dtlpy/repositories/messages.py +94 -94
  177. dtlpy/repositories/models.py +877 -867
  178. dtlpy/repositories/nodes.py +80 -80
  179. dtlpy/repositories/ontologies.py +511 -511
  180. dtlpy/repositories/organizations.py +525 -525
  181. dtlpy/repositories/packages.py +1941 -1941
  182. dtlpy/repositories/pipeline_executions.py +448 -448
  183. dtlpy/repositories/pipelines.py +642 -642
  184. dtlpy/repositories/projects.py +539 -539
  185. dtlpy/repositories/recipes.py +399 -399
  186. dtlpy/repositories/resource_executions.py +137 -137
  187. dtlpy/repositories/schema.py +120 -120
  188. dtlpy/repositories/service_drivers.py +213 -213
  189. dtlpy/repositories/services.py +1704 -1704
  190. dtlpy/repositories/settings.py +339 -339
  191. dtlpy/repositories/tasks.py +1124 -1124
  192. dtlpy/repositories/times_series.py +278 -278
  193. dtlpy/repositories/triggers.py +536 -536
  194. dtlpy/repositories/upload_element.py +257 -257
  195. dtlpy/repositories/uploader.py +651 -651
  196. dtlpy/repositories/webhooks.py +249 -249
  197. dtlpy/services/__init__.py +22 -22
  198. dtlpy/services/aihttp_retry.py +131 -131
  199. dtlpy/services/api_client.py +1782 -1782
  200. dtlpy/services/api_reference.py +40 -40
  201. dtlpy/services/async_utils.py +133 -133
  202. dtlpy/services/calls_counter.py +44 -44
  203. dtlpy/services/check_sdk.py +68 -68
  204. dtlpy/services/cookie.py +115 -115
  205. dtlpy/services/create_logger.py +156 -156
  206. dtlpy/services/events.py +84 -84
  207. dtlpy/services/logins.py +235 -235
  208. dtlpy/services/reporter.py +256 -256
  209. dtlpy/services/service_defaults.py +91 -91
  210. dtlpy/utilities/__init__.py +20 -20
  211. dtlpy/utilities/annotations/__init__.py +16 -16
  212. dtlpy/utilities/annotations/annotation_converters.py +269 -269
  213. dtlpy/utilities/base_package_runner.py +264 -264
  214. dtlpy/utilities/converter.py +1650 -1650
  215. dtlpy/utilities/dataset_generators/__init__.py +1 -1
  216. dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
  217. dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
  218. dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
  219. dtlpy/utilities/local_development/__init__.py +1 -1
  220. dtlpy/utilities/local_development/local_session.py +179 -179
  221. dtlpy/utilities/reports/__init__.py +2 -2
  222. dtlpy/utilities/reports/figures.py +343 -343
  223. dtlpy/utilities/reports/report.py +71 -71
  224. dtlpy/utilities/videos/__init__.py +17 -17
  225. dtlpy/utilities/videos/video_player.py +598 -598
  226. dtlpy/utilities/videos/videos.py +470 -470
  227. {dtlpy-1.113.10.data → dtlpy-1.114.13.data}/scripts/dlp +1 -1
  228. dtlpy-1.114.13.data/scripts/dlp.bat +2 -0
  229. {dtlpy-1.113.10.data → dtlpy-1.114.13.data}/scripts/dlp.py +128 -128
  230. {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/LICENSE +200 -200
  231. {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/METADATA +172 -172
  232. dtlpy-1.114.13.dist-info/RECORD +240 -0
  233. {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/WHEEL +1 -1
  234. tests/features/environment.py +551 -550
  235. dtlpy-1.113.10.data/scripts/dlp.bat +0 -2
  236. dtlpy-1.113.10.dist-info/RECORD +0 -244
  237. tests/assets/__init__.py +0 -0
  238. tests/assets/models_flow/__init__.py +0 -0
  239. tests/assets/models_flow/failedmain.py +0 -52
  240. tests/assets/models_flow/main.py +0 -62
  241. tests/assets/models_flow/main_model.py +0 -54
  242. {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/entry_points.txt +0 -0
  243. {dtlpy-1.113.10.dist-info → dtlpy-1.114.13.dist-info}/top_level.txt +0 -0
@@ -1,642 +1,642 @@
1
- import logging
2
- from .. import entities, repositories, exceptions, miscellaneous, _api_reference
3
- from ..services.api_client import ApiClient
4
-
5
- logger = logging.getLogger(name='dtlpy')
6
-
7
-
8
- def generate_basic_pipeline():
9
- return dict(name="", projectId="", nodes=[], connections=[], startNodes=[], variables=[])
10
-
11
-
12
- class Pipelines:
13
- """
14
- Pipelines Repository
15
-
16
- The Pipelines class allows users to manage pipelines and their properties. See our documentation for more information on `pipelines <https://dataloop.ai/docs/pipelines-overview>`_.
17
- """
18
-
19
- def __init__(self, client_api: ApiClient, project: entities.Project = None):
20
- self._client_api = client_api
21
- self._project = project
22
-
23
- ############
24
- # entities #
25
- ############
26
- @property
27
- def project(self) -> entities.Project:
28
- if self._project is None:
29
- try:
30
- self._project = repositories.Projects(client_api=self._client_api).get()
31
- except exceptions.NotFound:
32
- raise exceptions.PlatformException(
33
- error='2001',
34
- message='Missing "project". need to set a Project entity or use project.pipelines repository')
35
- return self._project
36
-
37
- @project.setter
38
- def project(self, project: entities.Project):
39
- if not isinstance(project, entities.Project):
40
- raise ValueError('Must input a valid Project entity')
41
- self._project = project
42
-
43
- ###########
44
- # methods #
45
- ###########
46
- @property
47
- def platform_url(self):
48
- return self._client_api._get_resource_url("projects/{}/pipelines".format(self.project.id))
49
-
50
- def open_in_web(self,
51
- pipeline: entities.Pipeline = None,
52
- pipeline_id: str = None,
53
- pipeline_name: str = None):
54
- """
55
- Open the pipeline in web platform.
56
-
57
- **prerequisites**: Must be *owner* or *developer* to use this method.
58
-
59
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
60
- :param str pipeline_id: pipeline id
61
- :param str pipeline_name: pipeline name
62
-
63
- **Example**:
64
-
65
- .. code-block:: python
66
-
67
- project.pipelines.open_in_web(pipeline_id='pipeline_id')
68
- """
69
- if pipeline_name is not None:
70
- pipeline = self.get(pipeline_name=pipeline_name)
71
- if pipeline is not None:
72
- pipeline.open_in_web()
73
- elif pipeline_id is not None:
74
- self._client_api._open_in_web(url=self.platform_url + '/' + str(pipeline_id))
75
- else:
76
- self._client_api._open_in_web(url=self.platform_url)
77
-
78
- @_api_reference.add(path='/pipelines/{pipelineId}', method='get')
79
- def get(self,
80
- pipeline_name=None,
81
- pipeline_id=None,
82
- fetch=None
83
- ) -> entities.Pipeline:
84
- """
85
- Get Pipeline object to use in your code.
86
-
87
- **prerequisites**: You must be an *owner* or *developer* to use this method.
88
-
89
- You must provide at least ONE of the following params: pipeline_name, pipeline_id.
90
-
91
- :param str pipeline_id: pipeline id
92
- :param str pipeline_name: pipeline name
93
- :param fetch: optional - fetch entity from platform, default taken from cookie
94
- :return: Pipeline object
95
- :rtype: dtlpy.entities.pipeline.Pipeline
96
-
97
- **Example**:
98
-
99
- .. code-block:: python
100
-
101
- pipeline = project.pipelines.get(pipeline_id='pipeline_id')
102
- """
103
- if fetch is None:
104
- fetch = self._client_api.fetch_entities
105
-
106
- if pipeline_name is None and pipeline_id is None:
107
- raise exceptions.PlatformException(
108
- error='400',
109
- message='Must provide an identifier in inputs')
110
- elif fetch:
111
- if pipeline_id is not None:
112
- success, response = self._client_api.gen_request(
113
- req_type="get",
114
- path="/pipelines/{}".format(pipeline_id))
115
- if not success:
116
- raise exceptions.PlatformException(response)
117
- pipeline = entities.Pipeline.from_json(
118
- client_api=self._client_api,
119
- _json=response.json(),
120
- project=self._project
121
- )
122
- if pipeline_name is not None and pipeline.name != pipeline_name:
123
- logger.warning(
124
- "Mismatch found in pipeline.get: pipeline_name is different then pipeline.name:"
125
- " {!r} != {!r}".format(
126
- pipeline_name,
127
- pipeline.name
128
- )
129
- )
130
- elif pipeline_name is not None:
131
- filters = entities.Filters(
132
- field='name',
133
- values=pipeline_name,
134
- resource=entities.FiltersResource.PIPELINE,
135
- use_defaults=False
136
- )
137
- if self._project is not None:
138
- filters.add(field='projectId', values=self._project.id)
139
- pipelines = self.list(filters=filters)
140
- if pipelines.items_count == 0:
141
- raise exceptions.PlatformException(
142
- error='404',
143
- message='Pipeline not found. Name: {}'.format(pipeline_name))
144
- elif pipelines.items_count > 1:
145
- raise exceptions.PlatformException(
146
- error='400',
147
- message='More than one pipelines found by the name of: {} '
148
- 'Please get pipeline from a project entity'.format(pipeline_name))
149
- pipeline = pipelines.items[0]
150
- else:
151
- raise exceptions.PlatformException(
152
- error='400',
153
- message='No checked-out pipeline was found, must checkout or provide an identifier in inputs')
154
- else:
155
- pipeline = entities.Pipeline.from_json(
156
- _json={'id': pipeline_id,
157
- 'name': pipeline_name},
158
- client_api=self._client_api,
159
- project=self._project,
160
- is_fetched=False
161
- )
162
-
163
- return pipeline
164
-
165
- def _build_entities_from_response(self, response_items) -> miscellaneous.List[entities.Pipeline]:
166
- pool = self._client_api.thread_pools(pool_name='entity.create')
167
- jobs = [None for _ in range(len(response_items))]
168
-
169
- for i_pipeline, pipeline in enumerate(response_items):
170
- jobs[i_pipeline] = pool.submit(
171
- entities.Pipeline._protected_from_json,
172
- **{
173
- 'client_api': self._client_api,
174
- '_json': pipeline,
175
- 'project': self._project
176
- }
177
- )
178
-
179
- # get all results
180
- # noinspection PyUnresolvedReferences
181
- results = [j.result() for j in jobs]
182
- # log errors
183
- _ = [logger.warning(r[1]) for r in results if r[0] is False]
184
- # return good jobs
185
- pipelines = miscellaneous.List([r[1] for r in results if r[0] is True])
186
- return pipelines
187
-
188
- def _list(self, filters: entities.Filters):
189
- url = '/pipelines/query'
190
-
191
- # request
192
- success, response = self._client_api.gen_request(
193
- req_type='post',
194
- path=url,
195
- json_req=filters.prepare()
196
- )
197
- if not success:
198
- raise exceptions.PlatformException(response)
199
- return response.json()
200
-
201
- @_api_reference.add(path='/pipelines/query', method='post')
202
- def list(self,
203
- filters: entities.Filters = None,
204
- project_id: str = None
205
- ) -> entities.PagedEntities:
206
- """
207
- List project pipelines.
208
-
209
- **prerequisites**: You must be an *owner* or *developer* to use this method.
210
-
211
- :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
212
- :param str project_id: project id
213
- :return: Paged entity
214
- :rtype: dtlpy.entities.paged_entities.PagedEntities
215
-
216
- **Example**:
217
-
218
- .. code-block:: python
219
-
220
- pipelines = project.pipelines.list()
221
- """
222
- if filters is None:
223
- filters = entities.Filters(resource=entities.FiltersResource.PIPELINE)
224
- # assert type filters
225
- elif not isinstance(filters, entities.Filters):
226
- raise exceptions.PlatformException(error='400',
227
- message='Unknown filters type: {!r}'.format(type(filters)))
228
- if filters.resource != entities.FiltersResource.PIPELINE:
229
- raise exceptions.PlatformException(
230
- error='400',
231
- message='Filters resource must to be FiltersResource.PIPELINE. Got: {!r}'.format(filters.resource))
232
-
233
- if project_id is None and self._project is not None:
234
- project_id = self._project.id
235
-
236
- if project_id is not None:
237
- filters.add(field='projectId', values=project_id)
238
-
239
- paged = entities.PagedEntities(items_repository=self,
240
- filters=filters,
241
- page_offset=filters.page,
242
- page_size=filters.page_size,
243
- project_id=project_id,
244
- client_api=self._client_api)
245
- paged.get_page()
246
- return paged
247
-
248
- def _name_validation(self, name: str):
249
- url = '/piper-misc/naming/packages/{}'.format(name)
250
-
251
- # request
252
- success, response = self._client_api.gen_request(req_type='get',
253
- path=url)
254
- if not success:
255
- raise exceptions.PlatformException(response)
256
-
257
- # @_api_reference.add(path='/pipelines/{pipelineId}', method='delete')
258
- def delete(self,
259
- pipeline: entities.Pipeline = None,
260
- pipeline_name: str = None,
261
- pipeline_id: str = None):
262
- """
263
- Delete Pipeline object.
264
-
265
- **prerequisites**: You must be an *owner* or *developer* to use this method.
266
-
267
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
268
- :param str pipeline_id: pipeline id
269
- :param str pipeline_name: pipeline name
270
- :return: True if success
271
- :rtype: bool
272
-
273
- **Example**:
274
-
275
- .. code-block:: python
276
-
277
- is_deleted = project.pipelines.delete(pipeline_id='pipeline_id')
278
- """
279
- # get id and name
280
- if pipeline_id is None:
281
- if pipeline is None:
282
- pipeline = self.get(pipeline_name=pipeline_name)
283
- pipeline_id = pipeline.id
284
-
285
- # request
286
- success, response = self._client_api.gen_request(req_type="delete",
287
- path="/pipelines/{}".format(pipeline_id))
288
-
289
- # exception handling
290
- if not success:
291
- raise exceptions.PlatformException(response)
292
-
293
- # return results
294
- return True
295
-
296
- @_api_reference.add(path='/pipelines/{pipelineId}/settings', method='patch')
297
- def update_settings(self, pipeline: entities.Pipeline, settings: entities.PipelineSettings):
298
- """
299
- Update pipeline settings.
300
-
301
- **prerequisites**: You must be an *owner* or *developer* to use this method.
302
-
303
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
304
- :param dtlpy.entities.pipeline.PipelineSettings settings: settings entity
305
- :return: Pipeline object
306
- :rtype: dtlpy.entities.pipeline.Pipeline
307
-
308
- **Example**:
309
-
310
- .. code-block:: python
311
-
312
- pipeline = project.pipelines.update_settings(pipeline='pipeline_entity', settings=dl.PipelineSettings(keep_triggers_active=True))
313
- """
314
- # payload
315
- payload = {'settings': settings.to_json()}
316
-
317
- # request
318
- success, response = self._client_api.gen_request(
319
- req_type='patch',
320
- path='/pipelines/{}'.format(pipeline.id),
321
- json_req=payload
322
- )
323
- if not success:
324
- raise exceptions.PlatformException(response)
325
-
326
- # return entity
327
- return entities.Pipeline.from_json(
328
- _json=response.json(),
329
- client_api=self._client_api,
330
- project=self._project
331
- )
332
-
333
- def __update_variables(self, pipeline: entities.Pipeline):
334
- pipeline_json = pipeline.to_json()
335
- variables = pipeline_json.get('variables', list())
336
-
337
- for var in variables:
338
- if var.get('reference', None) is None:
339
- var['reference'] = pipeline.id
340
-
341
- # payload
342
- payload = {'variables': variables}
343
-
344
- # request
345
- success, response = self._client_api.gen_request(
346
- req_type='patch',
347
- path='/pipelines/{}/variables'.format(pipeline.id),
348
- json_req=payload
349
- )
350
- if not success:
351
- raise exceptions.PlatformException(response)
352
-
353
- # return entity
354
- return entities.Pipeline.from_json(
355
- _json=response.json(),
356
- client_api=self._client_api,
357
- project=self._project
358
- )
359
-
360
- @_api_reference.add(path='/pipelines/{pipelineId}', method='patch')
361
- def update(self,
362
- pipeline: entities.Pipeline = None
363
- ) -> entities.Pipeline:
364
- """
365
- Update pipeline changes to platform.
366
-
367
- **prerequisites**: You must be an *owner* or *developer* to use this method.
368
-
369
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
370
- :return: Pipeline object
371
- :rtype: dtlpy.entities.pipeline.Pipeline
372
-
373
- **Example**:
374
-
375
- .. code-block:: python
376
-
377
- pipeline = project.pipelines.update(pipeline='pipeline_entity')
378
- """
379
- # payload
380
- payload = pipeline.to_json()
381
-
382
- # update settings
383
- if pipeline.settings_changed():
384
- new_pipeline = self.update_settings(pipeline=pipeline, settings=pipeline.settings)
385
- payload['settings'] = new_pipeline.to_json().get('settings', payload.get('settings'))
386
-
387
- # update variables
388
- if pipeline.variables_changed():
389
- new_pipeline = self.__update_variables(pipeline=pipeline)
390
- payload['variables'] = new_pipeline.to_json().get('variables', payload.get('variables'))
391
-
392
- success, response = self._client_api.gen_request(
393
- req_type='patch',
394
- path='/pipelines/{}'.format(pipeline.id),
395
- json_req=payload
396
- )
397
-
398
- # exception handling
399
- if not success:
400
- raise exceptions.PlatformException(response)
401
-
402
- # return entity
403
- return entities.Pipeline.from_json(
404
- _json=response.json(),
405
- client_api=self._client_api,
406
- project=self._project
407
- )
408
-
409
- @_api_reference.add(path='/pipelines', method='post')
410
- def create(self,
411
- name: str = None,
412
- project_id: str = None,
413
- pipeline_json: dict = None
414
- ) -> entities.Pipeline:
415
- """
416
- Create a new pipeline.
417
-
418
- **prerequisites**: You must be an *owner* or *developer* to use this method.
419
-
420
- :param str name: pipeline name
421
- :param str project_id: project id
422
- :param dict pipeline_json: json containing the pipeline fields
423
- :return: Pipeline object
424
- :rtype: dtlpy.entities.pipeline.Pipeline
425
-
426
- **Example**:
427
-
428
- .. code-block:: python
429
-
430
- pipeline = project.pipelines.create(name='pipeline_name')
431
- """
432
- if pipeline_json is None:
433
- pipeline_json = generate_basic_pipeline()
434
-
435
- if name is not None:
436
- pipeline_json['name'] = name
437
-
438
- if project_id is not None:
439
- pipeline_json['projectId'] = project_id
440
- else:
441
- if not pipeline_json.get('projectId', None):
442
- pipeline_json['projectId'] = self.project.id
443
-
444
- success, response = self._client_api.gen_request(req_type='post',
445
- path='/pipelines',
446
- json_req=pipeline_json)
447
- if success:
448
- pipeline = entities.Pipeline.from_json(client_api=self._client_api,
449
- _json=response.json(),
450
- project=self.project)
451
- else:
452
- raise exceptions.PlatformException(response)
453
- assert isinstance(pipeline, entities.Pipeline)
454
- return pipeline
455
-
456
- @_api_reference.add(path='/pipelines/{pipelineId}/install', method='post')
457
- def install(self, pipeline: entities.Pipeline = None, resume_option: entities.PipelineResumeOption = None):
458
- """
459
- Install (start) a pipeline.
460
-
461
- **prerequisites**: You must be an *owner* or *developer* to use this method.
462
-
463
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
464
- :param dtlpy.entities.pipeline.PipelineResumeOption resume_option: optional - resume pipeline method (what to do with existing cycles)
465
- :return: Composition object
466
-
467
- **Example**:
468
-
469
- .. code-block:: python
470
-
471
- project.pipelines.install(pipeline='pipeline_entity')
472
- """
473
-
474
- payload = {}
475
- if resume_option:
476
- payload['resumeOption'] = resume_option
477
-
478
- success, response = self._client_api.gen_request(
479
- req_type='post',
480
- path='/pipelines/{}/install'.format(pipeline.id),
481
- json_req=payload
482
- )
483
-
484
- if not success:
485
- raise exceptions.PlatformException(response)
486
-
487
- return entities.Pipeline.from_json(client_api=self._client_api,
488
- _json=response.json(),
489
- project=self.project)
490
-
491
- @_api_reference.add(path='/pipelines/{pipelineId}/uninstall', method='post')
492
- def pause(self, pipeline: entities.Pipeline = None, keep_triggers_active: bool = None):
493
- """
494
- Pause a pipeline.
495
-
496
- **prerequisites**: You must be an *owner* or *developer* to use this method.
497
-
498
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
499
- :param bool keep_triggers_active: Do we want the triggers to stay active and collect events
500
- :return: Composition object
501
-
502
- **Example**:
503
-
504
- .. code-block:: python
505
-
506
- project.pipelines.pause(pipeline='pipeline_entity')
507
- """
508
-
509
- payload = {}
510
- if keep_triggers_active is not None:
511
- payload['keepTriggersActive'] = keep_triggers_active
512
-
513
- success, response = self._client_api.gen_request(
514
- req_type='post',
515
- path='/pipelines/{}/uninstall'.format(pipeline.id),
516
- json_req=payload
517
- )
518
-
519
- if not success:
520
- raise exceptions.PlatformException(response)
521
-
522
- @_api_reference.add(path='/pipelines/{pipelineId}/reset', method='post')
523
- def reset(self,
524
- pipeline: entities.Pipeline = None,
525
- pipeline_id: str = None,
526
- pipeline_name: str = None,
527
- stop_if_running: bool = False):
528
- """
529
- Reset pipeline counters.
530
-
531
- **prerequisites**: You must be an *owner* or *developer* to use this method.
532
-
533
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity - optional
534
- :param str pipeline_id: pipeline_id - optional
535
- :param str pipeline_name: pipeline_name - optional
536
- :param bool stop_if_running: If the pipeline is installed it will stop the pipeline and reset the counters.
537
- :return: bool
538
-
539
- **Example**:
540
-
541
- .. code-block:: python
542
-
543
- success = project.pipelines.reset(pipeline='pipeline_entity')
544
- """
545
-
546
- if pipeline_id is None:
547
- if pipeline is None:
548
- if pipeline_name is not None:
549
- pipeline = self.get(pipeline_name=pipeline_name)
550
- else:
551
- raise exceptions.PlatformException(
552
- '400',
553
- 'Must provide one of pipeline, pipeline_id or pipeline_name'
554
- )
555
- pipeline_id = pipeline.id
556
-
557
- if stop_if_running is True:
558
- if pipeline is None:
559
- pipeline = self.get(pipeline_id=pipeline_id)
560
- pipeline.pause()
561
-
562
- success, response = self._client_api.gen_request(
563
- req_type='post',
564
- path='/pipelines/{}/reset'.format(pipeline_id)
565
- )
566
-
567
- if not success:
568
- raise exceptions.PlatformException(response)
569
-
570
- return True
571
-
572
- @_api_reference.add(path='/pipelines/{id}/statistics', method='get')
573
- def stats(self, pipeline: entities.Pipeline = None, pipeline_id: str = None, pipeline_name: str = None):
574
- """
575
- Get pipeline counters.
576
-
577
- **prerequisites**: You must be an *owner* or *developer* to use this method.
578
-
579
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity - optional
580
- :param str pipeline_id: pipeline_id - optional
581
- :param str pipeline_name: pipeline_name - optional
582
- :return: PipelineStats
583
- :rtype: dtlpy.entities.pipeline.PipelineStats
584
-
585
- **Example**:
586
-
587
- .. code-block:: python
588
-
589
- pipeline_stats = project.pipelines.stats(pipeline='pipeline_entity')
590
- """
591
-
592
- if pipeline_id is None:
593
- if pipeline is None:
594
- if pipeline_name is not None:
595
- pipeline = self.get(pipeline_name=pipeline_name)
596
- else:
597
- raise exceptions.PlatformException(
598
- '400',
599
- 'Must provide one of pipeline, pipeline_id or pipeline_name'
600
- )
601
- pipeline_id = pipeline.id
602
-
603
- success, response = self._client_api.gen_request(
604
- req_type='get',
605
- path='/pipelines/{}/statistics'.format(pipeline_id)
606
- )
607
-
608
- if not success:
609
- raise exceptions.PlatformException(response)
610
-
611
- return entities.PipelineStats.from_json(_json=response.json())
612
-
613
- def execute(self,
614
- pipeline: entities.Pipeline = None,
615
- pipeline_id: str = None,
616
- pipeline_name: str = None,
617
- execution_input=None):
618
- """
619
- Execute a pipeline and return the pipeline execution as an object.
620
-
621
- **prerequisites**: You must be an *owner* or *developer* to use this method.
622
-
623
- :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
624
- :param str pipeline_id: pipeline id
625
- :param str pipeline_name: pipeline name
626
- :param execution_input: list of the dl.FunctionIO or dict of pipeline input - example {'item': 'item_id'}
627
- :return: entities.PipelineExecution object
628
- :rtype: dtlpy.entities.pipeline_execution.PipelineExecution
629
-
630
- **Example**:
631
-
632
- .. code-block:: python
633
-
634
- pipeline_execution= project.pipelines.execute(pipeline='pipeline_entity', execution_input= {'item': 'item_id'} )
635
- """
636
- if pipeline is None:
637
- pipeline = self.get(pipeline_id=pipeline_id, pipeline_name=pipeline_name)
638
- execution = repositories.PipelineExecutions(pipeline=pipeline,
639
- client_api=self._client_api,
640
- project=self._project).create(pipeline_id=pipeline.id,
641
- execution_input=execution_input)
642
- return execution
1
+ import logging
2
+ from .. import entities, repositories, exceptions, miscellaneous, _api_reference
3
+ from ..services.api_client import ApiClient
4
+
5
+ logger = logging.getLogger(name='dtlpy')
6
+
7
+
8
+ def generate_basic_pipeline():
9
+ return dict(name="", projectId="", nodes=[], connections=[], startNodes=[], variables=[])
10
+
11
+
12
+ class Pipelines:
13
+ """
14
+ Pipelines Repository
15
+
16
+ The Pipelines class allows users to manage pipelines and their properties. See our documentation for more information on `pipelines <https://dataloop.ai/docs/pipelines-overview>`_.
17
+ """
18
+
19
+ def __init__(self, client_api: ApiClient, project: entities.Project = None):
20
+ self._client_api = client_api
21
+ self._project = project
22
+
23
+ ############
24
+ # entities #
25
+ ############
26
+ @property
27
+ def project(self) -> entities.Project:
28
+ if self._project is None:
29
+ try:
30
+ self._project = repositories.Projects(client_api=self._client_api).get()
31
+ except exceptions.NotFound:
32
+ raise exceptions.PlatformException(
33
+ error='2001',
34
+ message='Missing "project". need to set a Project entity or use project.pipelines repository')
35
+ return self._project
36
+
37
+ @project.setter
38
+ def project(self, project: entities.Project):
39
+ if not isinstance(project, entities.Project):
40
+ raise ValueError('Must input a valid Project entity')
41
+ self._project = project
42
+
43
+ ###########
44
+ # methods #
45
+ ###########
46
+ @property
47
+ def platform_url(self):
48
+ return self._client_api._get_resource_url("projects/{}/pipelines".format(self.project.id))
49
+
50
+ def open_in_web(self,
51
+ pipeline: entities.Pipeline = None,
52
+ pipeline_id: str = None,
53
+ pipeline_name: str = None):
54
+ """
55
+ Open the pipeline in web platform.
56
+
57
+ **prerequisites**: Must be *owner* or *developer* to use this method.
58
+
59
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
60
+ :param str pipeline_id: pipeline id
61
+ :param str pipeline_name: pipeline name
62
+
63
+ **Example**:
64
+
65
+ .. code-block:: python
66
+
67
+ project.pipelines.open_in_web(pipeline_id='pipeline_id')
68
+ """
69
+ if pipeline_name is not None:
70
+ pipeline = self.get(pipeline_name=pipeline_name)
71
+ if pipeline is not None:
72
+ pipeline.open_in_web()
73
+ elif pipeline_id is not None:
74
+ self._client_api._open_in_web(url=self.platform_url + '/' + str(pipeline_id))
75
+ else:
76
+ self._client_api._open_in_web(url=self.platform_url)
77
+
78
+ @_api_reference.add(path='/pipelines/{pipelineId}', method='get')
79
+ def get(self,
80
+ pipeline_name=None,
81
+ pipeline_id=None,
82
+ fetch=None
83
+ ) -> entities.Pipeline:
84
+ """
85
+ Get Pipeline object to use in your code.
86
+
87
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
88
+
89
+ You must provide at least ONE of the following params: pipeline_name, pipeline_id.
90
+
91
+ :param str pipeline_id: pipeline id
92
+ :param str pipeline_name: pipeline name
93
+ :param fetch: optional - fetch entity from platform, default taken from cookie
94
+ :return: Pipeline object
95
+ :rtype: dtlpy.entities.pipeline.Pipeline
96
+
97
+ **Example**:
98
+
99
+ .. code-block:: python
100
+
101
+ pipeline = project.pipelines.get(pipeline_id='pipeline_id')
102
+ """
103
+ if fetch is None:
104
+ fetch = self._client_api.fetch_entities
105
+
106
+ if pipeline_name is None and pipeline_id is None:
107
+ raise exceptions.PlatformException(
108
+ error='400',
109
+ message='Must provide an identifier in inputs')
110
+ elif fetch:
111
+ if pipeline_id is not None:
112
+ success, response = self._client_api.gen_request(
113
+ req_type="get",
114
+ path="/pipelines/{}".format(pipeline_id))
115
+ if not success:
116
+ raise exceptions.PlatformException(response)
117
+ pipeline = entities.Pipeline.from_json(
118
+ client_api=self._client_api,
119
+ _json=response.json(),
120
+ project=self._project
121
+ )
122
+ if pipeline_name is not None and pipeline.name != pipeline_name:
123
+ logger.warning(
124
+ "Mismatch found in pipeline.get: pipeline_name is different then pipeline.name:"
125
+ " {!r} != {!r}".format(
126
+ pipeline_name,
127
+ pipeline.name
128
+ )
129
+ )
130
+ elif pipeline_name is not None:
131
+ filters = entities.Filters(
132
+ field='name',
133
+ values=pipeline_name,
134
+ resource=entities.FiltersResource.PIPELINE,
135
+ use_defaults=False
136
+ )
137
+ if self._project is not None:
138
+ filters.add(field='projectId', values=self._project.id)
139
+ pipelines = self.list(filters=filters)
140
+ if pipelines.items_count == 0:
141
+ raise exceptions.PlatformException(
142
+ error='404',
143
+ message='Pipeline not found. Name: {}'.format(pipeline_name))
144
+ elif pipelines.items_count > 1:
145
+ raise exceptions.PlatformException(
146
+ error='400',
147
+ message='More than one pipelines found by the name of: {} '
148
+ 'Please get pipeline from a project entity'.format(pipeline_name))
149
+ pipeline = pipelines.items[0]
150
+ else:
151
+ raise exceptions.PlatformException(
152
+ error='400',
153
+ message='No checked-out pipeline was found, must checkout or provide an identifier in inputs')
154
+ else:
155
+ pipeline = entities.Pipeline.from_json(
156
+ _json={'id': pipeline_id,
157
+ 'name': pipeline_name},
158
+ client_api=self._client_api,
159
+ project=self._project,
160
+ is_fetched=False
161
+ )
162
+
163
+ return pipeline
164
+
165
+ def _build_entities_from_response(self, response_items) -> miscellaneous.List[entities.Pipeline]:
166
+ pool = self._client_api.thread_pools(pool_name='entity.create')
167
+ jobs = [None for _ in range(len(response_items))]
168
+
169
+ for i_pipeline, pipeline in enumerate(response_items):
170
+ jobs[i_pipeline] = pool.submit(
171
+ entities.Pipeline._protected_from_json,
172
+ **{
173
+ 'client_api': self._client_api,
174
+ '_json': pipeline,
175
+ 'project': self._project
176
+ }
177
+ )
178
+
179
+ # get all results
180
+ # noinspection PyUnresolvedReferences
181
+ results = [j.result() for j in jobs]
182
+ # log errors
183
+ _ = [logger.warning(r[1]) for r in results if r[0] is False]
184
+ # return good jobs
185
+ pipelines = miscellaneous.List([r[1] for r in results if r[0] is True])
186
+ return pipelines
187
+
188
+ def _list(self, filters: entities.Filters):
189
+ url = '/pipelines/query'
190
+
191
+ # request
192
+ success, response = self._client_api.gen_request(
193
+ req_type='post',
194
+ path=url,
195
+ json_req=filters.prepare()
196
+ )
197
+ if not success:
198
+ raise exceptions.PlatformException(response)
199
+ return response.json()
200
+
201
+ @_api_reference.add(path='/pipelines/query', method='post')
202
+ def list(self,
203
+ filters: entities.Filters = None,
204
+ project_id: str = None
205
+ ) -> entities.PagedEntities:
206
+ """
207
+ List project pipelines.
208
+
209
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
210
+
211
+ :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
212
+ :param str project_id: project id
213
+ :return: Paged entity
214
+ :rtype: dtlpy.entities.paged_entities.PagedEntities
215
+
216
+ **Example**:
217
+
218
+ .. code-block:: python
219
+
220
+ pipelines = project.pipelines.list()
221
+ """
222
+ if filters is None:
223
+ filters = entities.Filters(resource=entities.FiltersResource.PIPELINE)
224
+ # assert type filters
225
+ elif not isinstance(filters, entities.Filters):
226
+ raise exceptions.PlatformException(error='400',
227
+ message='Unknown filters type: {!r}'.format(type(filters)))
228
+ if filters.resource != entities.FiltersResource.PIPELINE:
229
+ raise exceptions.PlatformException(
230
+ error='400',
231
+ message='Filters resource must to be FiltersResource.PIPELINE. Got: {!r}'.format(filters.resource))
232
+
233
+ if project_id is None and self._project is not None:
234
+ project_id = self._project.id
235
+
236
+ if project_id is not None:
237
+ filters.add(field='projectId', values=project_id)
238
+
239
+ paged = entities.PagedEntities(items_repository=self,
240
+ filters=filters,
241
+ page_offset=filters.page,
242
+ page_size=filters.page_size,
243
+ project_id=project_id,
244
+ client_api=self._client_api)
245
+ paged.get_page()
246
+ return paged
247
+
248
+ def _name_validation(self, name: str):
249
+ url = '/piper-misc/naming/packages/{}'.format(name)
250
+
251
+ # request
252
+ success, response = self._client_api.gen_request(req_type='get',
253
+ path=url)
254
+ if not success:
255
+ raise exceptions.PlatformException(response)
256
+
257
+ # @_api_reference.add(path='/pipelines/{pipelineId}', method='delete')
258
+ def delete(self,
259
+ pipeline: entities.Pipeline = None,
260
+ pipeline_name: str = None,
261
+ pipeline_id: str = None):
262
+ """
263
+ Delete Pipeline object.
264
+
265
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
266
+
267
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
268
+ :param str pipeline_id: pipeline id
269
+ :param str pipeline_name: pipeline name
270
+ :return: True if success
271
+ :rtype: bool
272
+
273
+ **Example**:
274
+
275
+ .. code-block:: python
276
+
277
+ is_deleted = project.pipelines.delete(pipeline_id='pipeline_id')
278
+ """
279
+ # get id and name
280
+ if pipeline_id is None:
281
+ if pipeline is None:
282
+ pipeline = self.get(pipeline_name=pipeline_name)
283
+ pipeline_id = pipeline.id
284
+
285
+ # request
286
+ success, response = self._client_api.gen_request(req_type="delete",
287
+ path="/pipelines/{}".format(pipeline_id))
288
+
289
+ # exception handling
290
+ if not success:
291
+ raise exceptions.PlatformException(response)
292
+
293
+ # return results
294
+ return True
295
+
296
+ @_api_reference.add(path='/pipelines/{pipelineId}/settings', method='patch')
297
+ def update_settings(self, pipeline: entities.Pipeline, settings: entities.PipelineSettings):
298
+ """
299
+ Update pipeline settings.
300
+
301
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
302
+
303
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
304
+ :param dtlpy.entities.pipeline.PipelineSettings settings: settings entity
305
+ :return: Pipeline object
306
+ :rtype: dtlpy.entities.pipeline.Pipeline
307
+
308
+ **Example**:
309
+
310
+ .. code-block:: python
311
+
312
+ pipeline = project.pipelines.update_settings(pipeline='pipeline_entity', settings=dl.PipelineSettings(keep_triggers_active=True))
313
+ """
314
+ # payload
315
+ payload = {'settings': settings.to_json()}
316
+
317
+ # request
318
+ success, response = self._client_api.gen_request(
319
+ req_type='patch',
320
+ path='/pipelines/{}'.format(pipeline.id),
321
+ json_req=payload
322
+ )
323
+ if not success:
324
+ raise exceptions.PlatformException(response)
325
+
326
+ # return entity
327
+ return entities.Pipeline.from_json(
328
+ _json=response.json(),
329
+ client_api=self._client_api,
330
+ project=self._project
331
+ )
332
+
333
+ def __update_variables(self, pipeline: entities.Pipeline):
334
+ pipeline_json = pipeline.to_json()
335
+ variables = pipeline_json.get('variables', list())
336
+
337
+ for var in variables:
338
+ if var.get('reference', None) is None:
339
+ var['reference'] = pipeline.id
340
+
341
+ # payload
342
+ payload = {'variables': variables}
343
+
344
+ # request
345
+ success, response = self._client_api.gen_request(
346
+ req_type='patch',
347
+ path='/pipelines/{}/variables'.format(pipeline.id),
348
+ json_req=payload
349
+ )
350
+ if not success:
351
+ raise exceptions.PlatformException(response)
352
+
353
+ # return entity
354
+ return entities.Pipeline.from_json(
355
+ _json=response.json(),
356
+ client_api=self._client_api,
357
+ project=self._project
358
+ )
359
+
360
+ @_api_reference.add(path='/pipelines/{pipelineId}', method='patch')
361
+ def update(self,
362
+ pipeline: entities.Pipeline = None
363
+ ) -> entities.Pipeline:
364
+ """
365
+ Update pipeline changes to platform.
366
+
367
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
368
+
369
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
370
+ :return: Pipeline object
371
+ :rtype: dtlpy.entities.pipeline.Pipeline
372
+
373
+ **Example**:
374
+
375
+ .. code-block:: python
376
+
377
+ pipeline = project.pipelines.update(pipeline='pipeline_entity')
378
+ """
379
+ # payload
380
+ payload = pipeline.to_json()
381
+
382
+ # update settings
383
+ if pipeline.settings_changed():
384
+ new_pipeline = self.update_settings(pipeline=pipeline, settings=pipeline.settings)
385
+ payload['settings'] = new_pipeline.to_json().get('settings', payload.get('settings'))
386
+
387
+ # update variables
388
+ if pipeline.variables_changed():
389
+ new_pipeline = self.__update_variables(pipeline=pipeline)
390
+ payload['variables'] = new_pipeline.to_json().get('variables', payload.get('variables'))
391
+
392
+ success, response = self._client_api.gen_request(
393
+ req_type='patch',
394
+ path='/pipelines/{}'.format(pipeline.id),
395
+ json_req=payload
396
+ )
397
+
398
+ # exception handling
399
+ if not success:
400
+ raise exceptions.PlatformException(response)
401
+
402
+ # return entity
403
+ return entities.Pipeline.from_json(
404
+ _json=response.json(),
405
+ client_api=self._client_api,
406
+ project=self._project
407
+ )
408
+
409
+ @_api_reference.add(path='/pipelines', method='post')
410
+ def create(self,
411
+ name: str = None,
412
+ project_id: str = None,
413
+ pipeline_json: dict = None
414
+ ) -> entities.Pipeline:
415
+ """
416
+ Create a new pipeline.
417
+
418
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
419
+
420
+ :param str name: pipeline name
421
+ :param str project_id: project id
422
+ :param dict pipeline_json: json containing the pipeline fields
423
+ :return: Pipeline object
424
+ :rtype: dtlpy.entities.pipeline.Pipeline
425
+
426
+ **Example**:
427
+
428
+ .. code-block:: python
429
+
430
+ pipeline = project.pipelines.create(name='pipeline_name')
431
+ """
432
+ if pipeline_json is None:
433
+ pipeline_json = generate_basic_pipeline()
434
+
435
+ if name is not None:
436
+ pipeline_json['name'] = name
437
+
438
+ if project_id is not None:
439
+ pipeline_json['projectId'] = project_id
440
+ else:
441
+ if not pipeline_json.get('projectId', None):
442
+ pipeline_json['projectId'] = self.project.id
443
+
444
+ success, response = self._client_api.gen_request(req_type='post',
445
+ path='/pipelines',
446
+ json_req=pipeline_json)
447
+ if success:
448
+ pipeline = entities.Pipeline.from_json(client_api=self._client_api,
449
+ _json=response.json(),
450
+ project=self.project)
451
+ else:
452
+ raise exceptions.PlatformException(response)
453
+ assert isinstance(pipeline, entities.Pipeline)
454
+ return pipeline
455
+
456
+ @_api_reference.add(path='/pipelines/{pipelineId}/install', method='post')
457
+ def install(self, pipeline: entities.Pipeline = None, resume_option: entities.PipelineResumeOption = None):
458
+ """
459
+ Install (start) a pipeline.
460
+
461
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
462
+
463
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
464
+ :param dtlpy.entities.pipeline.PipelineResumeOption resume_option: optional - resume pipeline method (what to do with existing cycles)
465
+ :return: Composition object
466
+
467
+ **Example**:
468
+
469
+ .. code-block:: python
470
+
471
+ project.pipelines.install(pipeline='pipeline_entity')
472
+ """
473
+
474
+ payload = {}
475
+ if resume_option:
476
+ payload['resumeOption'] = resume_option
477
+
478
+ success, response = self._client_api.gen_request(
479
+ req_type='post',
480
+ path='/pipelines/{}/install'.format(pipeline.id),
481
+ json_req=payload
482
+ )
483
+
484
+ if not success:
485
+ raise exceptions.PlatformException(response)
486
+
487
+ return entities.Pipeline.from_json(client_api=self._client_api,
488
+ _json=response.json(),
489
+ project=self.project)
490
+
491
+ @_api_reference.add(path='/pipelines/{pipelineId}/uninstall', method='post')
492
+ def pause(self, pipeline: entities.Pipeline = None, keep_triggers_active: bool = None):
493
+ """
494
+ Pause a pipeline.
495
+
496
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
497
+
498
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
499
+ :param bool keep_triggers_active: Do we want the triggers to stay active and collect events
500
+ :return: Composition object
501
+
502
+ **Example**:
503
+
504
+ .. code-block:: python
505
+
506
+ project.pipelines.pause(pipeline='pipeline_entity')
507
+ """
508
+
509
+ payload = {}
510
+ if keep_triggers_active is not None:
511
+ payload['keepTriggersActive'] = keep_triggers_active
512
+
513
+ success, response = self._client_api.gen_request(
514
+ req_type='post',
515
+ path='/pipelines/{}/uninstall'.format(pipeline.id),
516
+ json_req=payload
517
+ )
518
+
519
+ if not success:
520
+ raise exceptions.PlatformException(response)
521
+
522
+ @_api_reference.add(path='/pipelines/{pipelineId}/reset', method='post')
523
+ def reset(self,
524
+ pipeline: entities.Pipeline = None,
525
+ pipeline_id: str = None,
526
+ pipeline_name: str = None,
527
+ stop_if_running: bool = False):
528
+ """
529
+ Reset pipeline counters.
530
+
531
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
532
+
533
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity - optional
534
+ :param str pipeline_id: pipeline_id - optional
535
+ :param str pipeline_name: pipeline_name - optional
536
+ :param bool stop_if_running: If the pipeline is installed it will stop the pipeline and reset the counters.
537
+ :return: bool
538
+
539
+ **Example**:
540
+
541
+ .. code-block:: python
542
+
543
+ success = project.pipelines.reset(pipeline='pipeline_entity')
544
+ """
545
+
546
+ if pipeline_id is None:
547
+ if pipeline is None:
548
+ if pipeline_name is not None:
549
+ pipeline = self.get(pipeline_name=pipeline_name)
550
+ else:
551
+ raise exceptions.PlatformException(
552
+ '400',
553
+ 'Must provide one of pipeline, pipeline_id or pipeline_name'
554
+ )
555
+ pipeline_id = pipeline.id
556
+
557
+ if stop_if_running is True:
558
+ if pipeline is None:
559
+ pipeline = self.get(pipeline_id=pipeline_id)
560
+ pipeline.pause()
561
+
562
+ success, response = self._client_api.gen_request(
563
+ req_type='post',
564
+ path='/pipelines/{}/reset'.format(pipeline_id)
565
+ )
566
+
567
+ if not success:
568
+ raise exceptions.PlatformException(response)
569
+
570
+ return True
571
+
572
+ @_api_reference.add(path='/pipelines/{id}/statistics', method='get')
573
+ def stats(self, pipeline: entities.Pipeline = None, pipeline_id: str = None, pipeline_name: str = None):
574
+ """
575
+ Get pipeline counters.
576
+
577
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
578
+
579
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity - optional
580
+ :param str pipeline_id: pipeline_id - optional
581
+ :param str pipeline_name: pipeline_name - optional
582
+ :return: PipelineStats
583
+ :rtype: dtlpy.entities.pipeline.PipelineStats
584
+
585
+ **Example**:
586
+
587
+ .. code-block:: python
588
+
589
+ pipeline_stats = project.pipelines.stats(pipeline='pipeline_entity')
590
+ """
591
+
592
+ if pipeline_id is None:
593
+ if pipeline is None:
594
+ if pipeline_name is not None:
595
+ pipeline = self.get(pipeline_name=pipeline_name)
596
+ else:
597
+ raise exceptions.PlatformException(
598
+ '400',
599
+ 'Must provide one of pipeline, pipeline_id or pipeline_name'
600
+ )
601
+ pipeline_id = pipeline.id
602
+
603
+ success, response = self._client_api.gen_request(
604
+ req_type='get',
605
+ path='/pipelines/{}/statistics'.format(pipeline_id)
606
+ )
607
+
608
+ if not success:
609
+ raise exceptions.PlatformException(response)
610
+
611
+ return entities.PipelineStats.from_json(_json=response.json())
612
+
613
+ def execute(self,
614
+ pipeline: entities.Pipeline = None,
615
+ pipeline_id: str = None,
616
+ pipeline_name: str = None,
617
+ execution_input=None):
618
+ """
619
+ Execute a pipeline and return the pipeline execution as an object.
620
+
621
+ **prerequisites**: You must be an *owner* or *developer* to use this method.
622
+
623
+ :param dtlpy.entities.pipeline.Pipeline pipeline: pipeline entity
624
+ :param str pipeline_id: pipeline id
625
+ :param str pipeline_name: pipeline name
626
+ :param execution_input: list of the dl.FunctionIO or dict of pipeline input - example {'item': 'item_id'}
627
+ :return: entities.PipelineExecution object
628
+ :rtype: dtlpy.entities.pipeline_execution.PipelineExecution
629
+
630
+ **Example**:
631
+
632
+ .. code-block:: python
633
+
634
+ pipeline_execution= project.pipelines.execute(pipeline='pipeline_entity', execution_input= {'item': 'item_id'} )
635
+ """
636
+ if pipeline is None:
637
+ pipeline = self.get(pipeline_id=pipeline_id, pipeline_name=pipeline_name)
638
+ execution = repositories.PipelineExecutions(pipeline=pipeline,
639
+ client_api=self._client_api,
640
+ project=self._project).create(pipeline_id=pipeline.id,
641
+ execution_input=execution_input)
642
+ return execution