dtlpy 1.114.17__py3-none-any.whl → 1.116.6__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 (238) hide show
  1. dtlpy/__init__.py +491 -491
  2. dtlpy/__version__.py +1 -1
  3. dtlpy/assets/__init__.py +26 -26
  4. dtlpy/assets/code_server/config.yaml +2 -2
  5. dtlpy/assets/code_server/installation.sh +24 -24
  6. dtlpy/assets/code_server/launch.json +13 -13
  7. dtlpy/assets/code_server/settings.json +2 -2
  8. dtlpy/assets/main.py +53 -53
  9. dtlpy/assets/main_partial.py +18 -18
  10. dtlpy/assets/mock.json +11 -11
  11. dtlpy/assets/model_adapter.py +83 -83
  12. dtlpy/assets/package.json +61 -61
  13. dtlpy/assets/package_catalog.json +29 -29
  14. dtlpy/assets/package_gitignore +307 -307
  15. dtlpy/assets/service_runners/__init__.py +33 -33
  16. dtlpy/assets/service_runners/converter.py +96 -96
  17. dtlpy/assets/service_runners/multi_method.py +49 -49
  18. dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
  19. dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
  20. dtlpy/assets/service_runners/multi_method_item.py +52 -52
  21. dtlpy/assets/service_runners/multi_method_json.py +52 -52
  22. dtlpy/assets/service_runners/single_method.py +37 -37
  23. dtlpy/assets/service_runners/single_method_annotation.py +43 -43
  24. dtlpy/assets/service_runners/single_method_dataset.py +43 -43
  25. dtlpy/assets/service_runners/single_method_item.py +41 -41
  26. dtlpy/assets/service_runners/single_method_json.py +42 -42
  27. dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
  28. dtlpy/assets/voc_annotation_template.xml +23 -23
  29. dtlpy/caches/base_cache.py +32 -32
  30. dtlpy/caches/cache.py +473 -473
  31. dtlpy/caches/dl_cache.py +201 -201
  32. dtlpy/caches/filesystem_cache.py +89 -89
  33. dtlpy/caches/redis_cache.py +84 -84
  34. dtlpy/dlp/__init__.py +20 -20
  35. dtlpy/dlp/cli_utilities.py +367 -367
  36. dtlpy/dlp/command_executor.py +764 -764
  37. dtlpy/dlp/dlp +1 -1
  38. dtlpy/dlp/dlp.bat +1 -1
  39. dtlpy/dlp/dlp.py +128 -128
  40. dtlpy/dlp/parser.py +651 -651
  41. dtlpy/entities/__init__.py +83 -83
  42. dtlpy/entities/analytic.py +347 -311
  43. dtlpy/entities/annotation.py +1879 -1879
  44. dtlpy/entities/annotation_collection.py +699 -699
  45. dtlpy/entities/annotation_definitions/__init__.py +20 -20
  46. dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
  47. dtlpy/entities/annotation_definitions/box.py +195 -195
  48. dtlpy/entities/annotation_definitions/classification.py +67 -67
  49. dtlpy/entities/annotation_definitions/comparison.py +72 -72
  50. dtlpy/entities/annotation_definitions/cube.py +204 -204
  51. dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
  52. dtlpy/entities/annotation_definitions/description.py +32 -32
  53. dtlpy/entities/annotation_definitions/ellipse.py +124 -124
  54. dtlpy/entities/annotation_definitions/free_text.py +62 -62
  55. dtlpy/entities/annotation_definitions/gis.py +69 -69
  56. dtlpy/entities/annotation_definitions/note.py +139 -139
  57. dtlpy/entities/annotation_definitions/point.py +117 -117
  58. dtlpy/entities/annotation_definitions/polygon.py +182 -182
  59. dtlpy/entities/annotation_definitions/polyline.py +111 -111
  60. dtlpy/entities/annotation_definitions/pose.py +92 -92
  61. dtlpy/entities/annotation_definitions/ref_image.py +86 -86
  62. dtlpy/entities/annotation_definitions/segmentation.py +240 -240
  63. dtlpy/entities/annotation_definitions/subtitle.py +34 -34
  64. dtlpy/entities/annotation_definitions/text.py +85 -85
  65. dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
  66. dtlpy/entities/app.py +220 -220
  67. dtlpy/entities/app_module.py +107 -107
  68. dtlpy/entities/artifact.py +174 -174
  69. dtlpy/entities/assignment.py +399 -399
  70. dtlpy/entities/base_entity.py +214 -214
  71. dtlpy/entities/bot.py +113 -113
  72. dtlpy/entities/codebase.py +292 -296
  73. dtlpy/entities/collection.py +38 -38
  74. dtlpy/entities/command.py +169 -169
  75. dtlpy/entities/compute.py +449 -442
  76. dtlpy/entities/dataset.py +1299 -1285
  77. dtlpy/entities/directory_tree.py +44 -44
  78. dtlpy/entities/dpk.py +470 -470
  79. dtlpy/entities/driver.py +235 -223
  80. dtlpy/entities/execution.py +397 -397
  81. dtlpy/entities/feature.py +124 -124
  82. dtlpy/entities/feature_set.py +145 -145
  83. dtlpy/entities/filters.py +798 -645
  84. dtlpy/entities/gis_item.py +107 -107
  85. dtlpy/entities/integration.py +184 -184
  86. dtlpy/entities/item.py +959 -953
  87. dtlpy/entities/label.py +123 -123
  88. dtlpy/entities/links.py +85 -85
  89. dtlpy/entities/message.py +175 -175
  90. dtlpy/entities/model.py +684 -684
  91. dtlpy/entities/node.py +1005 -1005
  92. dtlpy/entities/ontology.py +810 -803
  93. dtlpy/entities/organization.py +287 -287
  94. dtlpy/entities/package.py +657 -657
  95. dtlpy/entities/package_defaults.py +5 -5
  96. dtlpy/entities/package_function.py +185 -185
  97. dtlpy/entities/package_module.py +113 -113
  98. dtlpy/entities/package_slot.py +118 -118
  99. dtlpy/entities/paged_entities.py +299 -299
  100. dtlpy/entities/pipeline.py +624 -624
  101. dtlpy/entities/pipeline_execution.py +279 -279
  102. dtlpy/entities/project.py +394 -394
  103. dtlpy/entities/prompt_item.py +505 -499
  104. dtlpy/entities/recipe.py +301 -301
  105. dtlpy/entities/reflect_dict.py +102 -102
  106. dtlpy/entities/resource_execution.py +138 -138
  107. dtlpy/entities/service.py +963 -958
  108. dtlpy/entities/service_driver.py +117 -117
  109. dtlpy/entities/setting.py +294 -294
  110. dtlpy/entities/task.py +495 -495
  111. dtlpy/entities/time_series.py +143 -143
  112. dtlpy/entities/trigger.py +426 -426
  113. dtlpy/entities/user.py +118 -118
  114. dtlpy/entities/webhook.py +124 -124
  115. dtlpy/examples/__init__.py +19 -19
  116. dtlpy/examples/add_labels.py +135 -135
  117. dtlpy/examples/add_metadata_to_item.py +21 -21
  118. dtlpy/examples/annotate_items_using_model.py +65 -65
  119. dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
  120. dtlpy/examples/annotations_convert_to_voc.py +9 -9
  121. dtlpy/examples/annotations_convert_to_yolo.py +9 -9
  122. dtlpy/examples/convert_annotation_types.py +51 -51
  123. dtlpy/examples/converter.py +143 -143
  124. dtlpy/examples/copy_annotations.py +22 -22
  125. dtlpy/examples/copy_folder.py +31 -31
  126. dtlpy/examples/create_annotations.py +51 -51
  127. dtlpy/examples/create_video_annotations.py +83 -83
  128. dtlpy/examples/delete_annotations.py +26 -26
  129. dtlpy/examples/filters.py +113 -113
  130. dtlpy/examples/move_item.py +23 -23
  131. dtlpy/examples/play_video_annotation.py +13 -13
  132. dtlpy/examples/show_item_and_mask.py +53 -53
  133. dtlpy/examples/triggers.py +49 -49
  134. dtlpy/examples/upload_batch_of_items.py +20 -20
  135. dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
  136. dtlpy/examples/upload_items_with_modalities.py +43 -43
  137. dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
  138. dtlpy/examples/upload_yolo_format_annotations.py +70 -70
  139. dtlpy/exceptions.py +125 -125
  140. dtlpy/miscellaneous/__init__.py +20 -20
  141. dtlpy/miscellaneous/dict_differ.py +95 -95
  142. dtlpy/miscellaneous/git_utils.py +217 -217
  143. dtlpy/miscellaneous/json_utils.py +14 -14
  144. dtlpy/miscellaneous/list_print.py +105 -105
  145. dtlpy/miscellaneous/zipping.py +130 -130
  146. dtlpy/ml/__init__.py +20 -20
  147. dtlpy/ml/base_feature_extractor_adapter.py +27 -27
  148. dtlpy/ml/base_model_adapter.py +1257 -1086
  149. dtlpy/ml/metrics.py +461 -461
  150. dtlpy/ml/predictions_utils.py +274 -274
  151. dtlpy/ml/summary_writer.py +57 -57
  152. dtlpy/ml/train_utils.py +60 -60
  153. dtlpy/new_instance.py +252 -252
  154. dtlpy/repositories/__init__.py +56 -56
  155. dtlpy/repositories/analytics.py +85 -85
  156. dtlpy/repositories/annotations.py +916 -916
  157. dtlpy/repositories/apps.py +383 -383
  158. dtlpy/repositories/artifacts.py +452 -452
  159. dtlpy/repositories/assignments.py +599 -599
  160. dtlpy/repositories/bots.py +213 -213
  161. dtlpy/repositories/codebases.py +559 -559
  162. dtlpy/repositories/collections.py +332 -332
  163. dtlpy/repositories/commands.py +152 -158
  164. dtlpy/repositories/compositions.py +61 -61
  165. dtlpy/repositories/computes.py +439 -435
  166. dtlpy/repositories/datasets.py +1504 -1291
  167. dtlpy/repositories/downloader.py +976 -903
  168. dtlpy/repositories/dpks.py +433 -433
  169. dtlpy/repositories/drivers.py +482 -470
  170. dtlpy/repositories/executions.py +815 -817
  171. dtlpy/repositories/feature_sets.py +226 -226
  172. dtlpy/repositories/features.py +255 -238
  173. dtlpy/repositories/integrations.py +484 -484
  174. dtlpy/repositories/items.py +912 -909
  175. dtlpy/repositories/messages.py +94 -94
  176. dtlpy/repositories/models.py +1000 -988
  177. dtlpy/repositories/nodes.py +80 -80
  178. dtlpy/repositories/ontologies.py +511 -511
  179. dtlpy/repositories/organizations.py +525 -525
  180. dtlpy/repositories/packages.py +1941 -1941
  181. dtlpy/repositories/pipeline_executions.py +451 -451
  182. dtlpy/repositories/pipelines.py +640 -640
  183. dtlpy/repositories/projects.py +539 -539
  184. dtlpy/repositories/recipes.py +419 -399
  185. dtlpy/repositories/resource_executions.py +137 -137
  186. dtlpy/repositories/schema.py +120 -120
  187. dtlpy/repositories/service_drivers.py +213 -213
  188. dtlpy/repositories/services.py +1704 -1704
  189. dtlpy/repositories/settings.py +339 -339
  190. dtlpy/repositories/tasks.py +1477 -1477
  191. dtlpy/repositories/times_series.py +278 -278
  192. dtlpy/repositories/triggers.py +536 -536
  193. dtlpy/repositories/upload_element.py +257 -257
  194. dtlpy/repositories/uploader.py +661 -651
  195. dtlpy/repositories/webhooks.py +249 -249
  196. dtlpy/services/__init__.py +22 -22
  197. dtlpy/services/aihttp_retry.py +131 -131
  198. dtlpy/services/api_client.py +1785 -1782
  199. dtlpy/services/api_reference.py +40 -40
  200. dtlpy/services/async_utils.py +133 -133
  201. dtlpy/services/calls_counter.py +44 -44
  202. dtlpy/services/check_sdk.py +68 -68
  203. dtlpy/services/cookie.py +115 -115
  204. dtlpy/services/create_logger.py +156 -156
  205. dtlpy/services/events.py +84 -84
  206. dtlpy/services/logins.py +235 -235
  207. dtlpy/services/reporter.py +256 -256
  208. dtlpy/services/service_defaults.py +91 -91
  209. dtlpy/utilities/__init__.py +20 -20
  210. dtlpy/utilities/annotations/__init__.py +16 -16
  211. dtlpy/utilities/annotations/annotation_converters.py +269 -269
  212. dtlpy/utilities/base_package_runner.py +285 -264
  213. dtlpy/utilities/converter.py +1650 -1650
  214. dtlpy/utilities/dataset_generators/__init__.py +1 -1
  215. dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
  216. dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
  217. dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
  218. dtlpy/utilities/local_development/__init__.py +1 -1
  219. dtlpy/utilities/local_development/local_session.py +179 -179
  220. dtlpy/utilities/reports/__init__.py +2 -2
  221. dtlpy/utilities/reports/figures.py +343 -343
  222. dtlpy/utilities/reports/report.py +71 -71
  223. dtlpy/utilities/videos/__init__.py +17 -17
  224. dtlpy/utilities/videos/video_player.py +598 -598
  225. dtlpy/utilities/videos/videos.py +470 -470
  226. {dtlpy-1.114.17.data → dtlpy-1.116.6.data}/scripts/dlp +1 -1
  227. dtlpy-1.116.6.data/scripts/dlp.bat +2 -0
  228. {dtlpy-1.114.17.data → dtlpy-1.116.6.data}/scripts/dlp.py +128 -128
  229. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/METADATA +186 -183
  230. dtlpy-1.116.6.dist-info/RECORD +239 -0
  231. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/WHEEL +1 -1
  232. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/licenses/LICENSE +200 -200
  233. tests/features/environment.py +551 -551
  234. dtlpy/assets/__pycache__/__init__.cpython-310.pyc +0 -0
  235. dtlpy-1.114.17.data/scripts/dlp.bat +0 -2
  236. dtlpy-1.114.17.dist-info/RECORD +0 -240
  237. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/entry_points.txt +0 -0
  238. {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/top_level.txt +0 -0
dtlpy/entities/task.py CHANGED
@@ -1,495 +1,495 @@
1
- import traceback
2
- from enum import Enum
3
- from typing import Union, List
4
- import attr
5
- import logging
6
-
7
- from .. import repositories, entities, exceptions
8
-
9
- logger = logging.getLogger(name='dtlpy')
10
-
11
-
12
- class AllocationMethod(str, Enum):
13
- DISTRIBUTION = 'distribution'
14
- PULLING = 'pulling'
15
-
16
- class ConsensusTaskType(str, Enum):
17
- CONSENSUS = 'consensus'
18
- QUALIFICATION = 'qualification'
19
- HONEYPOT = 'honeypot'
20
-
21
- class TaskPriority(int, Enum):
22
- LOW = 1
23
- MEDIUM = 2
24
- HIGH = 3
25
-
26
-
27
- class ItemAction:
28
- def __init__(self, action, display_name=None, color='#FFFFFF', icon=None):
29
- if not action or not isinstance(action, str):
30
- raise ValueError('action should be a non-empty string')
31
- self.action = action
32
- if not display_name:
33
- display_name = action
34
- self.display_name = display_name
35
- self.color = color
36
- self.icon = icon
37
-
38
- @classmethod
39
- def from_json(cls, _json: dict):
40
- kwarg = {
41
- 'action': _json.get('action')
42
- }
43
-
44
- if _json.get('displayName', False):
45
- kwarg['display_name'] = _json['displayName']
46
-
47
- if _json.get('color', False):
48
- kwarg['color'] = _json['color']
49
-
50
- if _json.get('icon', False):
51
- kwarg['icon'] = _json['icon']
52
-
53
- return cls(**kwarg)
54
-
55
- def to_json(self) -> dict:
56
- _json = {
57
- 'action': self.action,
58
- 'color': self.color,
59
- 'displayName': self.display_name if self.display_name is not None else self.action
60
- }
61
-
62
- if self.icon is not None:
63
- _json['icon'] = self.icon
64
-
65
- return _json
66
-
67
-
68
- @attr.s
69
- class Task:
70
- """
71
- Task object
72
- """
73
-
74
- # platform
75
- name = attr.ib()
76
- status = attr.ib()
77
- project_id = attr.ib()
78
- metadata = attr.ib(repr=False)
79
- id = attr.ib()
80
- url = attr.ib(repr=False)
81
- task_owner = attr.ib(repr=False)
82
- item_status = attr.ib(repr=False)
83
- creator = attr.ib()
84
- due_date = attr.ib()
85
- dataset_id = attr.ib()
86
- spec = attr.ib()
87
- recipe_id = attr.ib(repr=False)
88
- query = attr.ib(repr=False)
89
- assignmentIds = attr.ib(repr=False)
90
- annotation_status = attr.ib(repr=False)
91
- progress = attr.ib()
92
- for_review = attr.ib()
93
- issues = attr.ib()
94
- updated_at = attr.ib()
95
- created_at = attr.ib()
96
- available_actions = attr.ib()
97
- total_items = attr.ib()
98
- priority = attr.ib()
99
- _description = attr.ib()
100
-
101
- # sdk
102
- _client_api = attr.ib(repr=False)
103
- _current_assignments = attr.ib(default=None, repr=False)
104
- _assignments = attr.ib(default=None, repr=False)
105
- _project = attr.ib(default=None, repr=False)
106
- _dataset = attr.ib(default=None, repr=False)
107
- _tasks = attr.ib(default=None, repr=False)
108
- _settings = attr.ib(default=None, repr=False)
109
-
110
- @property
111
- def description(self):
112
- return self._description
113
-
114
- @description.setter
115
- def description(self, description):
116
- if not isinstance(description, str):
117
- raise ValueError('description should be a string')
118
- if self._description is None:
119
- self._description = {}
120
- self._description['content'] = description
121
-
122
- @staticmethod
123
- def _protected_from_json(_json, client_api, project=None, dataset=None):
124
- """
125
- Same as from_json but with try-except to catch if error
126
-
127
- :param dict _json: platform json that describe the task
128
- :param client_api: ApiClient object
129
- :param dtlpy.entities.project.Project project: project object where task will create
130
- :param dtlpy.entities.dataset.Dataset dataset: dataset object that refer to the task
131
- :return:
132
- """
133
- try:
134
- task = Task.from_json(
135
- _json=_json,
136
- client_api=client_api,
137
- project=project,
138
- dataset=dataset
139
- )
140
- status = True
141
- except Exception:
142
- task = traceback.format_exc()
143
- status = False
144
- return status, task
145
-
146
- @classmethod
147
- def from_json(cls, _json, client_api, project=None, dataset=None):
148
- """
149
- Return the task object form the json
150
-
151
- :param dict _json: platform json that describe the task
152
- :param client_api: ApiClient object
153
- :param dtlpy.entities.project.Project project: project object where task will create
154
- :param dtlpy.entities.dataset.Dataset dataset: dataset object that refer to the task
155
- :return:
156
- """
157
- if project is not None:
158
- if project.id != _json.get('projectId', None):
159
- logger.warning('Task has been fetched from a project that is not belong to it')
160
- project = None
161
-
162
- if dataset is not None:
163
- if dataset.id != _json.get('datasetId', None):
164
- logger.warning('Task has been fetched from a dataset that is not belong to it')
165
- dataset = None
166
-
167
- actions = [ItemAction.from_json(_json=action) for action in _json.get('availableActions', list())]
168
-
169
- return cls(
170
- name=_json.get('name', None),
171
- status=_json.get('status', None),
172
- project_id=_json.get('projectId', None),
173
- metadata=_json.get('metadata', dict()),
174
- url=_json.get('url', None),
175
- spec=_json.get('spec', None),
176
- id=_json['id'],
177
- creator=_json.get('creator', None),
178
- due_date=_json.get('dueDate', 0),
179
- dataset_id=_json.get('datasetId', None),
180
- recipe_id=_json.get('recipeId', None),
181
- query=_json.get('query', None),
182
- task_owner=_json.get('taskOwner', None),
183
- item_status=_json.get('itemStatus', None),
184
- assignmentIds=_json.get('assignmentIds', list()),
185
- dataset=dataset,
186
- project=project,
187
- client_api=client_api,
188
- annotation_status=_json.get('annotationStatus', None),
189
- progress=_json.get('progress', None),
190
- for_review=_json.get('forReview', None),
191
- issues=_json.get('issues', None),
192
- updated_at=_json.get('updatedAt', None),
193
- created_at=_json.get('createdAt', None),
194
- available_actions=actions,
195
- total_items=_json.get('totalItems', None),
196
- priority=_json.get('priority', None),
197
- description=_json.get('description', None)
198
- )
199
-
200
- def to_json(self):
201
- """
202
- Returns platform _json format of object
203
-
204
- :return: platform json format of object
205
- :rtype: dict
206
- """
207
- _json = attr.asdict(
208
- self, filter=attr.filters.exclude(
209
- attr.fields(Task)._client_api,
210
- attr.fields(Task)._project,
211
- attr.fields(Task).project_id,
212
- attr.fields(Task).dataset_id,
213
- attr.fields(Task).recipe_id,
214
- attr.fields(Task).task_owner,
215
- attr.fields(Task).available_actions,
216
- attr.fields(Task).item_status,
217
- attr.fields(Task).due_date,
218
- attr.fields(Task)._tasks,
219
- attr.fields(Task)._dataset,
220
- attr.fields(Task)._current_assignments,
221
- attr.fields(Task)._assignments,
222
- attr.fields(Task).annotation_status,
223
- attr.fields(Task).for_review,
224
- attr.fields(Task).issues,
225
- attr.fields(Task).updated_at,
226
- attr.fields(Task).created_at,
227
- attr.fields(Task).total_items,
228
- attr.fields(Task)._settings,
229
- attr.fields(Task)._description
230
- )
231
- )
232
- _json['projectId'] = self.project_id
233
- _json['datasetId'] = self.dataset_id
234
- _json['recipeId'] = self.recipe_id
235
- _json['taskOwner'] = self.task_owner
236
- _json['dueDate'] = self.due_date
237
- _json['totalItems'] = self.total_items
238
- _json['forReview'] = self.for_review
239
- _json['description'] = self.description
240
-
241
- if self.available_actions is not None:
242
- _json['availableActions'] = [action.to_json() for action in self.available_actions]
243
-
244
- return _json
245
-
246
- @property
247
- def platform_url(self):
248
- return self._client_api._get_resource_url("projects/{}/tasks/{}".format(self.project.id, self.id))
249
-
250
- @property
251
- def current_assignments(self):
252
- if self._current_assignments is None:
253
- self._current_assignments = list()
254
- for assignment in self.assignmentIds:
255
- self._current_assignments.append(self.assignments.get(assignment_id=assignment))
256
- return self._current_assignments
257
-
258
- @property
259
- def assignments(self):
260
- if self._assignments is None:
261
- self._assignments = repositories.Assignments(client_api=self._client_api, dataset=self._dataset,
262
- project=self.project, task=self, project_id=self.project_id)
263
- assert isinstance(self._assignments, repositories.Assignments)
264
- return self._assignments
265
-
266
- @property
267
- def tasks(self):
268
- if self._tasks is None:
269
- self._tasks = repositories.Tasks(client_api=self._client_api, project=self.project, dataset=self.dataset)
270
- assert isinstance(self._tasks, repositories.Tasks)
271
- return self._tasks
272
-
273
- @property
274
- def settings(self):
275
- if self._settings is None:
276
- self._settings = repositories.Settings(
277
- client_api=self._client_api,
278
- project=self.project,
279
- dataset=self.dataset,
280
- task=self
281
- )
282
- assert isinstance(self._settings, repositories.Settings)
283
- return self._settings
284
-
285
- @property
286
- def project(self):
287
- if self._project is None:
288
- self.get_project()
289
- if self._project is None:
290
- raise exceptions.PlatformException(error='2001',
291
- message='Missing entity "project". need to "get_project()" ')
292
- assert isinstance(self._project, entities.Project)
293
- return self._project
294
-
295
- @property
296
- def dataset(self):
297
- if self._dataset is None:
298
- self.get_dataset()
299
- if self._dataset is None:
300
- raise exceptions.PlatformException(error='2001',
301
- message='Missing entity "dataset". need to "get_dataset()" ')
302
- assert isinstance(self._dataset, entities.Dataset)
303
- return self._dataset
304
-
305
- def get_project(self):
306
- if self._project is None:
307
- self._project = repositories.Projects(client_api=self._client_api).get(project_id=self.project_id)
308
-
309
- def get_dataset(self):
310
- if self._dataset is None:
311
- self._dataset = repositories.Datasets(client_api=self._client_api, project=self._project).get(
312
- dataset_id=self.dataset_id)
313
-
314
- def open_in_web(self):
315
- """
316
- Open the task in web platform
317
-
318
- :return:
319
- """
320
- self._client_api._open_in_web(url=self.platform_url)
321
-
322
- def delete(self, wait=True):
323
- """
324
- Delete task from platform
325
-
326
- :param bool wait: wait until delete task finish
327
- :return: True
328
- :rtype: bool
329
- """
330
- return self.tasks.delete(task_id=self.id, wait=wait)
331
-
332
- def update(self, system_metadata=False):
333
- """
334
- Update an Annotation Task
335
-
336
- :param bool system_metadata: DEPRECATED
337
- """
338
- return self.tasks.update(task=self, system_metadata=system_metadata)
339
-
340
- def create_qa_task(self,
341
- due_date,
342
- assignee_ids,
343
- filters=None,
344
- items=None,
345
- query=None,
346
- workload=None,
347
- metadata=None,
348
- available_actions=None,
349
- wait=True,
350
- batch_size=None,
351
- max_batch_workload=None,
352
- allowed_assignees=None,
353
- priority=TaskPriority.MEDIUM
354
- ):
355
- """
356
- Create a new QA Task
357
-
358
- :param float due_date: date by which the QA task should be finished; for example, due_date=datetime.datetime(day=1, month=1, year=2029).timestamp()
359
- :param list assignee_ids: list the QA task assignees (contributors) that should be working on the task. Provide a list of users' emails
360
- :param entities.Filters filters: dl.Filters entity to filter items for the task
361
- :param List[entities.Item] items: list of items (item Id or objects) to insert to the task
362
- :param dict DQL query: filter items for the task
363
- :param List[WorkloadUnit] workload: list of WorkloadUnit objects. Customize distribution (percentage) between the task assignees. For example: [dl.WorkloadUnit(annotator@hi.com, 80), dl.WorkloadUnit(annotator2@hi.com, 20)]
364
- :param dict metadata: metadata for the task
365
- :param list available_actions: list of available actions (statuses) that will be available for the task items; The default statuses are: "approved" and "discard"
366
- :param bool wait: wait until create task finish
367
- :param int batch_size: Pulling batch size (items), use with pulling allocation method. Restrictions - Min 3, max 100
368
- :param int max_batch_workload: Max items in assignment, use with pulling allocation method. Restrictions - Min batchSize + 2, max batchSize * 2
369
- :param list allowed_assignees: list the task assignees (contributors) that should be working on the task. Provide a list of users' emails
370
- :param entities.TaskPriority priority: priority of the task options in entities.TaskPriority
371
- :return: task object
372
- :rtype: dtlpy.entities.task.Task
373
-
374
- **Example**:
375
-
376
- .. code-block:: python
377
-
378
- task = task.create_qa_task(due_date = datetime.datetime(day= 1, month= 1, year= 2029).timestamp(),
379
- assignee_ids =[ 'annotator1@dataloop.ai', 'annotator2@dataloop.ai'])
380
- """
381
- return self.tasks.create_qa_task(task=self,
382
- due_date=due_date,
383
- assignee_ids=assignee_ids,
384
- filters=filters,
385
- items=items,
386
- query=query,
387
- workload=workload,
388
- metadata=metadata,
389
- available_actions=available_actions,
390
- wait=wait,
391
- batch_size=batch_size,
392
- max_batch_workload=max_batch_workload,
393
- allowed_assignees=allowed_assignees,
394
- priority=priority
395
- )
396
-
397
- def create_assignment(self, assignment_name, assignee_id, items=None, filters=None):
398
- """
399
- Create a new assignment
400
-
401
- :param str assignment_name: assignment name
402
- :param str assignee_id: the assignment assignees (contributors) that should be working on the task. Provide a user email
403
- :param List[entities.Item] items: list of items (item Id or objects) to insert to the task
404
- :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
405
- :return: Assignment object
406
- :rtype: dtlpy.entities.assignment.Assignment assignment
407
-
408
- **Example**:
409
-
410
- .. code-block:: python
411
-
412
- assignment = task.create_assignment(assignee_id='annotator1@dataloop.ai')
413
- """
414
- assignment = self.assignments.create(assignee_id=assignee_id,
415
- filters=filters,
416
- items=items)
417
-
418
- assignment.metadata['system']['taskId'] = self.id
419
- assignment.update(system_metadata=True)
420
- self.assignmentIds.append(assignment.id)
421
- self.update()
422
- self.add_items(filters=filters, items=items)
423
- return assignment
424
-
425
- def add_items(self, filters=None, items=None, assignee_ids=None, workload=None, limit=None, wait=True, query=None):
426
- """
427
- Add items to Task
428
-
429
- :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
430
- :param list items: list of items (item Ids or objects) to add to the task
431
- :param list assignee_ids: list to assignee who works in the task
432
- :param list workload: list of WorkloadUnit objects. Customize distribution (percentage) between the task assignees. For example: [dl.WorkloadUnit(annotator@hi.com, 80), dl.WorkloadUnit(annotator2@hi.com, 20)]
433
- :param int limit: the limit items that task can include
434
- :param bool wait: wait until add items will to finish
435
- :param dict query: query to filter the items for the task
436
-
437
- :return: task entity
438
- :rtype: dtlpy.entities.task.Task
439
- """
440
- return self.tasks.add_items(task=self,
441
- filters=filters,
442
- items=items,
443
- assignee_ids=assignee_ids,
444
- workload=workload,
445
- limit=limit,
446
- wait=wait,
447
- query=query)
448
-
449
- def remove_items(self,
450
- filters: entities.Filters = None,
451
- query=None,
452
- items=None,
453
- wait=True):
454
- """
455
- remove items from Task.
456
-
457
- **Prerequisites**: You must be in the role of an *owner*, *developer*, or *annotation manager* who has been assigned to be *owner* of the annotation task.
458
-
459
- :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
460
- :param dict query: query to filter the items use it
461
- :param list items: list of items to add to the task
462
- :param bool wait: wait until remove items finish
463
-
464
- :return: True if success and an error if failed
465
- :rtype: bool
466
- """
467
- return self.tasks.remove_items(task=self,
468
- query=query,
469
- filters=filters,
470
- items=items,
471
- wait=wait)
472
-
473
- def get_items(self, filters=None, get_consensus_items: bool = False):
474
- """
475
- Get the task items
476
-
477
- :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
478
- :return: list of the items or PagedEntity output of items
479
- :rtype: list or dtlpy.entities.paged_entities.PagedEntities
480
- """
481
- return self.tasks.get_items(task_id=self.id, dataset=self.dataset, filters=filters, get_consensus_items=get_consensus_items)
482
-
483
- def set_status(self, status: str, operation: str, item_ids: List[str]):
484
- """
485
- Update item status within task
486
-
487
- :param str status: string the describes the status
488
- :param str operation: the status action need 'create' or 'delete'
489
- :param list item_ids: List[str] id items ids
490
-
491
- :return: True if success
492
- :rtype: bool
493
- """
494
- return self.tasks.set_status(status=status, operation=operation, item_ids=item_ids, task_id=self.id)
495
-
1
+ import traceback
2
+ from enum import Enum
3
+ from typing import Union, List
4
+ import attr
5
+ import logging
6
+
7
+ from .. import repositories, entities, exceptions
8
+
9
+ logger = logging.getLogger(name='dtlpy')
10
+
11
+
12
+ class AllocationMethod(str, Enum):
13
+ DISTRIBUTION = 'distribution'
14
+ PULLING = 'pulling'
15
+
16
+ class ConsensusTaskType(str, Enum):
17
+ CONSENSUS = 'consensus'
18
+ QUALIFICATION = 'qualification'
19
+ HONEYPOT = 'honeypot'
20
+
21
+ class TaskPriority(int, Enum):
22
+ LOW = 1
23
+ MEDIUM = 2
24
+ HIGH = 3
25
+
26
+
27
+ class ItemAction:
28
+ def __init__(self, action, display_name=None, color='#FFFFFF', icon=None):
29
+ if not action or not isinstance(action, str):
30
+ raise ValueError('action should be a non-empty string')
31
+ self.action = action
32
+ if not display_name:
33
+ display_name = action
34
+ self.display_name = display_name
35
+ self.color = color
36
+ self.icon = icon
37
+
38
+ @classmethod
39
+ def from_json(cls, _json: dict):
40
+ kwarg = {
41
+ 'action': _json.get('action')
42
+ }
43
+
44
+ if _json.get('displayName', False):
45
+ kwarg['display_name'] = _json['displayName']
46
+
47
+ if _json.get('color', False):
48
+ kwarg['color'] = _json['color']
49
+
50
+ if _json.get('icon', False):
51
+ kwarg['icon'] = _json['icon']
52
+
53
+ return cls(**kwarg)
54
+
55
+ def to_json(self) -> dict:
56
+ _json = {
57
+ 'action': self.action,
58
+ 'color': self.color,
59
+ 'displayName': self.display_name if self.display_name is not None else self.action
60
+ }
61
+
62
+ if self.icon is not None:
63
+ _json['icon'] = self.icon
64
+
65
+ return _json
66
+
67
+
68
+ @attr.s
69
+ class Task:
70
+ """
71
+ Task object
72
+ """
73
+
74
+ # platform
75
+ name = attr.ib()
76
+ status = attr.ib()
77
+ project_id = attr.ib()
78
+ metadata = attr.ib(repr=False)
79
+ id = attr.ib()
80
+ url = attr.ib(repr=False)
81
+ task_owner = attr.ib(repr=False)
82
+ item_status = attr.ib(repr=False)
83
+ creator = attr.ib()
84
+ due_date = attr.ib()
85
+ dataset_id = attr.ib()
86
+ spec = attr.ib()
87
+ recipe_id = attr.ib(repr=False)
88
+ query = attr.ib(repr=False)
89
+ assignmentIds = attr.ib(repr=False)
90
+ annotation_status = attr.ib(repr=False)
91
+ progress = attr.ib()
92
+ for_review = attr.ib()
93
+ issues = attr.ib()
94
+ updated_at = attr.ib()
95
+ created_at = attr.ib()
96
+ available_actions = attr.ib()
97
+ total_items = attr.ib()
98
+ priority = attr.ib()
99
+ _description = attr.ib()
100
+
101
+ # sdk
102
+ _client_api = attr.ib(repr=False)
103
+ _current_assignments = attr.ib(default=None, repr=False)
104
+ _assignments = attr.ib(default=None, repr=False)
105
+ _project = attr.ib(default=None, repr=False)
106
+ _dataset = attr.ib(default=None, repr=False)
107
+ _tasks = attr.ib(default=None, repr=False)
108
+ _settings = attr.ib(default=None, repr=False)
109
+
110
+ @property
111
+ def description(self):
112
+ return self._description
113
+
114
+ @description.setter
115
+ def description(self, description):
116
+ if not isinstance(description, str):
117
+ raise ValueError('description should be a string')
118
+ if self._description is None:
119
+ self._description = {}
120
+ self._description['content'] = description
121
+
122
+ @staticmethod
123
+ def _protected_from_json(_json, client_api, project=None, dataset=None):
124
+ """
125
+ Same as from_json but with try-except to catch if error
126
+
127
+ :param dict _json: platform json that describe the task
128
+ :param client_api: ApiClient object
129
+ :param dtlpy.entities.project.Project project: project object where task will create
130
+ :param dtlpy.entities.dataset.Dataset dataset: dataset object that refer to the task
131
+ :return:
132
+ """
133
+ try:
134
+ task = Task.from_json(
135
+ _json=_json,
136
+ client_api=client_api,
137
+ project=project,
138
+ dataset=dataset
139
+ )
140
+ status = True
141
+ except Exception:
142
+ task = traceback.format_exc()
143
+ status = False
144
+ return status, task
145
+
146
+ @classmethod
147
+ def from_json(cls, _json, client_api, project=None, dataset=None):
148
+ """
149
+ Return the task object form the json
150
+
151
+ :param dict _json: platform json that describe the task
152
+ :param client_api: ApiClient object
153
+ :param dtlpy.entities.project.Project project: project object where task will create
154
+ :param dtlpy.entities.dataset.Dataset dataset: dataset object that refer to the task
155
+ :return:
156
+ """
157
+ if project is not None:
158
+ if project.id != _json.get('projectId', None):
159
+ logger.warning('Task has been fetched from a project that is not belong to it')
160
+ project = None
161
+
162
+ if dataset is not None:
163
+ if dataset.id != _json.get('datasetId', None):
164
+ logger.warning('Task has been fetched from a dataset that is not belong to it')
165
+ dataset = None
166
+
167
+ actions = [ItemAction.from_json(_json=action) for action in _json.get('availableActions', list())]
168
+
169
+ return cls(
170
+ name=_json.get('name', None),
171
+ status=_json.get('status', None),
172
+ project_id=_json.get('projectId', None),
173
+ metadata=_json.get('metadata', dict()),
174
+ url=_json.get('url', None),
175
+ spec=_json.get('spec', None),
176
+ id=_json['id'],
177
+ creator=_json.get('creator', None),
178
+ due_date=_json.get('dueDate', 0),
179
+ dataset_id=_json.get('datasetId', None),
180
+ recipe_id=_json.get('recipeId', None),
181
+ query=_json.get('query', None),
182
+ task_owner=_json.get('taskOwner', None),
183
+ item_status=_json.get('itemStatus', None),
184
+ assignmentIds=_json.get('assignmentIds', list()),
185
+ dataset=dataset,
186
+ project=project,
187
+ client_api=client_api,
188
+ annotation_status=_json.get('annotationStatus', None),
189
+ progress=_json.get('progress', None),
190
+ for_review=_json.get('forReview', None),
191
+ issues=_json.get('issues', None),
192
+ updated_at=_json.get('updatedAt', None),
193
+ created_at=_json.get('createdAt', None),
194
+ available_actions=actions,
195
+ total_items=_json.get('totalItems', None),
196
+ priority=_json.get('priority', None),
197
+ description=_json.get('description', None)
198
+ )
199
+
200
+ def to_json(self):
201
+ """
202
+ Returns platform _json format of object
203
+
204
+ :return: platform json format of object
205
+ :rtype: dict
206
+ """
207
+ _json = attr.asdict(
208
+ self, filter=attr.filters.exclude(
209
+ attr.fields(Task)._client_api,
210
+ attr.fields(Task)._project,
211
+ attr.fields(Task).project_id,
212
+ attr.fields(Task).dataset_id,
213
+ attr.fields(Task).recipe_id,
214
+ attr.fields(Task).task_owner,
215
+ attr.fields(Task).available_actions,
216
+ attr.fields(Task).item_status,
217
+ attr.fields(Task).due_date,
218
+ attr.fields(Task)._tasks,
219
+ attr.fields(Task)._dataset,
220
+ attr.fields(Task)._current_assignments,
221
+ attr.fields(Task)._assignments,
222
+ attr.fields(Task).annotation_status,
223
+ attr.fields(Task).for_review,
224
+ attr.fields(Task).issues,
225
+ attr.fields(Task).updated_at,
226
+ attr.fields(Task).created_at,
227
+ attr.fields(Task).total_items,
228
+ attr.fields(Task)._settings,
229
+ attr.fields(Task)._description
230
+ )
231
+ )
232
+ _json['projectId'] = self.project_id
233
+ _json['datasetId'] = self.dataset_id
234
+ _json['recipeId'] = self.recipe_id
235
+ _json['taskOwner'] = self.task_owner
236
+ _json['dueDate'] = self.due_date
237
+ _json['totalItems'] = self.total_items
238
+ _json['forReview'] = self.for_review
239
+ _json['description'] = self.description
240
+
241
+ if self.available_actions is not None:
242
+ _json['availableActions'] = [action.to_json() for action in self.available_actions]
243
+
244
+ return _json
245
+
246
+ @property
247
+ def platform_url(self):
248
+ return self._client_api._get_resource_url("projects/{}/tasks/{}".format(self.project.id, self.id))
249
+
250
+ @property
251
+ def current_assignments(self):
252
+ if self._current_assignments is None:
253
+ self._current_assignments = list()
254
+ for assignment in self.assignmentIds:
255
+ self._current_assignments.append(self.assignments.get(assignment_id=assignment))
256
+ return self._current_assignments
257
+
258
+ @property
259
+ def assignments(self):
260
+ if self._assignments is None:
261
+ self._assignments = repositories.Assignments(client_api=self._client_api, dataset=self._dataset,
262
+ project=self.project, task=self, project_id=self.project_id)
263
+ assert isinstance(self._assignments, repositories.Assignments)
264
+ return self._assignments
265
+
266
+ @property
267
+ def tasks(self):
268
+ if self._tasks is None:
269
+ self._tasks = repositories.Tasks(client_api=self._client_api, project=self.project, dataset=self.dataset)
270
+ assert isinstance(self._tasks, repositories.Tasks)
271
+ return self._tasks
272
+
273
+ @property
274
+ def settings(self):
275
+ if self._settings is None:
276
+ self._settings = repositories.Settings(
277
+ client_api=self._client_api,
278
+ project=self.project,
279
+ dataset=self.dataset,
280
+ task=self
281
+ )
282
+ assert isinstance(self._settings, repositories.Settings)
283
+ return self._settings
284
+
285
+ @property
286
+ def project(self):
287
+ if self._project is None:
288
+ self.get_project()
289
+ if self._project is None:
290
+ raise exceptions.PlatformException(error='2001',
291
+ message='Missing entity "project". need to "get_project()" ')
292
+ assert isinstance(self._project, entities.Project)
293
+ return self._project
294
+
295
+ @property
296
+ def dataset(self):
297
+ if self._dataset is None:
298
+ self.get_dataset()
299
+ if self._dataset is None:
300
+ raise exceptions.PlatformException(error='2001',
301
+ message='Missing entity "dataset". need to "get_dataset()" ')
302
+ assert isinstance(self._dataset, entities.Dataset)
303
+ return self._dataset
304
+
305
+ def get_project(self):
306
+ if self._project is None:
307
+ self._project = repositories.Projects(client_api=self._client_api).get(project_id=self.project_id)
308
+
309
+ def get_dataset(self):
310
+ if self._dataset is None:
311
+ self._dataset = repositories.Datasets(client_api=self._client_api, project=self._project).get(
312
+ dataset_id=self.dataset_id)
313
+
314
+ def open_in_web(self):
315
+ """
316
+ Open the task in web platform
317
+
318
+ :return:
319
+ """
320
+ self._client_api._open_in_web(url=self.platform_url)
321
+
322
+ def delete(self, wait=True):
323
+ """
324
+ Delete task from platform
325
+
326
+ :param bool wait: wait until delete task finish
327
+ :return: True
328
+ :rtype: bool
329
+ """
330
+ return self.tasks.delete(task_id=self.id, wait=wait)
331
+
332
+ def update(self, system_metadata=False):
333
+ """
334
+ Update an Annotation Task
335
+
336
+ :param bool system_metadata: DEPRECATED
337
+ """
338
+ return self.tasks.update(task=self, system_metadata=system_metadata)
339
+
340
+ def create_qa_task(self,
341
+ due_date,
342
+ assignee_ids,
343
+ filters=None,
344
+ items=None,
345
+ query=None,
346
+ workload=None,
347
+ metadata=None,
348
+ available_actions=None,
349
+ wait=True,
350
+ batch_size=None,
351
+ max_batch_workload=None,
352
+ allowed_assignees=None,
353
+ priority=TaskPriority.MEDIUM
354
+ ):
355
+ """
356
+ Create a new QA Task
357
+
358
+ :param float due_date: date by which the QA task should be finished; for example, due_date=datetime.datetime(day=1, month=1, year=2029).timestamp()
359
+ :param list assignee_ids: list the QA task assignees (contributors) that should be working on the task. Provide a list of users' emails
360
+ :param entities.Filters filters: dl.Filters entity to filter items for the task
361
+ :param List[entities.Item] items: list of items (item Id or objects) to insert to the task
362
+ :param dict DQL query: filter items for the task
363
+ :param List[WorkloadUnit] workload: list of WorkloadUnit objects. Customize distribution (percentage) between the task assignees. For example: [dl.WorkloadUnit(annotator@hi.com, 80), dl.WorkloadUnit(annotator2@hi.com, 20)]
364
+ :param dict metadata: metadata for the task
365
+ :param list available_actions: list of available actions (statuses) that will be available for the task items; The default statuses are: "approved" and "discard"
366
+ :param bool wait: wait until create task finish
367
+ :param int batch_size: Pulling batch size (items), use with pulling allocation method. Restrictions - Min 3, max 100
368
+ :param int max_batch_workload: Max items in assignment, use with pulling allocation method. Restrictions - Min batchSize + 2, max batchSize * 2
369
+ :param list allowed_assignees: list the task assignees (contributors) that should be working on the task. Provide a list of users' emails
370
+ :param entities.TaskPriority priority: priority of the task options in entities.TaskPriority
371
+ :return: task object
372
+ :rtype: dtlpy.entities.task.Task
373
+
374
+ **Example**:
375
+
376
+ .. code-block:: python
377
+
378
+ task = task.create_qa_task(due_date = datetime.datetime(day= 1, month= 1, year= 2029).timestamp(),
379
+ assignee_ids =[ 'annotator1@dataloop.ai', 'annotator2@dataloop.ai'])
380
+ """
381
+ return self.tasks.create_qa_task(task=self,
382
+ due_date=due_date,
383
+ assignee_ids=assignee_ids,
384
+ filters=filters,
385
+ items=items,
386
+ query=query,
387
+ workload=workload,
388
+ metadata=metadata,
389
+ available_actions=available_actions,
390
+ wait=wait,
391
+ batch_size=batch_size,
392
+ max_batch_workload=max_batch_workload,
393
+ allowed_assignees=allowed_assignees,
394
+ priority=priority
395
+ )
396
+
397
+ def create_assignment(self, assignment_name, assignee_id, items=None, filters=None):
398
+ """
399
+ Create a new assignment
400
+
401
+ :param str assignment_name: assignment name
402
+ :param str assignee_id: the assignment assignees (contributors) that should be working on the task. Provide a user email
403
+ :param List[entities.Item] items: list of items (item Id or objects) to insert to the task
404
+ :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
405
+ :return: Assignment object
406
+ :rtype: dtlpy.entities.assignment.Assignment assignment
407
+
408
+ **Example**:
409
+
410
+ .. code-block:: python
411
+
412
+ assignment = task.create_assignment(assignee_id='annotator1@dataloop.ai')
413
+ """
414
+ assignment = self.assignments.create(assignee_id=assignee_id,
415
+ filters=filters,
416
+ items=items)
417
+
418
+ assignment.metadata['system']['taskId'] = self.id
419
+ assignment.update(system_metadata=True)
420
+ self.assignmentIds.append(assignment.id)
421
+ self.update()
422
+ self.add_items(filters=filters, items=items)
423
+ return assignment
424
+
425
+ def add_items(self, filters=None, items=None, assignee_ids=None, workload=None, limit=None, wait=True, query=None):
426
+ """
427
+ Add items to Task
428
+
429
+ :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
430
+ :param list items: list of items (item Ids or objects) to add to the task
431
+ :param list assignee_ids: list to assignee who works in the task
432
+ :param list workload: list of WorkloadUnit objects. Customize distribution (percentage) between the task assignees. For example: [dl.WorkloadUnit(annotator@hi.com, 80), dl.WorkloadUnit(annotator2@hi.com, 20)]
433
+ :param int limit: the limit items that task can include
434
+ :param bool wait: wait until add items will to finish
435
+ :param dict query: query to filter the items for the task
436
+
437
+ :return: task entity
438
+ :rtype: dtlpy.entities.task.Task
439
+ """
440
+ return self.tasks.add_items(task=self,
441
+ filters=filters,
442
+ items=items,
443
+ assignee_ids=assignee_ids,
444
+ workload=workload,
445
+ limit=limit,
446
+ wait=wait,
447
+ query=query)
448
+
449
+ def remove_items(self,
450
+ filters: entities.Filters = None,
451
+ query=None,
452
+ items=None,
453
+ wait=True):
454
+ """
455
+ remove items from Task.
456
+
457
+ **Prerequisites**: You must be in the role of an *owner*, *developer*, or *annotation manager* who has been assigned to be *owner* of the annotation task.
458
+
459
+ :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
460
+ :param dict query: query to filter the items use it
461
+ :param list items: list of items to add to the task
462
+ :param bool wait: wait until remove items finish
463
+
464
+ :return: True if success and an error if failed
465
+ :rtype: bool
466
+ """
467
+ return self.tasks.remove_items(task=self,
468
+ query=query,
469
+ filters=filters,
470
+ items=items,
471
+ wait=wait)
472
+
473
+ def get_items(self, filters=None, get_consensus_items: bool = False):
474
+ """
475
+ Get the task items
476
+
477
+ :param dtlpy.entities.filters.Filters filters: Filters entity or a dictionary containing filters parameters
478
+ :return: list of the items or PagedEntity output of items
479
+ :rtype: list or dtlpy.entities.paged_entities.PagedEntities
480
+ """
481
+ return self.tasks.get_items(task_id=self.id, dataset=self.dataset, filters=filters, get_consensus_items=get_consensus_items)
482
+
483
+ def set_status(self, status: str, operation: str, item_ids: List[str]):
484
+ """
485
+ Update item status within task
486
+
487
+ :param str status: string the describes the status
488
+ :param str operation: the status action need 'create' or 'delete'
489
+ :param list item_ids: List[str] id items ids
490
+
491
+ :return: True if success
492
+ :rtype: bool
493
+ """
494
+ return self.tasks.set_status(status=status, operation=operation, item_ids=item_ids, task_id=self.id)
495
+