supervisely 6.73.311__py3-none-any.whl → 6.73.312__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.

Potentially problematic release.


This version of supervisely might be problematic. Click here for more details.

supervisely/__init__.py CHANGED
@@ -311,4 +311,4 @@ except Exception as e:
311
311
  # If new changes in Supervisely Python SDK require upgrade of the Supervisely instance
312
312
  # set a new value for the environment variable MINIMUM_INSTANCE_VERSION_FOR_SDK, otherwise
313
313
  # users can face compatibility issues, if the instance version is lower than the SDK version.
314
- os.environ["MINIMUM_INSTANCE_VERSION_FOR_SDK"] = "6.12.28"
314
+ os.environ["MINIMUM_INSTANCE_VERSION_FOR_SDK"] = "6.12.30"
@@ -3,14 +3,13 @@
3
3
 
4
4
  # docs
5
5
  from __future__ import annotations
6
- from typing import List, Optional, Dict, Union
7
- from supervisely.annotation.tag_meta import TagMeta
8
- from supervisely.annotation.tag_meta_collection import TagMetaCollection
9
6
 
7
+ from typing import Dict, List, Optional, Union
10
8
 
11
- from supervisely.annotation.tag_meta import TagValueType
12
- from supervisely.collection.key_indexed_collection import KeyObject
13
9
  from supervisely._utils import take_with_default
10
+ from supervisely.annotation.tag_meta import TagMeta, TagValueType
11
+ from supervisely.annotation.tag_meta_collection import TagMetaCollection
12
+ from supervisely.collection.key_indexed_collection import KeyObject
14
13
 
15
14
 
16
15
  class TagJsonFields:
@@ -83,6 +82,8 @@ class Tag(KeyObject):
83
82
  # Output: ValueError: Tag coat color can not have value yellow
84
83
  """
85
84
 
85
+ _SUPPORT_UNFINISHED_TAGS = False
86
+
86
87
  def __init__(
87
88
  self,
88
89
  meta: TagMeta,
@@ -97,7 +98,8 @@ class Tag(KeyObject):
97
98
  self._meta = meta
98
99
  self._value = value
99
100
  if not self._meta.is_valid_value(value):
100
- raise ValueError("Tag {} can not have value {}".format(self.meta.name, value))
101
+ if not (self._SUPPORT_UNFINISHED_TAGS and value is None):
102
+ raise ValueError(f"Tag {self.meta.name} can not have value {value}")
101
103
  self.labeler_login = labeler_login
102
104
  self.updated_at = updated_at
103
105
  self.created_at = created_at
@@ -219,9 +221,7 @@ class Tag(KeyObject):
219
221
  # "createdAt": "2021-01-22T18:00:00.000Z"
220
222
  # }
221
223
  """
222
- res = {
223
- TagJsonFields.TAG_NAME: self.meta.name
224
- }
224
+ res = {TagJsonFields.TAG_NAME: self.meta.name}
225
225
  if self.meta.value_type != TagValueType.NONE:
226
226
  res[TagJsonFields.VALUE] = self.value
227
227
  if self.labeler_login is not None:
@@ -621,6 +621,10 @@ class ApiField:
621
621
  """"""
622
622
  EXPERIMENT = "experiment"
623
623
  """"""
624
+ IS_FINISHED = "isFinished"
625
+ """"""
626
+ NON_FINAL_VALUE = "nonFinalValue"
627
+ """"""
624
628
 
625
629
 
626
630
  def _get_single_item(items):
@@ -6,7 +6,9 @@ from typing import List, Optional, Union
6
6
  from supervisely.annotation.tag_meta import TagMeta
7
7
  from supervisely.api.entity_annotation.tag_api import TagApi
8
8
  from supervisely.api.module_api import ApiField
9
+ from supervisely.collection.key_indexed_collection import KeyIndexedCollection
9
10
  from supervisely.project.project_meta import ProjectMeta
11
+ from supervisely.video_annotation.key_id_map import KeyIdMap
10
12
  from supervisely.video_annotation.video_tag import VideoTag
11
13
  from supervisely.video_annotation.video_tag_collection import VideoTagCollection
12
14
 
@@ -102,6 +104,8 @@ class VideoTagApi(TagApi):
102
104
  video_id: int,
103
105
  value: Optional[Union[str, int]] = None,
104
106
  frame_range: Optional[List[int]] = None,
107
+ is_finished: Optional[bool] = True,
108
+ non_final_value: Optional[bool] = False,
105
109
  ) -> int:
106
110
  """
107
111
  Add VideoTag to video.
@@ -114,6 +118,10 @@ class VideoTagApi(TagApi):
114
118
  :type value: str or int
115
119
  :param frame_range: New VideoTag frame range.
116
120
  :type frame_range: List[int]
121
+ :param is_finished: Specify if the tag is finished.
122
+ :type is_finished: bool
123
+ :param non_final_value: Specify if the tag value is non-final.
124
+ :type non_final_value: bool
117
125
  :return: None
118
126
  :rtype: dict
119
127
  :Usage example:
@@ -133,11 +141,17 @@ class VideoTagApi(TagApi):
133
141
  request_data = {ApiField.TAG_ID: project_meta_tag_id, ApiField.VIDEO_ID: video_id}
134
142
  if value:
135
143
  request_data[ApiField.VALUE] = value
144
+ if non_final_value is True:
145
+ is_finished = False
136
146
  if frame_range:
147
+ if is_finished is False and frame_range[0] != frame_range[1]:
148
+ raise ValueError("Start frame and end frame must be equal for unfinished tags")
137
149
  request_data[ApiField.FRAME_RANGE] = frame_range
150
+ request_data[ApiField.IS_FINISHED] = is_finished
151
+ request_data[ApiField.NON_FINAL_VALUE] = non_final_value
138
152
 
139
153
  resp = self._api.post("videos.tags.add", request_data)
140
- # {'imageId': 3267369, 'tagId': 368985, 'id': 2296676, 'createdAt': '2022-09-20T11:52:33.829Z', 'updatedAt': '2022-09-20T11:52:33.829Z', 'labelerLogin': 'max'}
154
+ # {'imageId': 3267369, 'tagId': 368985, 'id': 2296676, 'createdAt': '2022-09-20T11:52:33.829Z', 'updatedAt': '2022-09-20T11:52:33.829Z', 'labelerLogin': 'max', isFinished: true, nonFinalValue: false}
141
155
  return resp.json()
142
156
 
143
157
  def add(self, video_id: int, tag: VideoTag, update_id_inplace=True) -> int:
@@ -186,7 +200,14 @@ class VideoTagApi(TagApi):
186
200
  else:
187
201
  raise ValueError("tag_meta.sly_id is None, get updated project meta from server")
188
202
 
189
- resp_json = self.add_tag(tag.meta.sly_id, video_id, tag.value, tag.frame_range)
203
+ resp_json = self.add_tag(
204
+ tag.meta.sly_id,
205
+ video_id,
206
+ tag.value,
207
+ tag.frame_range,
208
+ tag.is_finished,
209
+ tag.non_final_value,
210
+ )
190
211
  tag_id = resp_json.get("id")
191
212
  created_at = resp_json.get("createdAt")
192
213
  updated_at = resp_json.get("updatedAt")
@@ -275,7 +296,7 @@ class VideoTagApi(TagApi):
275
296
 
276
297
 
277
298
  class VideoObjectTagApi(TagApi):
278
- _entity_id_field = ApiField.OBJECT_ID
299
+ _entity_id_field = ApiField.ENTITY_ID
279
300
  _method_bulk_add = "annotation-objects.tags.bulk.add"
280
301
 
281
302
  def add(
@@ -284,6 +305,8 @@ class VideoObjectTagApi(TagApi):
284
305
  object_id: int,
285
306
  value: Optional[Union[str, int]] = None,
286
307
  frame_range: Optional[List[int]] = None,
308
+ is_finished: Optional[bool] = True,
309
+ non_final_value: Optional[bool] = False,
287
310
  ) -> int:
288
311
  """Add a tag to an annotation object.
289
312
 
@@ -304,8 +327,14 @@ class VideoObjectTagApi(TagApi):
304
327
  }
305
328
  if value is not None:
306
329
  request_body[ApiField.VALUE] = value
330
+ if non_final_value is True:
331
+ is_finished = False
307
332
  if frame_range is not None:
333
+ if is_finished is False and frame_range[0] != frame_range[1]:
334
+ raise ValueError("Start frame and end frame must be equal for unfinished tags")
308
335
  request_body[ApiField.FRAME_RANGE] = frame_range
336
+ request_body[ApiField.IS_FINISHED] = is_finished
337
+ request_body[ApiField.NON_FINAL_VALUE] = non_final_value
309
338
 
310
339
  response = self._api.post("annotation-objects.tags.add", request_body)
311
340
  id = response.json()[ApiField.ID]
@@ -349,3 +378,40 @@ class VideoObjectTagApi(TagApi):
349
378
  ApiField.FRAME_RANGE: frame_range,
350
379
  }
351
380
  self._api.post("annotation-objects.tags.update", request_body)
381
+
382
+ def append_to_entity(
383
+ self,
384
+ entity_id: int,
385
+ project_id: int,
386
+ tags: KeyIndexedCollection,
387
+ object_id: int,
388
+ key_id_map: KeyIdMap = None,
389
+ ):
390
+ """
391
+ Add tags to entity in project with given ID.
392
+
393
+ :param entity_id: ID of the entity in Supervisely to add a tag to
394
+ :type entity_id: int
395
+ :param project_id: Project ID in Supervisely.
396
+ :type project_id: int
397
+ :param tags: Collection of tags
398
+ :type tags: KeyIndexedCollection
399
+ :param object_id: ID of the object in Supervisely to add a tag to
400
+ :type object_id: int, optional
401
+ :param key_id_map: KeyIdMap object.
402
+ :type key_id_map: KeyIdMap, optional
403
+ :return: List of tags IDs
404
+ :rtype: list
405
+ """
406
+
407
+ if len(tags) == 0:
408
+ return []
409
+ tags_json, tags_keys = self._tags_to_json(tags, project_id=project_id)
410
+ tags_to_add = []
411
+ for tag in tags_json:
412
+ if object_id is not None:
413
+ tag[ApiField.OBJECT_ID] = object_id
414
+ tags_to_add.append(tag)
415
+ ids = self._append_json(entity_id, tags_to_add)
416
+ KeyIdMap.add_tags_to(key_id_map, tags_keys, ids)
417
+ return ids
@@ -1,6 +1,9 @@
1
1
  from __future__ import annotations
2
+
2
3
  import uuid
3
- from typing import Optional, Dict, Union, Tuple
4
+ from typing import Dict, Optional, Tuple, Union
5
+
6
+ from supervisely._utils import take_with_default
4
7
  from supervisely.annotation.tag_meta import TagMeta
5
8
  from supervisely.annotation.tag_meta_collection import TagMetaCollection
6
9
  from supervisely.video_annotation.key_id_map import KeyIdMap
@@ -57,6 +60,30 @@ class PointcloudEpisodeTag(VideoTag):
57
60
  # Output: ValueError: Tag car color can not have value yellow
58
61
  """
59
62
 
63
+ _SUPPORT_UNFINISHED_TAGS = False
64
+
65
+ def __init__(
66
+ self,
67
+ meta,
68
+ value=None,
69
+ frame_range=None,
70
+ key=None,
71
+ sly_id=None,
72
+ labeler_login=None,
73
+ updated_at=None,
74
+ created_at=None,
75
+ ):
76
+ super().__init__(
77
+ meta,
78
+ value,
79
+ frame_range,
80
+ key,
81
+ sly_id,
82
+ labeler_login,
83
+ updated_at,
84
+ created_at,
85
+ )
86
+
60
87
  @classmethod
61
88
  def from_json(
62
89
  cls,
@@ -95,7 +122,18 @@ class PointcloudEpisodeTag(VideoTag):
95
122
  tag_car_color = sly.PointcloudEpisodeTag.from_json(tag_car_color_json, meta_car_collection)
96
123
  """
97
124
 
98
- return super().from_json(data, tag_meta_collection, key_id_map=key_id_map)
125
+ temp = super(PointcloudEpisodeTag, cls).from_json(data, tag_meta_collection, key_id_map)
126
+
127
+ return cls(
128
+ meta=temp.meta,
129
+ value=temp.value,
130
+ frame_range=temp.frame_range,
131
+ key=temp.key(),
132
+ sly_id=temp.sly_id,
133
+ labeler_login=temp.labeler_login,
134
+ updated_at=temp.updated_at,
135
+ created_at=temp.created_at,
136
+ )
99
137
 
100
138
  def __eq__(self, other: PointcloudEpisodeTag) -> bool:
101
139
  return super().__eq__(other)
@@ -154,13 +192,13 @@ class PointcloudEpisodeTag(VideoTag):
154
192
  # }
155
193
  """
156
194
 
157
- return super().clone(
158
- meta=meta,
159
- value=value,
160
- frame_range=frame_range,
161
- key=key,
162
- sly_id=sly_id,
163
- labeler_login=labeler_login,
164
- updated_at=updated_at,
165
- created_at=created_at,
195
+ return self.__class__(
196
+ meta=take_with_default(meta, self.meta),
197
+ value=take_with_default(value, self.value),
198
+ frame_range=take_with_default(frame_range, self.frame_range),
199
+ key=take_with_default(key, self.key()),
200
+ sly_id=take_with_default(sly_id, self.sly_id),
201
+ labeler_login=take_with_default(labeler_login, self.labeler_login),
202
+ updated_at=take_with_default(updated_at, self.updated_at),
203
+ created_at=take_with_default(created_at, self.created_at),
166
204
  )
@@ -2,15 +2,17 @@
2
2
 
3
3
  # docs
4
4
  from __future__ import annotations
5
- from typing import List, Tuple, Dict, Optional, Union
6
- from supervisely.annotation.tag_meta_collection import TagMetaCollection
7
- from supervisely.annotation.tag_meta import TagMeta
8
-
9
5
 
10
6
  import uuid
11
- from supervisely.annotation.tag import Tag, TagJsonFields
7
+ from typing import Dict, List, Optional, Tuple, Union
8
+
12
9
  from supervisely._utils import take_with_default
13
- from supervisely.video_annotation.constants import KEY, ID, FRAME_RANGE
10
+ from supervisely.annotation.tag import Tag, TagJsonFields
11
+ from supervisely.annotation.tag_meta import TagMeta, TagTargetType
12
+ from supervisely.annotation.tag_meta_collection import TagMetaCollection
13
+ from supervisely.api.module_api import ApiField
14
+ from supervisely.sly_logger import logger
15
+ from supervisely.video_annotation.constants import FRAME_RANGE, ID, KEY
14
16
  from supervisely.video_annotation.key_id_map import KeyIdMap
15
17
 
16
18
 
@@ -34,6 +36,10 @@ class VideoTag(Tag):
34
36
  :type updated_at: str, optional
35
37
  :param created_at: Date and Time when VideoTag was created. Date Format is the same as in "updated_at" parameter.
36
38
  :type created_at: str, optional
39
+ :param is_finished: Video Tag is finished or not (applicable for range tags).
40
+ :type is_finished: bool, optional
41
+ :param non_final_value: Video Tag value is final or not. Can be useful to create tag without value.
42
+ :type non_final_value: bool, optional
37
43
  :Usage example:
38
44
 
39
45
  .. code-block:: python
@@ -64,22 +70,52 @@ class VideoTag(Tag):
64
70
  tag_coat_color = VideoTag(meta_coat_color, value="yellow")
65
71
  # Output: ValueError: Tag coat color can not have value yellow
66
72
  """
67
- def __init__(self, meta: TagMeta, value: Optional[Union[str, int, float]]=None, frame_range: Optional[Tuple[int, int]]=None,
68
- key: Optional[uuid.UUID]=None, sly_id: Optional[int]=None, labeler_login: Optional[str]=None,
69
- updated_at: Optional[str]=None, created_at: Optional[str]=None):
70
- super(VideoTag, self).__init__(meta, value=value, sly_id=sly_id, labeler_login=labeler_login, updated_at=updated_at, created_at=created_at)
71
-
73
+
74
+ _SUPPORT_UNFINISHED_TAGS = True
75
+
76
+ def __init__(
77
+ self,
78
+ meta: TagMeta,
79
+ value: Optional[Union[str, int, float]] = None,
80
+ frame_range: Optional[Tuple[int, int]] = None,
81
+ key: Optional[uuid.UUID] = None,
82
+ sly_id: Optional[int] = None,
83
+ labeler_login: Optional[str] = None,
84
+ updated_at: Optional[str] = None,
85
+ created_at: Optional[str] = None,
86
+ is_finished: Optional[bool] = None,
87
+ non_final_value: Optional[bool] = None,
88
+ ):
89
+ super(VideoTag, self).__init__(
90
+ meta,
91
+ value=value,
92
+ sly_id=sly_id,
93
+ labeler_login=labeler_login,
94
+ updated_at=updated_at,
95
+ created_at=created_at,
96
+ )
97
+
72
98
  self._frame_range = None
73
99
  if frame_range is not None:
74
- if not isinstance(frame_range, (tuple, list)):
75
- raise TypeError('frame_range has to be a tuple or a list. Given type "{}".'.format(type(frame_range)))
76
-
77
- if len(frame_range) != 2 or not isinstance(frame_range[0], int) or not isinstance(frame_range[1], int):
78
- raise ValueError("frame_range has to be a tuple or a list with 2 int values.")
79
- self._frame_range = list(frame_range)
100
+ self._frame_range = self._validate_frame_range(frame_range)
80
101
 
81
102
  self._key = take_with_default(key, uuid.uuid4())
82
103
 
104
+ self._is_finished = None
105
+ self._non_final_value = None
106
+
107
+ if self._SUPPORT_UNFINISHED_TAGS is True:
108
+ self._is_finished = take_with_default(is_finished, True)
109
+ if self._is_finished is False:
110
+ if self._frame_range is None:
111
+ raise ValueError("Cannot set is_finished=False for a tag without frame range")
112
+ self._frame_range = [self._frame_range[0], self._frame_range[0]]
113
+ if not self.meta.is_valid_value(self.value) and self.value is None:
114
+ non_final_value = True
115
+ self._non_final_value = take_with_default(non_final_value, False)
116
+ if self._non_final_value is True:
117
+ self._is_finished = False
118
+
83
119
  @property
84
120
  def frame_range(self) -> Tuple[int, int]:
85
121
  """
@@ -95,9 +131,53 @@ class VideoTag(Tag):
95
131
  """
96
132
  return self._frame_range
97
133
 
134
+ @property
135
+ def is_finished(self) -> bool:
136
+ """
137
+ VideoTag is finished or not (applicable for range tags).
138
+
139
+ :return: True if VideoTag is finished, otherwise False
140
+ :rtype: :class:`bool`
141
+ :Usage example:
142
+
143
+ .. code-block:: python
144
+
145
+ is_finished = tag_cat.is_finished
146
+ """
147
+ return self._is_finished
148
+
149
+ @property
150
+ def non_final_value(self) -> bool:
151
+ """
152
+ VideoTag value is final or not.
153
+
154
+ :return: True if VideoTag value is final, otherwise False
155
+ :rtype: :class:`bool`
156
+ :Usage example:
157
+
158
+ .. code-block:: python
159
+
160
+ non_final_value = tag_cat.non_final_value
161
+ """
162
+ return self._non_final_value
163
+
98
164
  def key(self) -> uuid.UUID:
99
165
  return self._key
100
166
 
167
+ def _validate_frame_range(self, frame_range: Tuple[int, int]) -> Tuple[int, int]:
168
+ if not isinstance(frame_range, (tuple, list)):
169
+ raise TypeError(
170
+ f'frame_range has to be a tuple or a list. Given type "{type(frame_range)}".'
171
+ )
172
+
173
+ if (
174
+ len(frame_range) != 2
175
+ or not isinstance(frame_range[0], int)
176
+ or not isinstance(frame_range[1], int)
177
+ ):
178
+ raise ValueError("frame_range has to be a tuple or a list with 2 int values.")
179
+ return list(frame_range)
180
+
101
181
  def to_json(self, key_id_map: Optional[KeyIdMap] = None) -> Dict:
102
182
  """
103
183
  Convert the VideoTag to a json dict. Read more about `Supervisely format <https://docs.supervise.ly/data-organization/00_ann_format_navi>`_.
@@ -127,6 +207,11 @@ class VideoTag(Tag):
127
207
  data_json = {TagJsonFields.TAG_NAME: data_json}
128
208
  if self.frame_range is not None:
129
209
  data_json[FRAME_RANGE] = self.frame_range
210
+
211
+ if self.is_finished is not None:
212
+ data_json[ApiField.IS_FINISHED] = self.is_finished
213
+ if self.non_final_value is not None:
214
+ data_json[ApiField.NON_FINAL_VALUE] = self.non_final_value
130
215
  data_json[KEY] = self.key().hex
131
216
 
132
217
  if key_id_map is not None:
@@ -137,7 +222,12 @@ class VideoTag(Tag):
137
222
  return data_json
138
223
 
139
224
  @classmethod
140
- def from_json(cls, data: Dict, tag_meta_collection: TagMetaCollection, key_id_map: Optional[KeyIdMap] = None) -> VideoTag:
225
+ def from_json(
226
+ cls,
227
+ data: Dict,
228
+ tag_meta_collection: TagMetaCollection,
229
+ key_id_map: Optional[KeyIdMap] = None,
230
+ ) -> VideoTag:
141
231
  """
142
232
  Convert a json dict to VideoTag. Read more about `Supervisely format <https://docs.supervise.ly/data-organization/00_ann_format_navi>`_.
143
233
 
@@ -171,13 +261,25 @@ class VideoTag(Tag):
171
261
  """
172
262
  temp = super(VideoTag, cls).from_json(data, tag_meta_collection)
173
263
  frame_range = data.get(FRAME_RANGE, None)
264
+ is_finished = data.get(ApiField.IS_FINISHED, True)
265
+ non_final_value = data.get(ApiField.NON_FINAL_VALUE, False)
174
266
  key = uuid.UUID(data[KEY]) if KEY in data else uuid.uuid4()
175
267
 
176
268
  if key_id_map is not None:
177
269
  key_id_map.add_tag(key, data.get(ID, None))
178
270
 
179
- return cls(meta=temp.meta, value=temp.value, frame_range=frame_range, key=key,
180
- sly_id=temp.sly_id, labeler_login=temp.labeler_login, updated_at=temp.updated_at, created_at=temp.created_at)
271
+ return cls(
272
+ meta=temp.meta,
273
+ value=temp.value,
274
+ frame_range=frame_range,
275
+ key=key,
276
+ sly_id=temp.sly_id,
277
+ labeler_login=temp.labeler_login,
278
+ updated_at=temp.updated_at,
279
+ created_at=temp.created_at,
280
+ is_finished=is_finished,
281
+ non_final_value=non_final_value,
282
+ )
181
283
 
182
284
  def get_compact_str(self) -> str:
183
285
  """
@@ -199,6 +301,10 @@ class VideoTag(Tag):
199
301
  res = super(VideoTag, self).get_compact_str()
200
302
  if self.frame_range is not None:
201
303
  res = "{}[{} - {}]".format(res, self.frame_range[0], self.frame_range[1])
304
+ if self.is_finished is False:
305
+ res += " (unfinished)"
306
+ if self.non_final_value is True:
307
+ res += " (non-final value)"
202
308
  return res
203
309
 
204
310
  def __eq__(self, other: VideoTag) -> bool:
@@ -233,14 +339,33 @@ class VideoTag(Tag):
233
339
  # Compare unidentical Tags
234
340
  print(tag_lemon_1 == tag_cucumber) # False
235
341
  """
236
- return isinstance(other, VideoTag) and \
237
- self.meta == other.meta and \
238
- self.value == other.value and \
239
- self.frame_range == other.frame_range
240
-
241
- def clone(self, meta: Optional[TagMeta] = None, value: Optional[Union[str, int, float]] = None, frame_range: Optional[Tuple[int, int]] = None,
242
- key: Optional[uuid.UUID] = None, sly_id: Optional[int] = None, labeler_login: Optional[str] = None,
243
- updated_at: Optional[str] = None, created_at: Optional[str] = None) -> VideoTag:
342
+ unfinished_tag_comparison = True
343
+ if self._SUPPORT_UNFINISHED_TAGS:
344
+ unfinished_tag_comparison = (
345
+ self.is_finished == other.is_finished
346
+ and self.non_final_value == other.non_final_value
347
+ )
348
+ return (
349
+ isinstance(other, VideoTag)
350
+ and self.meta == other.meta
351
+ and self.value == other.value
352
+ and self.frame_range == other.frame_range
353
+ and unfinished_tag_comparison
354
+ )
355
+
356
+ def clone(
357
+ self,
358
+ meta: Optional[TagMeta] = None,
359
+ value: Optional[Union[str, int, float]] = None,
360
+ frame_range: Optional[Tuple[int, int]] = None,
361
+ key: Optional[uuid.UUID] = None,
362
+ sly_id: Optional[int] = None,
363
+ labeler_login: Optional[str] = None,
364
+ updated_at: Optional[str] = None,
365
+ created_at: Optional[str] = None,
366
+ is_finished: Optional[bool] = None,
367
+ non_final_value: Optional[bool] = None,
368
+ ) -> VideoTag:
244
369
  """
245
370
  Makes a copy of VideoTag with new fields, if fields are given, otherwise it will use fields of the original VideoTag.
246
371
 
@@ -260,6 +385,10 @@ class VideoTag(Tag):
260
385
  :type updated_at: str, optional
261
386
  :param created_at: Date and Time when VideoTag was created. Date Format is the same as in "updated_at" parameter.
262
387
  :type created_at: str, optional
388
+ :param is_finished: Video Tag is finished or not (applicable for range tags).
389
+ :type is_finished: bool, optional
390
+ :param non_final_value: Video Tag value is final or not (applicable for range tags).
391
+ :type non_final_value: bool, optional
263
392
  :Usage example:
264
393
 
265
394
  .. code-block:: python
@@ -292,19 +421,48 @@ class VideoTag(Tag):
292
421
  sly_id=take_with_default(sly_id, self.sly_id),
293
422
  labeler_login=take_with_default(labeler_login, self.labeler_login),
294
423
  updated_at=take_with_default(updated_at, self.updated_at),
295
- created_at=take_with_default(created_at, self.created_at)
424
+ created_at=take_with_default(created_at, self.created_at),
425
+ is_finished=take_with_default(is_finished, self.is_finished),
426
+ non_final_value=take_with_default(non_final_value, self.non_final_value),
296
427
  )
297
428
 
298
429
  def __str__(self):
299
430
  # pylint: disable=too-many-format-args
300
- return '{:<7s}{:<10}{:<7s} {:<13}{:<7s} {:<10} {:<12}'.format('Name:', self._meta.name,
301
- 'Value type:', self._meta.value_type,
302
- 'Value:', str(self.value),
303
- 'FrameRange', str(self.frame_range))
431
+ s = "{:<7s}{:<10}{:<7s} {:<13}{:<7s} {:<10} {:<12}".format(
432
+ "Name:",
433
+ self._meta.name,
434
+ "Value type:",
435
+ self._meta.value_type,
436
+ "Value:",
437
+ str(self.value),
438
+ "FrameRange",
439
+ str(self.frame_range),
440
+ )
441
+ if self._SUPPORT_UNFINISHED_TAGS:
442
+ s += "{:<7s} {:<10} {:<12}".format(
443
+ "Is finished:",
444
+ str(self.is_finished),
445
+ "Non final value:",
446
+ str(self.non_final_value),
447
+ )
448
+
449
+ return s
304
450
 
305
451
  @classmethod
306
452
  def get_header_ptable(cls) -> List[str]:
307
- return ['Name', 'Value type', 'Value', 'Frame range']
453
+ header = ["Name", "Value type", "Value", "Frame range"]
454
+ if cls._SUPPORT_UNFINISHED_TAGS:
455
+ header += ["Is finished", "Non final value"]
456
+ return header
308
457
 
309
458
  def get_row_ptable(self) -> List[str]:
310
- return [self._meta.name, self._meta.value_type, self.value, self.frame_range]
459
+ row = [
460
+ self._meta.name,
461
+ self._meta.value_type,
462
+ self.value,
463
+ self.frame_range,
464
+ ]
465
+ if self._SUPPORT_UNFINISHED_TAGS:
466
+ row += [self.is_finished, self.non_final_value]
467
+
468
+ return row
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.311
3
+ Version: 6.73.312
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -1,5 +1,5 @@
1
1
  supervisely/README.md,sha256=XM-DiMC6To3I9RjQZ0c61905EFRR_jnCUx2q3uNR-X8,3331
2
- supervisely/__init__.py,sha256=NCOkCKvZ1qqcgIRuEcd-uFkzC0g4MaUdlulPSHqUbu0,10833
2
+ supervisely/__init__.py,sha256=mtgVKiRSlnRU7yKG0Re130mBL10wCzsNfOfi-w-Kj4c,10833
3
3
  supervisely/_utils.py,sha256=DX_2n8zWTG2AzW8bCvU9z9joLzcwzVjLmvslVF39pE8,16022
4
4
  supervisely/function_wrapper.py,sha256=R5YajTQ0GnRp2vtjwfC9hINkzQc0JiyGsu8TER373xY,1912
5
5
  supervisely/sly_logger.py,sha256=LG1wTyyctyEKuCuKM2IKf_SMPH7BzkTsFdO-0tnorzg,6225
@@ -13,7 +13,7 @@ supervisely/annotation/obj_class.py,sha256=iXUygOqB12ezxX0qA-sk4FmT6HIogUai_VUKY
13
13
  supervisely/annotation/obj_class_collection.py,sha256=1LzozlTAXaoiFsO9f1krh5RHNMafbYxfdo80l4b4730,12410
14
14
  supervisely/annotation/obj_class_mapper.py,sha256=aIJDoRULqcAOD2a1CQPk2OOF8k3VPPSJQZdBAj71VQc,943
15
15
  supervisely/annotation/renamer.py,sha256=rVvNLtpfd1kKUVPgm8VlLmYSDByWjriJ92FobC4buqY,1944
16
- supervisely/annotation/tag.py,sha256=m_sPgrr_ZW8HuiK7Fr2-WnHwKwez1WZtGrcdZN2DZuQ,17598
16
+ supervisely/annotation/tag.py,sha256=iBHI0s52TiSvuGKL2p-mkd1Jpkmx4d7tTy9QZ7Ta9Hk,17635
17
17
  supervisely/annotation/tag_collection.py,sha256=MVPTzer9rLpD4O0g2XhYFUheK7-ILgwAXDJd1em3kZ8,10015
18
18
  supervisely/annotation/tag_meta.py,sha256=nTRKVuW_h6mGdTxuwXvtR2ERhwOvjjdUf635ONLFFx8,27767
19
19
  supervisely/annotation/tag_meta_collection.py,sha256=JY2wAo4dF47UylYeglkJtRtpVOArGjf3dXeEYIHFWP0,14491
@@ -32,7 +32,7 @@ supervisely/api/image_api.py,sha256=WIML_6N1qgOWBm3acexmGSWz4hAaSxlYmUtbytROaP8,
32
32
  supervisely/api/import_storage_api.py,sha256=BDCgmR0Hv6OoiRHLCVPKt3iDxSVlQp1WrnKhAK_Zl84,460
33
33
  supervisely/api/issues_api.py,sha256=BqDJXmNoTzwc3xe6_-mA7FDFC5QQ-ahGbXk_HmpkSeQ,17925
34
34
  supervisely/api/labeling_job_api.py,sha256=odnzZjp29yM16Gq-FYkv-OA4WFMNJCLFo4qSikW2A7c,56280
35
- supervisely/api/module_api.py,sha256=06YJ-LsDDEAIZTnoexqcUilgT3VBDw-I0b4h_bQnCO0,44422
35
+ supervisely/api/module_api.py,sha256=NkDU9gZ0hAHFVnbF26fOOx56QGizyQO23E2kMjKrBWM,44513
36
36
  supervisely/api/neural_network_api.py,sha256=ktPVRO4Jeulougio8F0mioJJHwRJcX250Djp1wBoQ9c,7620
37
37
  supervisely/api/object_class_api.py,sha256=-rQcKwhBw3iL9KNH9c1ROgoimgWM1ls6Wi_tb1R-MzY,7683
38
38
  supervisely/api/plugin_api.py,sha256=TlfrosdRuYG4NUxk92QiQoVaOdztFspPpygyVa3M3zk,5283
@@ -68,7 +68,7 @@ supervisely/api/video/video_api.py,sha256=vnzAUBBfYyegB-kFeenBlkWsUT4w2U7qgnayA9
68
68
  supervisely/api/video/video_figure_api.py,sha256=quksohjhgrK2l2-PtbbNE99fOW6uWXX59-_4xfc-I-k,6244
69
69
  supervisely/api/video/video_frame_api.py,sha256=4GwSI4xdCNYEUvTqzKc-Ewd44fw5zqkFoD24jrrN_aY,10214
70
70
  supervisely/api/video/video_object_api.py,sha256=IC0NP8EoIT_d3xxDRgz2cA3ixSiuJ5ymy64eS-RfmDM,2227
71
- supervisely/api/video/video_tag_api.py,sha256=oJgdJt_0w-5UfXaxZ7jdxK0PetZjax1vOfjm0IMYwe8,12266
71
+ supervisely/api/video/video_tag_api.py,sha256=wPe1HeJyg9kV1z2UJq6BEte5sKBoPJ2UGAHpGivis9c,14911
72
72
  supervisely/api/volume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
73
  supervisely/api/volume/volume_annotation_api.py,sha256=q1nzSeMBndxCTPf-3apliXvqcOaOjYWohSO5CZDHITQ,22243
74
74
  supervisely/api/volume/volume_api.py,sha256=-n3r5qj4I4EtoERKTHFT8PpsKFJ141SvQfamIcHqWK4,55387
@@ -999,7 +999,7 @@ supervisely/pointcloud_annotation/pointcloud_episode_frame.py,sha256=rXQqsCWPvtE
999
999
  supervisely/pointcloud_annotation/pointcloud_episode_frame_collection.py,sha256=GHTL96LEjmTofbVSrl3GWRck1tLkw7aodFzWcnd0oo0,16100
1000
1000
  supervisely/pointcloud_annotation/pointcloud_episode_object.py,sha256=kkjLwxm6clLTFMmXXyM8n-k58Jyzmf3buJsEWyRK2Pg,2221
1001
1001
  supervisely/pointcloud_annotation/pointcloud_episode_object_collection.py,sha256=5KsyVqaLFoWQ1wdyEZkUB1XiWhrXM5P7zPIuzQlHcxk,2693
1002
- supervisely/pointcloud_annotation/pointcloud_episode_tag.py,sha256=a9AFH3KP-0iLAICnvxBEDHnVEc6DCRIibO8TUqhAQG8,7877
1002
+ supervisely/pointcloud_annotation/pointcloud_episode_tag.py,sha256=e2qSFMqSmWBXIS0i8fd8suofyq3-n-sMOUFqqZ2Ezx4,8997
1003
1003
  supervisely/pointcloud_annotation/pointcloud_episode_tag_collection.py,sha256=c9ddhUZhn-mv5wfe9-Ma8k-OeW75DfltSHcbAtGGF1o,10352
1004
1004
  supervisely/pointcloud_annotation/pointcloud_figure.py,sha256=-rJqLIruVDvM1ncKxlmu1gmjP5eUHarThTB3d3F9GQc,11191
1005
1005
  supervisely/pointcloud_annotation/pointcloud_object.py,sha256=7SB_t-kLxY_dwxbVbjfGqB-n_vLKhkhGJV9Epgq-fa4,5652
@@ -1047,7 +1047,7 @@ supervisely/video_annotation/video_annotation.py,sha256=syqfhIerzhMWNh8scM_kWskB
1047
1047
  supervisely/video_annotation/video_figure.py,sha256=j1ZoDnMLO_bFRUI19GDK3A2CzTWGr5pGYbd3NjC7ztE,23766
1048
1048
  supervisely/video_annotation/video_object.py,sha256=i-oiliNpDr2X4Wcy9DJ7sBbuVUT3QYiSrtklCCJGVsY,16736
1049
1049
  supervisely/video_annotation/video_object_collection.py,sha256=Epu9MAC9uZiThfBn4NxKbQ7JRbW4eFZHglTzaJJ9WUQ,9047
1050
- supervisely/video_annotation/video_tag.py,sha256=3mnBJelkrjKtEoTU1vw8kzCSTL8YT9iBCKBg3FjpWF8,13916
1050
+ supervisely/video_annotation/video_tag.py,sha256=a1mdzRoq1GLJl7GxyHNGkX1PEGvudlVoqCDn0MxxAEQ,18306
1051
1051
  supervisely/video_annotation/video_tag_collection.py,sha256=lr9dz616SKtbzpY2bWsvFL-ZSzHCsjLvXDccYsQRs_k,13474
1052
1052
  supervisely/volume/__init__.py,sha256=EBZBY_5mzabXzMUQh5akusIGd16XnX9n8J0jIi_JmWw,446
1053
1053
  supervisely/volume/nrrd_encoder.py,sha256=1lqwwyqxEvctw1ysQ70x4xPSV1uy1g5YcH5CURwL7-c,4084
@@ -1075,9 +1075,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
1075
1075
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
1076
1076
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
1077
1077
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1078
- supervisely-6.73.311.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1079
- supervisely-6.73.311.dist-info/METADATA,sha256=UBLsxrd4D6kvEBOA4q_NYAUxbReS-fGip95b_7nRPzE,33596
1080
- supervisely-6.73.311.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1081
- supervisely-6.73.311.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1082
- supervisely-6.73.311.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1083
- supervisely-6.73.311.dist-info/RECORD,,
1078
+ supervisely-6.73.312.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1079
+ supervisely-6.73.312.dist-info/METADATA,sha256=PPqHYBNXFQ0EUVs242nEG-VAEBDVk7pwq033pSKWZ68,33596
1080
+ supervisely-6.73.312.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1081
+ supervisely-6.73.312.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1082
+ supervisely-6.73.312.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1083
+ supervisely-6.73.312.dist-info/RECORD,,