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,536 +1,536 @@
1
- import logging
2
-
3
- from .. import entities, miscellaneous, exceptions, repositories, _api_reference
4
- from ..services.api_client import ApiClient
5
-
6
- logger = logging.getLogger(name='dtlpy')
7
-
8
-
9
- class Triggers:
10
- """
11
- Triggers Repository
12
-
13
- The Triggers class allows users to manage triggers and their properties. Triggers activate services.
14
- See our documentation for more information on `triggers <https://developers.dataloop.ai/tutorials/faas/concept/chapter/>`_.
15
- """
16
-
17
- def __init__(self,
18
- client_api: ApiClient,
19
- project: entities.Project = None,
20
- service: entities.Service = None,
21
- project_id: str = None,
22
- pipeline: entities.Pipeline = None):
23
- self._client_api = client_api
24
- self._project = project
25
- self._service = service
26
- self._pipeline = pipeline
27
- if project_id is None:
28
- if self._project is not None:
29
- project_id = self._project.id
30
- elif self._service is not None:
31
- project_id = self._service.project_id
32
-
33
- self._project_id = project_id
34
-
35
- ############
36
- # entities #
37
- ############
38
- @property
39
- def service(self) -> entities.Service:
40
- if self._service is None:
41
- raise exceptions.PlatformException(
42
- error='2001',
43
- message='Missing "service". need to set a Service entity or use service.triggers repository')
44
- assert isinstance(self._service, entities.Service)
45
- return self._service
46
-
47
- @service.setter
48
- def service(self, service: entities.Service):
49
- if not isinstance(service, entities.Service):
50
- raise ValueError('Must input a valid Service entity')
51
- self._service = service
52
-
53
- @property
54
- def pipeline(self) -> entities.Pipeline:
55
- if self._pipeline is None:
56
- raise exceptions.PlatformException(
57
- error='2001',
58
- message='Missing "pipeline". need to set a Pipeline entity or use pipeline.triggers repository')
59
- assert isinstance(self._pipeline, entities.Pipeline)
60
- return self._pipeline
61
-
62
- @pipeline.setter
63
- def pipeline(self, pipeline: entities.Pipeline):
64
- if not isinstance(pipeline, entities.Pipeline):
65
- raise ValueError('Must input a valid Service entity')
66
- self._pipeline = pipeline
67
-
68
- @property
69
- def project(self) -> entities.Project:
70
- if self._project is None:
71
- if self._service is not None:
72
- self._project = self._service._project
73
- if self._project is None:
74
- raise exceptions.PlatformException(
75
- error='2001',
76
- message='Missing "project". need to set a Project entity or use project.triggers repository')
77
- assert isinstance(self._project, entities.Project)
78
- return self._project
79
-
80
- @project.setter
81
- def project(self, project: entities.Project):
82
- if not isinstance(project, entities.Project):
83
- raise ValueError('Must input a valid Project entity')
84
- self._project = project
85
-
86
- def name_validation(self, name: str):
87
- """
88
- This method validates the trigger name. If name is not valid, this method will return an error. Otherwise, it will not return anything.
89
-
90
- :param str name: trigger name
91
- """
92
- url = '/piper-misc/naming/triggers/{}'.format(name)
93
-
94
- # request
95
- success, response = self._client_api.gen_request(req_type='get',
96
- path=url)
97
- if not success:
98
- raise exceptions.PlatformException(response)
99
-
100
- @_api_reference.add(path='/triggers', method='post')
101
- def create(self,
102
- # for both trigger types
103
- service_id: str = None,
104
- trigger_type: entities.TriggerType = entities.TriggerType.EVENT,
105
- name: str = None,
106
- webhook_id=None,
107
- function_name=entities.package_defaults.DEFAULT_PACKAGE_FUNCTION_NAME,
108
- project_id=None,
109
- active=True,
110
- # for event trigger
111
- filters=None,
112
- resource: entities.TriggerResource = entities.TriggerResource.ITEM,
113
- actions: entities.TriggerAction = None,
114
- execution_mode: entities.TriggerExecutionMode = entities.TriggerExecutionMode.ONCE,
115
- # for cron triggers
116
- start_at=None,
117
- end_at=None,
118
- inputs=None,
119
- cron=None,
120
- pipeline_id=None,
121
- pipeline=None,
122
- pipeline_node_id=None,
123
- root_node_namespace=None,
124
- **kwargs) -> entities.BaseTrigger:
125
- """
126
- Create a Trigger. Can create two types: a cron trigger or an event trigger.
127
- Inputs are different for each type
128
-
129
- **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
130
-
131
- Inputs for all types:
132
-
133
- :param str service_id: Id of services to be triggered
134
- :param str trigger_type: can be cron or event. use enum dl.TriggerType for the full list
135
- :param str name: name of the trigger
136
- :param str webhook_id: id for webhook to be called
137
- :param str function_name: the function name to be called when triggered (must be defined in the package)
138
- :param str project_id: project id where trigger will work
139
- :param bool active: optional - True/False, default = True, if true trigger is active
140
-
141
- Inputs for event trigger:
142
- :param dtlpy.entities.filters.Filters filters: optional - Item/Annotation metadata filters, default = none
143
- :param str resource: optional - Dataset/Item/Annotation/ItemStatus, default = Item
144
- :param str actions: optional - Created/Updated/Deleted, default = create
145
- :param str execution_mode: how many times trigger should be activated; default is "Once". enum dl.TriggerExecutionMode
146
-
147
- Inputs for cron trigger:
148
- :param start_at: iso format date string to start activating the cron trigger
149
- :param end_at: iso format date string to end the cron activation
150
- :param inputs: dictionary "name":"val" of inputs to the function
151
- :param str cron: cron spec specifying when it should run. more information: https://en.wikipedia.org/wiki/Cron
152
- :param str pipeline_id: Id of pipeline to be triggered
153
- :param pipeline: pipeline entity to be triggered
154
- :param str pipeline_node_id: Id of pipeline root node to be triggered
155
- :param root_node_namespace: namespace of pipeline root node to be triggered
156
-
157
- :return: Trigger entity
158
- :rtype: dtlpy.entities.trigger.Trigger
159
-
160
- **Example**:
161
-
162
- .. code-block:: python
163
-
164
- service.triggers.create(name='triggername',
165
- execution_mode=dl.TriggerExecutionMode.ONCE,
166
- resource='Item',
167
- actions='Created',
168
- function_name='run',
169
- filters={'$and': [{'hidden': False},
170
- {'type': 'file'}]}
171
- )
172
- """
173
- scope = kwargs.get('scope', None)
174
-
175
- if service_id is None and webhook_id is None and pipeline_id is None and pipeline is None:
176
- if self._service is not None:
177
- service_id = self._service.id
178
- elif self._pipeline is not None:
179
- pipeline = self._pipeline
180
- pipeline_id = self._pipeline.id
181
-
182
- if pipeline is not None:
183
- pipeline_id = pipeline.id
184
-
185
- # type
186
- input_num = sum(input_id is not None for input_id in [service_id, webhook_id, pipeline_id])
187
- if input_num != 1:
188
- raise exceptions.PlatformException('400',
189
- 'Must provide only one of service id, webhook id, pipeline id or pipeline')
190
-
191
- if pipeline_id is not None:
192
- if pipeline is None:
193
- pipeline = repositories.Pipelines(client_api=self._client_api).get(pipeline_id=pipeline_id)
194
- if pipeline_node_id is None:
195
- if pipeline.start_nodes:
196
- for pipe_node in pipeline.start_nodes:
197
- if pipe_node['type'] == 'root':
198
- pipeline_node_id = pipe_node['nodeId']
199
- if pipeline_node_id is None:
200
- raise exceptions.PlatformException('400', 'Must provide pipeline node id')
201
- if not actions:
202
- actions = [entities.TriggerAction.CREATED]
203
- pipeline.nodes.get(node_id=pipeline_node_id).add_trigger(
204
- trigger_type=trigger_type,
205
- filters=filters,
206
- resource=resource,
207
- actions=actions,
208
- execution_mode=execution_mode,
209
- cron=cron,
210
- )
211
- logger.info("The trigger will not create until pipeline is install")
212
- pipeline.update()
213
- return True
214
- else:
215
- if name is None:
216
- if self._service is not None:
217
- name = self._service.name
218
- else:
219
- name = 'defaulttrigger'
220
-
221
- if filters is None:
222
- filters = dict()
223
- elif isinstance(filters, entities.Filters):
224
- filters = filters.prepare(query_only=True).get('filter', dict())
225
-
226
- if webhook_id is not None:
227
- operation = {
228
- 'type': 'webhook',
229
- 'webhookId': webhook_id
230
- }
231
- else:
232
- operation = {
233
- 'type': 'function',
234
- 'serviceId': service_id,
235
- 'functionName': function_name
236
-
237
- }
238
-
239
- if actions is not None:
240
- if not isinstance(actions, list):
241
- actions = [actions]
242
- else:
243
- actions = [entities.TriggerAction.CREATED]
244
-
245
- if len(actions) == 0:
246
- actions = [entities.TriggerAction.CREATED]
247
-
248
- if trigger_type == entities.TriggerType.EVENT:
249
- spec = {
250
- 'filter': filters,
251
- 'resource': resource,
252
- 'executionMode': execution_mode,
253
- 'actions': actions
254
- }
255
- elif trigger_type == entities.TriggerType.CRON:
256
- spec = {
257
- 'endAt': end_at,
258
- 'startAt': start_at,
259
- 'cron': cron,
260
- }
261
- else:
262
- raise ValueError('Unknown trigger type: "{}". Use dl.TriggerType for known types'.format(trigger_type))
263
-
264
- spec['input'] = dict() if inputs is None else inputs
265
- spec['operation'] = operation
266
-
267
- # payload
268
- if self._project_id is None and project_id is None:
269
- raise exceptions.PlatformException('400', 'Please provide a project id')
270
- elif project_id is None:
271
- project_id = self._project_id
272
-
273
- payload = {
274
- 'type': trigger_type,
275
- 'active': active,
276
- 'projectId': project_id,
277
- 'name': name,
278
- 'spec': spec
279
- }
280
-
281
- if scope is not None:
282
- logger.warning(
283
- "Only superuser is allowed to define a trigger's scope. "
284
- "If you are not a superuser you will not be able to perform this action")
285
- payload['scope'] = scope
286
-
287
- # request
288
- success, response = self._client_api.gen_request(req_type='post',
289
- path='/triggers',
290
- json_req=payload)
291
-
292
- # exception handling
293
- if not success:
294
- raise exceptions.PlatformException(response)
295
-
296
- # return entity
297
- return entities.BaseTrigger.from_json(_json=response.json(),
298
- client_api=self._client_api,
299
- project=self._project if self._project_id == project_id else None,
300
- service=self._service)
301
-
302
- @_api_reference.add(path='/triggers/{id}', method='get')
303
- def get(self, trigger_id=None, trigger_name=None) -> entities.BaseTrigger:
304
- """
305
- Get Trigger object
306
-
307
- **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
308
-
309
- :param str trigger_id: trigger id
310
- :param str trigger_name: trigger name
311
- :return: Trigger entity
312
- :rtype: dtlpy.entities.trigger.Trigger
313
-
314
- **Example**:
315
-
316
- .. code-block:: python
317
-
318
- service.triggers.get(trigger_id='trigger_id')
319
- """
320
- # request
321
- if trigger_id is not None:
322
- success, response = self._client_api.gen_request(
323
- req_type="get",
324
- path="/triggers/{}".format(trigger_id)
325
- )
326
-
327
- # exception handling
328
- if not success:
329
- raise exceptions.PlatformException(response)
330
-
331
- # return entity
332
- trigger = entities.BaseTrigger.from_json(client_api=self._client_api,
333
- _json=response.json(),
334
- project=self._project,
335
- service=self._service)
336
- # verify input trigger name is same as the given id
337
- if trigger_name is not None and trigger.name != trigger_name:
338
- logger.warning(
339
- "Mismatch found in triggers.get: trigger_name is different then trigger.name:"
340
- " {!r} != {!r}".format(
341
- trigger_name,
342
- trigger.name))
343
- else:
344
- if trigger_name is None:
345
- raise exceptions.PlatformException('400', 'Must provide either trigger name or trigger id')
346
- else:
347
- filters = self.__generate_default_filter()
348
- filters.add(field='name', values=trigger_name)
349
- triggers = self.list(filters)
350
- if triggers.items_count == 0:
351
- raise exceptions.PlatformException('404', 'Trigger not found')
352
- elif triggers.items_count == 1:
353
- trigger = triggers.items[0]
354
- else:
355
- raise exceptions.PlatformException('404',
356
- 'More than one trigger by name {} exist'.format(trigger_name))
357
-
358
- return trigger
359
-
360
- @_api_reference.add(path='/triggers/{id}', method='delete')
361
- def delete(self, trigger_id=None, trigger_name=None):
362
- """
363
- Delete Trigger object
364
-
365
- **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
366
-
367
- :param str trigger_id: trigger id
368
- :param str trigger_name: trigger name
369
- :return: True is successful error if not
370
- :rtype: bool
371
-
372
- **Example**:
373
-
374
- .. code-block:: python
375
-
376
- service.triggers.delete(trigger_id='trigger_id')
377
- """
378
- if trigger_id is None:
379
- if trigger_name is None:
380
- raise exceptions.PlatformException('400', 'Must provide either trigger name or trigger id')
381
- else:
382
- trigger_id = self.get(trigger_name=trigger_name).id
383
- # request
384
- success, response = self._client_api.gen_request(
385
- req_type="delete",
386
- path="/triggers/{}".format(trigger_id)
387
- )
388
- # exception handling
389
- if not success:
390
- raise exceptions.PlatformException(response)
391
- return True
392
-
393
- @_api_reference.add(path='/triggers/{id}', method='patch')
394
- def update(self, trigger: entities.BaseTrigger) -> entities.BaseTrigger:
395
- """
396
- Update trigger
397
-
398
- **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
399
-
400
- :param dtlpy.entities.trigger.Trigger trigger: Trigger entity
401
- :return: Trigger entity
402
- :rtype: dtlpy.entities.trigger.Trigger
403
-
404
- **Example**:
405
-
406
- .. code-block:: python
407
-
408
- service.triggers.update(trigger='trigger_entity')
409
- """
410
- # payload
411
- payload = trigger.to_json()
412
-
413
- # request
414
- success, response = self._client_api.gen_request(req_type='patch',
415
- path='/triggers/{}'.format(trigger.id),
416
- json_req=payload)
417
-
418
- # exception handling
419
- if not success:
420
- raise exceptions.PlatformException(response)
421
-
422
- # return entity
423
- return entities.BaseTrigger.from_json(_json=response.json(),
424
- client_api=self._client_api,
425
- project=self._project,
426
- service=self._service)
427
-
428
- def _build_entities_from_response(self, response_items) -> miscellaneous.List[entities.BaseTrigger]:
429
- pool = self._client_api.thread_pools(pool_name='entity.create')
430
- jobs = [None for _ in range(len(response_items))]
431
- # return triggers list
432
- for i_trigger, trigger in enumerate(response_items):
433
- jobs[i_trigger] = pool.submit(entities.BaseTrigger._protected_from_json,
434
- **{'client_api': self._client_api,
435
- '_json': trigger,
436
- 'project': self._project,
437
- 'service': self._service})
438
-
439
- # get all results
440
- results = [j.result() for j in jobs]
441
- # log errors
442
- _ = [logger.warning(r[1]) for r in results if r[0] is False]
443
- # return good jobs
444
- triggers = miscellaneous.List([r[1] for r in results if r[0] is True])
445
- return triggers
446
-
447
- def _list(self, filters: entities.Filters):
448
- """
449
- List project triggers
450
- :return:
451
- """
452
- url = '/query/faas'
453
-
454
- success, response = self._client_api.gen_request(req_type='POST',
455
- path=url,
456
- json_req=filters.prepare())
457
- if not success:
458
- raise exceptions.PlatformException(response)
459
- return response.json()
460
-
461
- def __generate_default_filter(self):
462
- filters = entities.Filters(resource=entities.FiltersResource.TRIGGER)
463
- if self._project is not None:
464
- filters.add(field='projectId', values=self._project.id)
465
- if self._service is not None:
466
- filters.add(field='spec.operation.serviceId', values=self._service.id)
467
- if self._pipeline is not None:
468
- filters.add(field='spec.operation.id', values=self._pipeline.id)
469
-
470
- return filters
471
-
472
- @_api_reference.add(path='/query/faas', method='post')
473
- def list(self, filters: entities.Filters = None) -> entities.PagedEntities:
474
- """
475
- List triggers of a project, package, or service.
476
-
477
- **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
478
-
479
- :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
480
- :return: Paged entity
481
- :rtype: dtlpy.entities.paged_entities.PagedEntities
482
-
483
- **Example**:
484
-
485
- .. code-block:: python
486
-
487
- service.triggers.list()
488
- """
489
- if filters is None:
490
- filters = self.__generate_default_filter()
491
- # assert type filters
492
- elif not isinstance(filters, entities.Filters):
493
- raise exceptions.PlatformException(error='400',
494
- message='Unknown filters type: {!r}'.format(type(filters)))
495
-
496
- if filters.resource != entities.FiltersResource.TRIGGER:
497
- raise exceptions.PlatformException(
498
- error='400',
499
- message='Filters resource must to be FiltersResource.TRIGGER. Got: {!r}'.format(filters.resource))
500
-
501
- paged = entities.PagedEntities(items_repository=self,
502
- filters=filters,
503
- page_offset=filters.page,
504
- page_size=filters.page_size,
505
- client_api=self._client_api)
506
- paged.get_page()
507
- return paged
508
-
509
- def resource_information(self, resource, resource_type, action='Created'):
510
- """
511
- Returns which function should run on an item (based on global triggers).
512
-
513
- **Prerequisites**: You must be a **superuser** to run this method.
514
-
515
- :param resource: 'Item' / 'Dataset' / etc
516
- :param resource_type: dictionary of the resource object
517
- :param action: 'Created' / 'Updated' / etc.
518
-
519
- **Example**:
520
-
521
- .. code-block:: python
522
-
523
- service.triggers.resource_information(resource='Item', resource_type=item_object, action='Created')
524
- """
525
- url = '/trigger-resource-information'
526
-
527
- payload = {'resource': resource_type,
528
- 'entity': resource.to_json(),
529
- 'action': action}
530
- # request
531
- success, response = self._client_api.gen_request(req_type='post',
532
- path=url,
533
- json_req=payload)
534
- if not success:
535
- raise exceptions.PlatformException(response)
536
- return response.json()
1
+ import logging
2
+
3
+ from .. import entities, miscellaneous, exceptions, repositories, _api_reference
4
+ from ..services.api_client import ApiClient
5
+
6
+ logger = logging.getLogger(name='dtlpy')
7
+
8
+
9
+ class Triggers:
10
+ """
11
+ Triggers Repository
12
+
13
+ The Triggers class allows users to manage triggers and their properties. Triggers activate services.
14
+ See our documentation for more information on `triggers <https://developers.dataloop.ai/tutorials/faas/concept/chapter/>`_.
15
+ """
16
+
17
+ def __init__(self,
18
+ client_api: ApiClient,
19
+ project: entities.Project = None,
20
+ service: entities.Service = None,
21
+ project_id: str = None,
22
+ pipeline: entities.Pipeline = None):
23
+ self._client_api = client_api
24
+ self._project = project
25
+ self._service = service
26
+ self._pipeline = pipeline
27
+ if project_id is None:
28
+ if self._project is not None:
29
+ project_id = self._project.id
30
+ elif self._service is not None:
31
+ project_id = self._service.project_id
32
+
33
+ self._project_id = project_id
34
+
35
+ ############
36
+ # entities #
37
+ ############
38
+ @property
39
+ def service(self) -> entities.Service:
40
+ if self._service is None:
41
+ raise exceptions.PlatformException(
42
+ error='2001',
43
+ message='Missing "service". need to set a Service entity or use service.triggers repository')
44
+ assert isinstance(self._service, entities.Service)
45
+ return self._service
46
+
47
+ @service.setter
48
+ def service(self, service: entities.Service):
49
+ if not isinstance(service, entities.Service):
50
+ raise ValueError('Must input a valid Service entity')
51
+ self._service = service
52
+
53
+ @property
54
+ def pipeline(self) -> entities.Pipeline:
55
+ if self._pipeline is None:
56
+ raise exceptions.PlatformException(
57
+ error='2001',
58
+ message='Missing "pipeline". need to set a Pipeline entity or use pipeline.triggers repository')
59
+ assert isinstance(self._pipeline, entities.Pipeline)
60
+ return self._pipeline
61
+
62
+ @pipeline.setter
63
+ def pipeline(self, pipeline: entities.Pipeline):
64
+ if not isinstance(pipeline, entities.Pipeline):
65
+ raise ValueError('Must input a valid Service entity')
66
+ self._pipeline = pipeline
67
+
68
+ @property
69
+ def project(self) -> entities.Project:
70
+ if self._project is None:
71
+ if self._service is not None:
72
+ self._project = self._service._project
73
+ if self._project is None:
74
+ raise exceptions.PlatformException(
75
+ error='2001',
76
+ message='Missing "project". need to set a Project entity or use project.triggers repository')
77
+ assert isinstance(self._project, entities.Project)
78
+ return self._project
79
+
80
+ @project.setter
81
+ def project(self, project: entities.Project):
82
+ if not isinstance(project, entities.Project):
83
+ raise ValueError('Must input a valid Project entity')
84
+ self._project = project
85
+
86
+ def name_validation(self, name: str):
87
+ """
88
+ This method validates the trigger name. If name is not valid, this method will return an error. Otherwise, it will not return anything.
89
+
90
+ :param str name: trigger name
91
+ """
92
+ url = '/piper-misc/naming/triggers/{}'.format(name)
93
+
94
+ # request
95
+ success, response = self._client_api.gen_request(req_type='get',
96
+ path=url)
97
+ if not success:
98
+ raise exceptions.PlatformException(response)
99
+
100
+ @_api_reference.add(path='/triggers', method='post')
101
+ def create(self,
102
+ # for both trigger types
103
+ service_id: str = None,
104
+ trigger_type: entities.TriggerType = entities.TriggerType.EVENT,
105
+ name: str = None,
106
+ webhook_id=None,
107
+ function_name=entities.package_defaults.DEFAULT_PACKAGE_FUNCTION_NAME,
108
+ project_id=None,
109
+ active=True,
110
+ # for event trigger
111
+ filters=None,
112
+ resource: entities.TriggerResource = entities.TriggerResource.ITEM,
113
+ actions: entities.TriggerAction = None,
114
+ execution_mode: entities.TriggerExecutionMode = entities.TriggerExecutionMode.ONCE,
115
+ # for cron triggers
116
+ start_at=None,
117
+ end_at=None,
118
+ inputs=None,
119
+ cron=None,
120
+ pipeline_id=None,
121
+ pipeline=None,
122
+ pipeline_node_id=None,
123
+ root_node_namespace=None,
124
+ **kwargs) -> entities.BaseTrigger:
125
+ """
126
+ Create a Trigger. Can create two types: a cron trigger or an event trigger.
127
+ Inputs are different for each type
128
+
129
+ **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
130
+
131
+ Inputs for all types:
132
+
133
+ :param str service_id: Id of services to be triggered
134
+ :param str trigger_type: can be cron or event. use enum dl.TriggerType for the full list
135
+ :param str name: name of the trigger
136
+ :param str webhook_id: id for webhook to be called
137
+ :param str function_name: the function name to be called when triggered (must be defined in the package)
138
+ :param str project_id: project id where trigger will work
139
+ :param bool active: optional - True/False, default = True, if true trigger is active
140
+
141
+ Inputs for event trigger:
142
+ :param dtlpy.entities.filters.Filters filters: optional - Item/Annotation metadata filters, default = none
143
+ :param str resource: optional - Dataset/Item/Annotation/ItemStatus, default = Item
144
+ :param str actions: optional - Created/Updated/Deleted, default = create
145
+ :param str execution_mode: how many times trigger should be activated; default is "Once". enum dl.TriggerExecutionMode
146
+
147
+ Inputs for cron trigger:
148
+ :param start_at: iso format date string to start activating the cron trigger
149
+ :param end_at: iso format date string to end the cron activation
150
+ :param inputs: dictionary "name":"val" of inputs to the function
151
+ :param str cron: cron spec specifying when it should run. more information: https://en.wikipedia.org/wiki/Cron
152
+ :param str pipeline_id: Id of pipeline to be triggered
153
+ :param pipeline: pipeline entity to be triggered
154
+ :param str pipeline_node_id: Id of pipeline root node to be triggered
155
+ :param root_node_namespace: namespace of pipeline root node to be triggered
156
+
157
+ :return: Trigger entity
158
+ :rtype: dtlpy.entities.trigger.Trigger
159
+
160
+ **Example**:
161
+
162
+ .. code-block:: python
163
+
164
+ service.triggers.create(name='triggername',
165
+ execution_mode=dl.TriggerExecutionMode.ONCE,
166
+ resource='Item',
167
+ actions='Created',
168
+ function_name='run',
169
+ filters={'$and': [{'hidden': False},
170
+ {'type': 'file'}]}
171
+ )
172
+ """
173
+ scope = kwargs.get('scope', None)
174
+
175
+ if service_id is None and webhook_id is None and pipeline_id is None and pipeline is None:
176
+ if self._service is not None:
177
+ service_id = self._service.id
178
+ elif self._pipeline is not None:
179
+ pipeline = self._pipeline
180
+ pipeline_id = self._pipeline.id
181
+
182
+ if pipeline is not None:
183
+ pipeline_id = pipeline.id
184
+
185
+ # type
186
+ input_num = sum(input_id is not None for input_id in [service_id, webhook_id, pipeline_id])
187
+ if input_num != 1:
188
+ raise exceptions.PlatformException('400',
189
+ 'Must provide only one of service id, webhook id, pipeline id or pipeline')
190
+
191
+ if pipeline_id is not None:
192
+ if pipeline is None:
193
+ pipeline = repositories.Pipelines(client_api=self._client_api).get(pipeline_id=pipeline_id)
194
+ if pipeline_node_id is None:
195
+ if pipeline.start_nodes:
196
+ for pipe_node in pipeline.start_nodes:
197
+ if pipe_node['type'] == 'root':
198
+ pipeline_node_id = pipe_node['nodeId']
199
+ if pipeline_node_id is None:
200
+ raise exceptions.PlatformException('400', 'Must provide pipeline node id')
201
+ if not actions:
202
+ actions = [entities.TriggerAction.CREATED]
203
+ pipeline.nodes.get(node_id=pipeline_node_id).add_trigger(
204
+ trigger_type=trigger_type,
205
+ filters=filters,
206
+ resource=resource,
207
+ actions=actions,
208
+ execution_mode=execution_mode,
209
+ cron=cron,
210
+ )
211
+ logger.info("The trigger will not create until pipeline is install")
212
+ pipeline.update()
213
+ return True
214
+ else:
215
+ if name is None:
216
+ if self._service is not None:
217
+ name = self._service.name
218
+ else:
219
+ name = 'defaulttrigger'
220
+
221
+ if filters is None:
222
+ filters = dict()
223
+ elif isinstance(filters, entities.Filters):
224
+ filters = filters.prepare(query_only=True).get('filter', dict())
225
+
226
+ if webhook_id is not None:
227
+ operation = {
228
+ 'type': 'webhook',
229
+ 'webhookId': webhook_id
230
+ }
231
+ else:
232
+ operation = {
233
+ 'type': 'function',
234
+ 'serviceId': service_id,
235
+ 'functionName': function_name
236
+
237
+ }
238
+
239
+ if actions is not None:
240
+ if not isinstance(actions, list):
241
+ actions = [actions]
242
+ else:
243
+ actions = [entities.TriggerAction.CREATED]
244
+
245
+ if len(actions) == 0:
246
+ actions = [entities.TriggerAction.CREATED]
247
+
248
+ if trigger_type == entities.TriggerType.EVENT:
249
+ spec = {
250
+ 'filter': filters,
251
+ 'resource': resource,
252
+ 'executionMode': execution_mode,
253
+ 'actions': actions
254
+ }
255
+ elif trigger_type == entities.TriggerType.CRON:
256
+ spec = {
257
+ 'endAt': end_at,
258
+ 'startAt': start_at,
259
+ 'cron': cron,
260
+ }
261
+ else:
262
+ raise ValueError('Unknown trigger type: "{}". Use dl.TriggerType for known types'.format(trigger_type))
263
+
264
+ spec['input'] = dict() if inputs is None else inputs
265
+ spec['operation'] = operation
266
+
267
+ # payload
268
+ if self._project_id is None and project_id is None:
269
+ raise exceptions.PlatformException('400', 'Please provide a project id')
270
+ elif project_id is None:
271
+ project_id = self._project_id
272
+
273
+ payload = {
274
+ 'type': trigger_type,
275
+ 'active': active,
276
+ 'projectId': project_id,
277
+ 'name': name,
278
+ 'spec': spec
279
+ }
280
+
281
+ if scope is not None:
282
+ logger.warning(
283
+ "Only superuser is allowed to define a trigger's scope. "
284
+ "If you are not a superuser you will not be able to perform this action")
285
+ payload['scope'] = scope
286
+
287
+ # request
288
+ success, response = self._client_api.gen_request(req_type='post',
289
+ path='/triggers',
290
+ json_req=payload)
291
+
292
+ # exception handling
293
+ if not success:
294
+ raise exceptions.PlatformException(response)
295
+
296
+ # return entity
297
+ return entities.BaseTrigger.from_json(_json=response.json(),
298
+ client_api=self._client_api,
299
+ project=self._project if self._project_id == project_id else None,
300
+ service=self._service)
301
+
302
+ @_api_reference.add(path='/triggers/{id}', method='get')
303
+ def get(self, trigger_id=None, trigger_name=None) -> entities.BaseTrigger:
304
+ """
305
+ Get Trigger object
306
+
307
+ **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
308
+
309
+ :param str trigger_id: trigger id
310
+ :param str trigger_name: trigger name
311
+ :return: Trigger entity
312
+ :rtype: dtlpy.entities.trigger.Trigger
313
+
314
+ **Example**:
315
+
316
+ .. code-block:: python
317
+
318
+ service.triggers.get(trigger_id='trigger_id')
319
+ """
320
+ # request
321
+ if trigger_id is not None:
322
+ success, response = self._client_api.gen_request(
323
+ req_type="get",
324
+ path="/triggers/{}".format(trigger_id)
325
+ )
326
+
327
+ # exception handling
328
+ if not success:
329
+ raise exceptions.PlatformException(response)
330
+
331
+ # return entity
332
+ trigger = entities.BaseTrigger.from_json(client_api=self._client_api,
333
+ _json=response.json(),
334
+ project=self._project,
335
+ service=self._service)
336
+ # verify input trigger name is same as the given id
337
+ if trigger_name is not None and trigger.name != trigger_name:
338
+ logger.warning(
339
+ "Mismatch found in triggers.get: trigger_name is different then trigger.name:"
340
+ " {!r} != {!r}".format(
341
+ trigger_name,
342
+ trigger.name))
343
+ else:
344
+ if trigger_name is None:
345
+ raise exceptions.PlatformException('400', 'Must provide either trigger name or trigger id')
346
+ else:
347
+ filters = self.__generate_default_filter()
348
+ filters.add(field='name', values=trigger_name)
349
+ triggers = self.list(filters)
350
+ if triggers.items_count == 0:
351
+ raise exceptions.PlatformException('404', 'Trigger not found')
352
+ elif triggers.items_count == 1:
353
+ trigger = triggers.items[0]
354
+ else:
355
+ raise exceptions.PlatformException('404',
356
+ 'More than one trigger by name {} exist'.format(trigger_name))
357
+
358
+ return trigger
359
+
360
+ @_api_reference.add(path='/triggers/{id}', method='delete')
361
+ def delete(self, trigger_id=None, trigger_name=None):
362
+ """
363
+ Delete Trigger object
364
+
365
+ **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
366
+
367
+ :param str trigger_id: trigger id
368
+ :param str trigger_name: trigger name
369
+ :return: True is successful error if not
370
+ :rtype: bool
371
+
372
+ **Example**:
373
+
374
+ .. code-block:: python
375
+
376
+ service.triggers.delete(trigger_id='trigger_id')
377
+ """
378
+ if trigger_id is None:
379
+ if trigger_name is None:
380
+ raise exceptions.PlatformException('400', 'Must provide either trigger name or trigger id')
381
+ else:
382
+ trigger_id = self.get(trigger_name=trigger_name).id
383
+ # request
384
+ success, response = self._client_api.gen_request(
385
+ req_type="delete",
386
+ path="/triggers/{}".format(trigger_id)
387
+ )
388
+ # exception handling
389
+ if not success:
390
+ raise exceptions.PlatformException(response)
391
+ return True
392
+
393
+ @_api_reference.add(path='/triggers/{id}', method='patch')
394
+ def update(self, trigger: entities.BaseTrigger) -> entities.BaseTrigger:
395
+ """
396
+ Update trigger
397
+
398
+ **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
399
+
400
+ :param dtlpy.entities.trigger.Trigger trigger: Trigger entity
401
+ :return: Trigger entity
402
+ :rtype: dtlpy.entities.trigger.Trigger
403
+
404
+ **Example**:
405
+
406
+ .. code-block:: python
407
+
408
+ service.triggers.update(trigger='trigger_entity')
409
+ """
410
+ # payload
411
+ payload = trigger.to_json()
412
+
413
+ # request
414
+ success, response = self._client_api.gen_request(req_type='patch',
415
+ path='/triggers/{}'.format(trigger.id),
416
+ json_req=payload)
417
+
418
+ # exception handling
419
+ if not success:
420
+ raise exceptions.PlatformException(response)
421
+
422
+ # return entity
423
+ return entities.BaseTrigger.from_json(_json=response.json(),
424
+ client_api=self._client_api,
425
+ project=self._project,
426
+ service=self._service)
427
+
428
+ def _build_entities_from_response(self, response_items) -> miscellaneous.List[entities.BaseTrigger]:
429
+ pool = self._client_api.thread_pools(pool_name='entity.create')
430
+ jobs = [None for _ in range(len(response_items))]
431
+ # return triggers list
432
+ for i_trigger, trigger in enumerate(response_items):
433
+ jobs[i_trigger] = pool.submit(entities.BaseTrigger._protected_from_json,
434
+ **{'client_api': self._client_api,
435
+ '_json': trigger,
436
+ 'project': self._project,
437
+ 'service': self._service})
438
+
439
+ # get all results
440
+ results = [j.result() for j in jobs]
441
+ # log errors
442
+ _ = [logger.warning(r[1]) for r in results if r[0] is False]
443
+ # return good jobs
444
+ triggers = miscellaneous.List([r[1] for r in results if r[0] is True])
445
+ return triggers
446
+
447
+ def _list(self, filters: entities.Filters):
448
+ """
449
+ List project triggers
450
+ :return:
451
+ """
452
+ url = '/query/faas'
453
+
454
+ success, response = self._client_api.gen_request(req_type='POST',
455
+ path=url,
456
+ json_req=filters.prepare())
457
+ if not success:
458
+ raise exceptions.PlatformException(response)
459
+ return response.json()
460
+
461
+ def __generate_default_filter(self):
462
+ filters = entities.Filters(resource=entities.FiltersResource.TRIGGER)
463
+ if self._project is not None:
464
+ filters.add(field='projectId', values=self._project.id)
465
+ if self._service is not None:
466
+ filters.add(field='spec.operation.serviceId', values=self._service.id)
467
+ if self._pipeline is not None:
468
+ filters.add(field='spec.operation.id', values=self._pipeline.id)
469
+
470
+ return filters
471
+
472
+ @_api_reference.add(path='/query/faas', method='post')
473
+ def list(self, filters: entities.Filters = None) -> entities.PagedEntities:
474
+ """
475
+ List triggers of a project, package, or service.
476
+
477
+ **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a service.
478
+
479
+ :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
480
+ :return: Paged entity
481
+ :rtype: dtlpy.entities.paged_entities.PagedEntities
482
+
483
+ **Example**:
484
+
485
+ .. code-block:: python
486
+
487
+ service.triggers.list()
488
+ """
489
+ if filters is None:
490
+ filters = self.__generate_default_filter()
491
+ # assert type filters
492
+ elif not isinstance(filters, entities.Filters):
493
+ raise exceptions.PlatformException(error='400',
494
+ message='Unknown filters type: {!r}'.format(type(filters)))
495
+
496
+ if filters.resource != entities.FiltersResource.TRIGGER:
497
+ raise exceptions.PlatformException(
498
+ error='400',
499
+ message='Filters resource must to be FiltersResource.TRIGGER. Got: {!r}'.format(filters.resource))
500
+
501
+ paged = entities.PagedEntities(items_repository=self,
502
+ filters=filters,
503
+ page_offset=filters.page,
504
+ page_size=filters.page_size,
505
+ client_api=self._client_api)
506
+ paged.get_page()
507
+ return paged
508
+
509
+ def resource_information(self, resource, resource_type, action='Created'):
510
+ """
511
+ Returns which function should run on an item (based on global triggers).
512
+
513
+ **Prerequisites**: You must be a **superuser** to run this method.
514
+
515
+ :param resource: 'Item' / 'Dataset' / etc
516
+ :param resource_type: dictionary of the resource object
517
+ :param action: 'Created' / 'Updated' / etc.
518
+
519
+ **Example**:
520
+
521
+ .. code-block:: python
522
+
523
+ service.triggers.resource_information(resource='Item', resource_type=item_object, action='Created')
524
+ """
525
+ url = '/trigger-resource-information'
526
+
527
+ payload = {'resource': resource_type,
528
+ 'entity': resource.to_json(),
529
+ 'action': action}
530
+ # request
531
+ success, response = self._client_api.gen_request(req_type='post',
532
+ path=url,
533
+ json_req=payload)
534
+ if not success:
535
+ raise exceptions.PlatformException(response)
536
+ return response.json()