label-studio-sdk 1.0.0__py3-none-any.whl → 1.0.2__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 (99) hide show
  1. label_studio_sdk/__init__.py +46 -4
  2. label_studio_sdk/_extensions/pager_ext.py +49 -0
  3. label_studio_sdk/_legacy/schema/label_config_schema.json +14 -14
  4. label_studio_sdk/actions/__init__.py +27 -0
  5. label_studio_sdk/actions/client.py +129 -8
  6. label_studio_sdk/actions/types/__init__.py +27 -0
  7. label_studio_sdk/actions/types/actions_create_request_filters.py +43 -0
  8. label_studio_sdk/actions/types/actions_create_request_filters_conjunction.py +5 -0
  9. label_studio_sdk/actions/types/actions_create_request_filters_items_item.py +50 -0
  10. label_studio_sdk/actions/types/actions_create_request_filters_items_item_filter.py +31 -0
  11. label_studio_sdk/actions/types/actions_create_request_filters_items_item_operator.py +23 -0
  12. label_studio_sdk/actions/types/actions_create_request_filters_items_item_value.py +5 -0
  13. label_studio_sdk/actions/types/actions_create_request_id.py +19 -0
  14. label_studio_sdk/actions/types/actions_create_request_ordering_item.py +31 -0
  15. label_studio_sdk/actions/types/actions_create_request_selected_items.py +10 -0
  16. label_studio_sdk/actions/types/actions_create_request_selected_items_excluded.py +39 -0
  17. label_studio_sdk/actions/types/actions_create_request_selected_items_included.py +39 -0
  18. label_studio_sdk/base_client.py +183 -0
  19. label_studio_sdk/client.py +17 -175
  20. label_studio_sdk/core/client_wrapper.py +1 -1
  21. label_studio_sdk/core/http_client.py +5 -1
  22. label_studio_sdk/errors/bad_request_error.py +3 -1
  23. label_studio_sdk/export_storage/azure/client.py +176 -10
  24. label_studio_sdk/export_storage/azure/types/azure_create_response.py +15 -0
  25. label_studio_sdk/export_storage/azure/types/azure_update_response.py +15 -0
  26. label_studio_sdk/export_storage/gcs/client.py +180 -14
  27. label_studio_sdk/export_storage/gcs/types/gcs_create_response.py +16 -1
  28. label_studio_sdk/export_storage/gcs/types/gcs_update_response.py +16 -1
  29. label_studio_sdk/export_storage/local/client.py +168 -22
  30. label_studio_sdk/export_storage/local/types/local_create_response.py +12 -2
  31. label_studio_sdk/export_storage/local/types/local_update_response.py +12 -2
  32. label_studio_sdk/export_storage/redis/client.py +234 -30
  33. label_studio_sdk/export_storage/redis/types/redis_create_response.py +20 -5
  34. label_studio_sdk/export_storage/redis/types/redis_update_response.py +20 -5
  35. label_studio_sdk/export_storage/s3/client.py +214 -26
  36. label_studio_sdk/export_storage/s3/types/s3create_response.py +15 -0
  37. label_studio_sdk/export_storage/s3/types/s3update_response.py +15 -0
  38. label_studio_sdk/import_storage/azure/client.py +266 -90
  39. label_studio_sdk/import_storage/azure/types/azure_create_response.py +28 -18
  40. label_studio_sdk/import_storage/azure/types/azure_update_response.py +28 -18
  41. label_studio_sdk/import_storage/gcs/client.py +270 -94
  42. label_studio_sdk/import_storage/gcs/types/gcs_create_response.py +28 -18
  43. label_studio_sdk/import_storage/gcs/types/gcs_update_response.py +28 -18
  44. label_studio_sdk/import_storage/local/client.py +168 -22
  45. label_studio_sdk/import_storage/local/types/local_create_response.py +12 -2
  46. label_studio_sdk/import_storage/local/types/local_update_response.py +12 -2
  47. label_studio_sdk/import_storage/redis/client.py +206 -50
  48. label_studio_sdk/import_storage/redis/types/redis_create_response.py +20 -10
  49. label_studio_sdk/import_storage/redis/types/redis_update_response.py +20 -10
  50. label_studio_sdk/import_storage/s3/client.py +336 -110
  51. label_studio_sdk/import_storage/s3/types/s3create_response.py +35 -25
  52. label_studio_sdk/import_storage/s3/types/s3update_response.py +35 -25
  53. label_studio_sdk/{_legacy/label_interface → label_interface}/base.py +10 -0
  54. label_studio_sdk/{_legacy/label_interface → label_interface}/control_tags.py +109 -71
  55. label_studio_sdk/{_legacy/label_interface → label_interface}/interface.py +97 -51
  56. label_studio_sdk/{_legacy/label_interface → label_interface}/object_tags.py +8 -13
  57. label_studio_sdk/label_interface/objects.py +60 -0
  58. label_studio_sdk/label_interface/region.py +75 -0
  59. label_studio_sdk/projects/client.py +6 -4
  60. label_studio_sdk/projects/client_ext.py +19 -0
  61. label_studio_sdk/tasks/client.py +35 -8
  62. label_studio_sdk/tasks/client_ext.py +18 -0
  63. label_studio_sdk/types/__init__.py +10 -0
  64. label_studio_sdk/types/annotation.py +5 -5
  65. label_studio_sdk/types/annotations_dm_field.py +120 -0
  66. label_studio_sdk/types/annotations_dm_field_last_action.py +19 -0
  67. label_studio_sdk/types/data_manager_task_serializer.py +123 -0
  68. label_studio_sdk/types/data_manager_task_serializer_drafts_item.py +31 -0
  69. label_studio_sdk/types/data_manager_task_serializer_predictions_item.py +37 -0
  70. label_studio_sdk/types/task.py +1 -1
  71. label_studio_sdk/views/__init__.py +12 -4
  72. label_studio_sdk/views/types/__init__.py +12 -4
  73. label_studio_sdk/views/types/views_create_request_data.py +2 -2
  74. label_studio_sdk/views/types/views_create_request_data_filters.py +5 -5
  75. label_studio_sdk/views/types/views_create_request_data_filters_conjunction.py +1 -1
  76. label_studio_sdk/views/types/views_create_request_data_filters_items_item.py +11 -8
  77. label_studio_sdk/views/types/views_create_request_data_filters_items_item_filter.py +31 -0
  78. label_studio_sdk/views/types/views_create_request_data_filters_items_item_operator.py +23 -0
  79. label_studio_sdk/views/types/views_create_request_data_filters_items_item_value.py +5 -0
  80. label_studio_sdk/views/types/views_create_request_data_ordering_item.py +27 -34
  81. label_studio_sdk/views/types/views_update_request_data.py +2 -2
  82. label_studio_sdk/views/types/views_update_request_data_filters.py +5 -5
  83. label_studio_sdk/views/types/views_update_request_data_filters_conjunction.py +1 -1
  84. label_studio_sdk/views/types/views_update_request_data_filters_items_item.py +11 -8
  85. label_studio_sdk/views/types/views_update_request_data_filters_items_item_filter.py +31 -0
  86. label_studio_sdk/views/types/views_update_request_data_filters_items_item_operator.py +23 -0
  87. label_studio_sdk/views/types/views_update_request_data_filters_items_item_value.py +5 -0
  88. label_studio_sdk/views/types/views_update_request_data_ordering_item.py +27 -34
  89. label_studio_sdk-1.0.2.dist-info/METADATA +195 -0
  90. {label_studio_sdk-1.0.0.dist-info → label_studio_sdk-1.0.2.dist-info}/RECORD +94 -69
  91. label_studio_sdk/_legacy/label_interface/region.py +0 -43
  92. label_studio_sdk/_legacy/objects.py +0 -35
  93. label_studio_sdk/views/types/views_create_request_data_ordering_item_direction.py +0 -5
  94. label_studio_sdk/views/types/views_update_request_data_ordering_item_direction.py +0 -5
  95. label_studio_sdk-1.0.0.dist-info/METADATA +0 -307
  96. /label_studio_sdk/{_legacy/label_interface → label_interface}/__init__.py +0 -0
  97. /label_studio_sdk/{_legacy/label_interface → label_interface}/data_examples.json +0 -0
  98. /label_studio_sdk/{_legacy/label_interface → label_interface}/label_tags.py +0 -0
  99. {label_studio_sdk-1.0.0.dist-info → label_studio_sdk-1.0.2.dist-info}/WHEEL +0 -0
@@ -8,29 +8,54 @@ from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
8
8
 
9
9
 
10
10
  class S3CreateResponse(pydantic_v1.BaseModel):
11
- project: typing.Optional[int] = pydantic_v1.Field(default=None)
11
+ regex_filter: typing.Optional[str] = pydantic_v1.Field(default=None)
12
12
  """
13
- Project ID
13
+ Cloud storage regex for filtering objects. You must specify it otherwise no objects will be imported.
14
14
  """
15
15
 
16
- bucket: typing.Optional[str] = pydantic_v1.Field(default=None)
16
+ use_blob_urls: typing.Optional[bool] = pydantic_v1.Field(default=None)
17
17
  """
18
- S3 bucket name
18
+ Interpret objects as BLOBs and generate URLs. For example, if your bucket contains images, you can use this option to generate URLs for these images. If set to False, it will read the content of the file and load it into Label Studio.
19
19
  """
20
20
 
21
- prefix: typing.Optional[str] = pydantic_v1.Field(default=None)
21
+ presign: typing.Optional[bool] = pydantic_v1.Field(default=None)
22
22
  """
23
- S3 bucket prefix
23
+ Presign URLs for download
24
24
  """
25
25
 
26
- regex_filter: typing.Optional[str] = pydantic_v1.Field(default=None)
26
+ presign_ttl: typing.Optional[int] = pydantic_v1.Field(default=None)
27
27
  """
28
- Cloud storage regex for filtering objects
28
+ Presign TTL in minutes
29
29
  """
30
30
 
31
- use_blob_urls: typing.Optional[bool] = pydantic_v1.Field(default=None)
31
+ recursive_scan: typing.Optional[bool] = pydantic_v1.Field(default=None)
32
+ """
33
+ Scan recursively
34
+ """
35
+
36
+ title: typing.Optional[str] = pydantic_v1.Field(default=None)
37
+ """
38
+ Storage title
39
+ """
40
+
41
+ description: typing.Optional[str] = pydantic_v1.Field(default=None)
42
+ """
43
+ Storage description
44
+ """
45
+
46
+ project: typing.Optional[int] = pydantic_v1.Field(default=None)
32
47
  """
33
- Interpret objects as BLOBs and generate URLs
48
+ Project ID
49
+ """
50
+
51
+ bucket: typing.Optional[str] = pydantic_v1.Field(default=None)
52
+ """
53
+ S3 bucket name
54
+ """
55
+
56
+ prefix: typing.Optional[str] = pydantic_v1.Field(default=None)
57
+ """
58
+ S3 bucket prefix
34
59
  """
35
60
 
36
61
  aws_access_key_id: typing.Optional[str] = pydantic_v1.Field(default=None)
@@ -63,21 +88,6 @@ class S3CreateResponse(pydantic_v1.BaseModel):
63
88
  S3 Endpoint
64
89
  """
65
90
 
66
- presign: typing.Optional[bool] = pydantic_v1.Field(default=None)
67
- """
68
- Presign URLs for download
69
- """
70
-
71
- presign_ttl: typing.Optional[int] = pydantic_v1.Field(default=None)
72
- """
73
- Presign TTL in seconds
74
- """
75
-
76
- recursive_scan: typing.Optional[bool] = pydantic_v1.Field(default=None)
77
- """
78
- Scan recursively
79
- """
80
-
81
91
  def json(self, **kwargs: typing.Any) -> str:
82
92
  kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
83
93
  return super().json(**kwargs_with_defaults)
@@ -8,29 +8,54 @@ from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
8
8
 
9
9
 
10
10
  class S3UpdateResponse(pydantic_v1.BaseModel):
11
- project: typing.Optional[int] = pydantic_v1.Field(default=None)
11
+ regex_filter: typing.Optional[str] = pydantic_v1.Field(default=None)
12
12
  """
13
- Project ID
13
+ Cloud storage regex for filtering objects. You must specify it otherwise no objects will be imported.
14
14
  """
15
15
 
16
- bucket: typing.Optional[str] = pydantic_v1.Field(default=None)
16
+ use_blob_urls: typing.Optional[bool] = pydantic_v1.Field(default=None)
17
17
  """
18
- S3 bucket name
18
+ Interpret objects as BLOBs and generate URLs. For example, if your bucket contains images, you can use this option to generate URLs for these images. If set to False, it will read the content of the file and load it into Label Studio.
19
19
  """
20
20
 
21
- prefix: typing.Optional[str] = pydantic_v1.Field(default=None)
21
+ presign: typing.Optional[bool] = pydantic_v1.Field(default=None)
22
22
  """
23
- S3 bucket prefix
23
+ Presign URLs for download
24
24
  """
25
25
 
26
- regex_filter: typing.Optional[str] = pydantic_v1.Field(default=None)
26
+ presign_ttl: typing.Optional[int] = pydantic_v1.Field(default=None)
27
27
  """
28
- Cloud storage regex for filtering objects
28
+ Presign TTL in minutes
29
29
  """
30
30
 
31
- use_blob_urls: typing.Optional[bool] = pydantic_v1.Field(default=None)
31
+ recursive_scan: typing.Optional[bool] = pydantic_v1.Field(default=None)
32
+ """
33
+ Scan recursively
34
+ """
35
+
36
+ title: typing.Optional[str] = pydantic_v1.Field(default=None)
37
+ """
38
+ Storage title
39
+ """
40
+
41
+ description: typing.Optional[str] = pydantic_v1.Field(default=None)
42
+ """
43
+ Storage description
44
+ """
45
+
46
+ project: typing.Optional[int] = pydantic_v1.Field(default=None)
32
47
  """
33
- Interpret objects as BLOBs and generate URLs
48
+ Project ID
49
+ """
50
+
51
+ bucket: typing.Optional[str] = pydantic_v1.Field(default=None)
52
+ """
53
+ S3 bucket name
54
+ """
55
+
56
+ prefix: typing.Optional[str] = pydantic_v1.Field(default=None)
57
+ """
58
+ S3 bucket prefix
34
59
  """
35
60
 
36
61
  aws_access_key_id: typing.Optional[str] = pydantic_v1.Field(default=None)
@@ -63,21 +88,6 @@ class S3UpdateResponse(pydantic_v1.BaseModel):
63
88
  S3 Endpoint
64
89
  """
65
90
 
66
- presign: typing.Optional[bool] = pydantic_v1.Field(default=None)
67
- """
68
- Presign URLs for download
69
- """
70
-
71
- presign_ttl: typing.Optional[int] = pydantic_v1.Field(default=None)
72
- """
73
- Presign TTL in seconds
74
- """
75
-
76
- recursive_scan: typing.Optional[bool] = pydantic_v1.Field(default=None)
77
- """
78
- Scan recursively
79
- """
80
-
81
91
  def json(self, **kwargs: typing.Any) -> str:
82
92
  kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
83
93
  return super().json(**kwargs_with_defaults)
@@ -2,6 +2,16 @@ from pydantic import BaseModel
2
2
  from typing import Dict, Optional, List, Tuple, Any, Callable
3
3
 
4
4
 
5
+ def get_tag_class(name, default_mapping, re_mapping=None):
6
+ """ """
7
+ lc_name = name.lower()
8
+ if re_mapping and lc_name in re_mapping:
9
+ return re_mapping.get(lc_name)
10
+ else:
11
+ class_name = default_mapping.get(name.lower())
12
+ return class_name
13
+
14
+
5
15
  class LabelStudioTag(BaseModel):
6
16
  """
7
17
  Base class for a LabelStudio Tag
@@ -3,9 +3,9 @@
3
3
 
4
4
  import xml.etree.ElementTree
5
5
  from typing import Type, Dict, Optional, List, Tuple, Any, Union
6
- from pydantic import BaseModel, confloat
6
+ from pydantic import BaseModel, confloat, Field, validator
7
7
 
8
- from .base import LabelStudioTag
8
+ from .base import LabelStudioTag, get_tag_class
9
9
  from .region import Region
10
10
  from .object_tags import ObjectTag
11
11
 
@@ -42,12 +42,6 @@ _TAG_TO_CLASS = {
42
42
  }
43
43
 
44
44
 
45
- def get_tag_class(name):
46
- """ """
47
- class_name = _TAG_TO_CLASS.get(name.lower())
48
- return globals().get(class_name, None)
49
-
50
-
51
45
  class ControlTag(LabelStudioTag):
52
46
  """
53
47
  Class that represents a ControlTag in Label Studio
@@ -100,7 +94,7 @@ class ControlTag(LabelStudioTag):
100
94
  )
101
95
 
102
96
  @classmethod
103
- def parse_node(cls, tag: xml.etree.ElementTree.Element) -> "ControlTag":
97
+ def parse_node(cls, tag: xml.etree.ElementTree.Element, tags_mapping=None) -> "ControlTag":
104
98
  """
105
99
  Parse tag into a tag info
106
100
 
@@ -114,8 +108,10 @@ class ControlTag(LabelStudioTag):
114
108
  ControlTag
115
109
  The parsed tag
116
110
  """
117
- tag_class = get_tag_class(tag.tag) or cls
118
-
111
+ tag_class = get_tag_class(tag.tag, _TAG_TO_CLASS, re_mapping=tags_mapping) or cls
112
+ if isinstance(tag_class, str):
113
+ tag_class = globals().get(tag_class, None)
114
+
119
115
  tag_info = {
120
116
  "tag": tag.tag,
121
117
  "name": tag.attrib["name"],
@@ -142,7 +138,9 @@ class ControlTag(LabelStudioTag):
142
138
  if conditionals:
143
139
  tag_info["conditionals"] = conditionals
144
140
 
145
- if tag.attrib.get("value", "empty")[0] == "$" or tag.attrib.get("apiUrl"):
141
+ val = tag.attrib.get("value", None)
142
+ if (val is not None and len(val) and val[0] == "$") or \
143
+ tag.attrib.get("apiUrl"):
146
144
  tag_info["dynamic_value"] = True
147
145
 
148
146
  return tag_class(**tag_info)
@@ -290,6 +288,7 @@ class ControlTag(LabelStudioTag):
290
288
  bool
291
289
  True if the value is valid, False otherwise
292
290
  """
291
+
293
292
  if hasattr(self, "_label_attr_name"):
294
293
  if not self._validate_value_labels(value):
295
294
  return False
@@ -361,7 +360,7 @@ class ControlTag(LabelStudioTag):
361
360
  obj = self.find_object_by_name(to_name)
362
361
  cls = self._value_class
363
362
  value = cls(**kwargs)
364
-
363
+
365
364
  return Region(from_tag=self, to_tag=obj, value=value)
366
365
 
367
366
  def _label_with_labels(
@@ -419,8 +418,8 @@ class ControlTag(LabelStudioTag):
419
418
  **kwargs,
420
419
  ) -> Region:
421
420
  """
422
- This method creates a new Region object with the specified label applied.
423
- If not labels are provided, it creates a new instance of the value class with the provided arguments and keyword arguments.
421
+ This method creates a new Region object with the specified label.
422
+
424
423
  If labels are provided, it creates a new instance of the value class with the provided arguments and keyword arguments and adds the labels to the Region object.
425
424
 
426
425
  Parameters:
@@ -459,13 +458,13 @@ class ControlTag(LabelStudioTag):
459
458
 
460
459
 
461
460
  class SpanSelection(BaseModel):
462
- start: str
463
- end: str
461
+ start: int = Field(..., ge=0)
462
+ end: int = Field(..., ge=0)
464
463
 
465
464
 
466
465
  class SpanSelectionOffsets(SpanSelection):
467
- startOffset: int
468
- endOffset: int
466
+ startOffset: int = Field(..., ge=0)
467
+ endOffset: int = Field(..., ge=0)
469
468
 
470
469
 
471
470
  class ChoicesValue(BaseModel):
@@ -492,11 +491,42 @@ class LabelsTag(ControlTag):
492
491
 
493
492
  ## Image tags
494
493
 
494
+ def validate_rle(list):
495
+ """
496
+ Validate if a list is correctly formatted in Run-Length Encoding (RLE).
497
+
498
+ A correctly formatted RLE list should follow 'value, count' pairs.
499
+ For example, [2,3,3,2] is a valid RLE list representing [2,2,2,3,3].
500
+
501
+ Parameters:
502
+ list : a list of integers
503
+
504
+ Returns:
505
+ bool : True if the list is correctly formatted in RLE, False otherwise
506
+ """
507
+ # If the list length is odd, it's invalid.
508
+ if len(list) % 2 != 0:
509
+ return False
510
+
511
+ # Check 'value, count' pairs. The count should always be greater than zero.
512
+ for i in range(1, len(list), 2):
513
+ if list[i] <= 0:
514
+ return False
515
+
516
+ return True
517
+
495
518
 
496
519
  class BrushValue(BaseModel):
497
- format: str
520
+ format: str = "rle"
498
521
  rle: List[int]
499
522
 
523
+ @validator('rle')
524
+ def validate_rle(cls, rle_data):
525
+ if not validate_rle(rle_data):
526
+ raise ValueError('Invalid RLE format')
527
+
528
+ return rle_data
529
+
500
530
 
501
531
  class BrushLabelsValue(BrushValue):
502
532
  brushlabels: List[str]
@@ -507,8 +537,14 @@ class BrushTag(ControlTag):
507
537
 
508
538
  _value_class: Type[BrushValue] = BrushValue
509
539
 
540
+ # def validate_value(self, value) -> bool:
541
+ # res = super().validate_value(value)
542
+ # if res is True and value.get("format") == "rle":
543
+ # return validate_rle(value.get("rle"))
544
+
545
+ # return res
510
546
 
511
- class BrushLabelsTag(ControlTag):
547
+ class BrushLabelsTag(BrushTag):
512
548
  """ """
513
549
 
514
550
  _label_attr_name: str = "brushlabels"
@@ -520,7 +556,7 @@ class EllipseValue(BaseModel):
520
556
  y: confloat(le=100)
521
557
  radiusX: confloat(le=50)
522
558
  radiusY: confloat(le=50)
523
- rotation: confloat(le=360) = 0
559
+ rotation: Optional[confloat(le=360)] = 0
524
560
 
525
561
 
526
562
  class EllipseLabelsValue(EllipseValue):
@@ -563,7 +599,7 @@ class KeyPointLabelsTag(ControlTag):
563
599
 
564
600
 
565
601
  class PolygonValue(BaseModel):
566
- points: Tuple[confloat(le=100), confloat(le=100)]
602
+ points: List[Tuple[confloat(le=100), confloat(le=100)]]
567
603
 
568
604
 
569
605
  class PolygonLabelsValue(PolygonValue):
@@ -575,9 +611,6 @@ class PolygonTag(ControlTag):
575
611
 
576
612
  _value_class: Type[PolygonValue] = PolygonValue
577
613
 
578
- def label(self, *args, **kwargs):
579
- """ """
580
-
581
614
 
582
615
  class PolygonLabelsTag(ControlTag):
583
616
  """ """
@@ -591,7 +624,7 @@ class RectangleValue(BaseModel):
591
624
  y: confloat(le=100)
592
625
  width: confloat(le=100)
593
626
  height: confloat(le=100)
594
- rotation: confloat(le=360)
627
+ rotation: Optional[confloat(le=360)] = 0
595
628
 
596
629
 
597
630
  class RectangleLabelsValue(RectangleValue):
@@ -611,42 +644,45 @@ class RectangleLabelsTag(ControlTag):
611
644
  _value_class: Type[RectangleLabelsValue] = RectangleLabelsValue
612
645
 
613
646
 
614
- class VideoRectangleValue(BaseModel):
615
- x: float
616
- y: float
617
- width: float
618
- height: float
619
- rotation: float
647
+ class VideoRectangleSequenceValue(BaseModel):
648
+ x: confloat(le=100)
649
+ y: confloat(le=100)
650
+ time: float
651
+ frame: int
652
+ width: confloat(le=100)
653
+ height: confloat(le=100)
654
+ rotation: Optional[float] = 0
620
655
 
621
656
 
657
+ class VideoRectangleValue(BaseModel):
658
+ framesCount: int
659
+ duration: float
660
+ sequence: List[VideoRectangleSequenceValue]
661
+ labels: Optional[List[str]]
662
+
663
+
622
664
  class VideoRectangleTag(ControlTag):
623
665
  """ """
624
-
666
+ _label_attr_name: str = "labels"
625
667
  _value_class: Type[VideoRectangleValue] = VideoRectangleValue
626
-
668
+
669
+
670
+ class NumberValue(BaseModel):
671
+ number: int = Field(..., ge=0)
672
+
627
673
 
628
674
  class NumberTag(ControlTag):
629
675
  """ """
676
+ _value_class: Type[NumberValue] = NumberValue
677
+
630
678
 
631
- def validate_value(self, value) -> bool:
632
- """ """
633
- # TODO implement
634
- return True
635
-
636
- def label(self, *args, **kwargs):
637
- """ """
638
-
679
+ class DateTimeValue(BaseModel):
680
+ datetime: str
639
681
 
682
+
640
683
  class DateTimeTag(ControlTag):
641
684
  """ """
642
-
643
- def validate_value(self, value) -> bool:
644
- """ """
645
- # TODO implement
646
- return True
647
-
648
- def label(self, *args, **kwargs):
649
- """ """
685
+ _value_class: Type[DateTimeValue] = DateTimeValue
650
686
 
651
687
 
652
688
  class HyperTextLabelsValue(SpanSelectionOffsets):
@@ -669,8 +705,10 @@ class PairwiseTag(ControlTag):
669
705
 
670
706
  _value_class: Type[PairwiseValue] = PairwiseValue
671
707
 
672
- def label(self, *args, **kwargs):
708
+ def label(self, side):
673
709
  """ """
710
+ value = PairwiseValue(selected=side)
711
+ return Region(from_tag=self, to_tag=self, value=value)
674
712
 
675
713
 
676
714
  class ParagraphLabelsValue(SpanSelectionOffsets):
@@ -683,46 +721,46 @@ class ParagraphLabelsTag(ControlTag):
683
721
  _label_attr_name: str = "paragraphlabels"
684
722
  _value_class: Type[ParagraphLabelsValue] = ParagraphLabelsValue
685
723
 
686
- def label(self, *args, **kwargs):
724
+ def label(self, utterance=None, *args, **kwargs):
687
725
  """ """
726
+ if isinstance(utterance, int):
727
+ kwargs["start"] = utterance
728
+ kwargs["end"] = utterance
729
+
730
+ return super().label(*args, **kwargs)
731
+
688
732
 
733
+ class RankerValue(BaseModel):
734
+ rank: List[str]
689
735
 
736
+
690
737
  class RankerTag(ControlTag):
691
738
  """ """
692
-
693
- def validate_value(self, value) -> bool:
694
- """ """
695
- # TODO
696
- return True
697
-
698
- def label(self, *args, **kwargs):
699
- """ """
739
+ _value_class: Type[RankerValue] = RankerValue
700
740
 
701
741
 
702
742
  class RatingValue(BaseModel):
703
- rating: int
743
+ rating: int = Field(..., ge=0)
704
744
 
705
745
 
706
746
  class RatingTag(ControlTag):
707
747
  """ """
708
-
709
748
  _value_class: Type[RatingValue] = RatingValue
710
749
 
711
- def label(self, *args, **kwargs):
712
- """ """
713
-
714
750
 
715
751
  class RelationsTag(ControlTag):
716
752
  """ """
717
-
718
- def validate_value(self, value) -> bool:
753
+ def validate_value(self, ) -> bool:
719
754
  """ """
720
- # TODO
721
- return True
755
+ raise NotImplemented("""Should not be called directly, instead
756
+ use validate_relation() method found in LabelInterface class""")
722
757
 
723
758
  def label(self, *args, **kwargs):
724
759
  """ """
725
-
760
+ raise NotImplemented("""
761
+ Relations work on regions instead of Object tags
762
+ use Regions add_relation() method""")
763
+
726
764
 
727
765
  class TaxonomyValue(BaseModel):
728
766
  taxonomy: List[List[str]]