label-studio-sdk 0.0.32__py3-none-any.whl → 1.0.0__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.
- label_studio_sdk/__init__.py +206 -6
- label_studio_sdk/_extensions/label_studio_tools/__init__.py +0 -0
- label_studio_sdk/_extensions/label_studio_tools/core/__init__.py +0 -0
- label_studio_sdk/_extensions/label_studio_tools/core/label_config.py +163 -0
- label_studio_sdk/_extensions/label_studio_tools/core/utils/__init__.py +0 -0
- label_studio_sdk/_extensions/label_studio_tools/core/utils/exceptions.py +2 -0
- label_studio_sdk/_extensions/label_studio_tools/core/utils/io.py +228 -0
- label_studio_sdk/_extensions/label_studio_tools/core/utils/params.py +45 -0
- label_studio_sdk/_extensions/label_studio_tools/etl/__init__.py +1 -0
- label_studio_sdk/_extensions/label_studio_tools/etl/beam.py +34 -0
- label_studio_sdk/_extensions/label_studio_tools/etl/example.py +17 -0
- label_studio_sdk/_extensions/label_studio_tools/etl/registry.py +67 -0
- label_studio_sdk/_extensions/label_studio_tools/postprocessing/__init__.py +0 -0
- label_studio_sdk/_extensions/label_studio_tools/postprocessing/video.py +97 -0
- label_studio_sdk/_legacy/__init__.py +11 -0
- label_studio_sdk/_legacy/client.py +471 -0
- label_studio_sdk/_legacy/exceptions.py +10 -0
- label_studio_sdk/_legacy/label_interface/__init__.py +1 -0
- label_studio_sdk/_legacy/label_interface/base.py +77 -0
- label_studio_sdk/_legacy/label_interface/control_tags.py +756 -0
- label_studio_sdk/_legacy/label_interface/data_examples.json +96 -0
- label_studio_sdk/_legacy/label_interface/interface.py +925 -0
- label_studio_sdk/_legacy/label_interface/label_tags.py +72 -0
- label_studio_sdk/_legacy/label_interface/object_tags.py +292 -0
- label_studio_sdk/_legacy/label_interface/region.py +43 -0
- label_studio_sdk/_legacy/objects.py +35 -0
- label_studio_sdk/{project.py → _legacy/project.py} +711 -258
- label_studio_sdk/_legacy/schema/label_config_schema.json +226 -0
- label_studio_sdk/{users.py → _legacy/users.py} +15 -13
- label_studio_sdk/{utils.py → _legacy/utils.py} +31 -30
- label_studio_sdk/{workspaces.py → _legacy/workspaces.py} +13 -11
- label_studio_sdk/actions/__init__.py +2 -0
- label_studio_sdk/actions/client.py +150 -0
- label_studio_sdk/annotations/__init__.py +2 -0
- label_studio_sdk/annotations/client.py +750 -0
- label_studio_sdk/client.py +164 -436
- label_studio_sdk/converter/__init__.py +7 -0
- label_studio_sdk/converter/audio.py +56 -0
- label_studio_sdk/converter/brush.py +452 -0
- label_studio_sdk/converter/converter.py +1175 -0
- label_studio_sdk/converter/exports/__init__.py +0 -0
- label_studio_sdk/converter/exports/csv.py +82 -0
- label_studio_sdk/converter/exports/csv2.py +103 -0
- label_studio_sdk/converter/funsd.py +85 -0
- label_studio_sdk/converter/imports/__init__.py +0 -0
- label_studio_sdk/converter/imports/coco.py +314 -0
- label_studio_sdk/converter/imports/colors.py +198 -0
- label_studio_sdk/converter/imports/label_config.py +45 -0
- label_studio_sdk/converter/imports/pathtrack.py +269 -0
- label_studio_sdk/converter/imports/yolo.py +236 -0
- label_studio_sdk/converter/main.py +202 -0
- label_studio_sdk/converter/utils.py +473 -0
- label_studio_sdk/core/__init__.py +33 -0
- label_studio_sdk/core/api_error.py +15 -0
- label_studio_sdk/core/client_wrapper.py +55 -0
- label_studio_sdk/core/datetime_utils.py +28 -0
- label_studio_sdk/core/file.py +38 -0
- label_studio_sdk/core/http_client.py +443 -0
- label_studio_sdk/core/jsonable_encoder.py +99 -0
- label_studio_sdk/core/pagination.py +87 -0
- label_studio_sdk/core/pydantic_utilities.py +28 -0
- label_studio_sdk/core/query_encoder.py +33 -0
- label_studio_sdk/core/remove_none_from_dict.py +11 -0
- label_studio_sdk/core/request_options.py +32 -0
- label_studio_sdk/data_manager.py +32 -23
- label_studio_sdk/environment.py +7 -0
- label_studio_sdk/errors/__init__.py +6 -0
- label_studio_sdk/errors/bad_request_error.py +8 -0
- label_studio_sdk/errors/internal_server_error.py +8 -0
- label_studio_sdk/export_storage/__init__.py +28 -0
- label_studio_sdk/export_storage/azure/__init__.py +5 -0
- label_studio_sdk/export_storage/azure/client.py +722 -0
- label_studio_sdk/export_storage/azure/types/__init__.py +6 -0
- label_studio_sdk/export_storage/azure/types/azure_create_response.py +52 -0
- label_studio_sdk/export_storage/azure/types/azure_update_response.py +52 -0
- label_studio_sdk/export_storage/client.py +107 -0
- label_studio_sdk/export_storage/gcs/__init__.py +5 -0
- label_studio_sdk/export_storage/gcs/client.py +722 -0
- label_studio_sdk/export_storage/gcs/types/__init__.py +6 -0
- label_studio_sdk/export_storage/gcs/types/gcs_create_response.py +52 -0
- label_studio_sdk/export_storage/gcs/types/gcs_update_response.py +52 -0
- label_studio_sdk/export_storage/local/__init__.py +5 -0
- label_studio_sdk/export_storage/local/client.py +688 -0
- label_studio_sdk/export_storage/local/types/__init__.py +6 -0
- label_studio_sdk/export_storage/local/types/local_create_response.py +47 -0
- label_studio_sdk/export_storage/local/types/local_update_response.py +47 -0
- label_studio_sdk/export_storage/redis/__init__.py +5 -0
- label_studio_sdk/export_storage/redis/client.py +714 -0
- label_studio_sdk/export_storage/redis/types/__init__.py +6 -0
- label_studio_sdk/export_storage/redis/types/redis_create_response.py +57 -0
- label_studio_sdk/export_storage/redis/types/redis_update_response.py +57 -0
- label_studio_sdk/export_storage/s3/__init__.py +5 -0
- label_studio_sdk/export_storage/s3/client.py +820 -0
- label_studio_sdk/export_storage/s3/types/__init__.py +6 -0
- label_studio_sdk/export_storage/s3/types/s3create_response.py +74 -0
- label_studio_sdk/export_storage/s3/types/s3update_response.py +74 -0
- label_studio_sdk/export_storage/types/__init__.py +5 -0
- label_studio_sdk/export_storage/types/export_storage_list_types_response_item.py +30 -0
- label_studio_sdk/files/__init__.py +2 -0
- label_studio_sdk/files/client.py +556 -0
- label_studio_sdk/import_storage/__init__.py +28 -0
- label_studio_sdk/import_storage/azure/__init__.py +5 -0
- label_studio_sdk/import_storage/azure/client.py +812 -0
- label_studio_sdk/import_storage/azure/types/__init__.py +6 -0
- label_studio_sdk/import_storage/azure/types/azure_create_response.py +72 -0
- label_studio_sdk/import_storage/azure/types/azure_update_response.py +72 -0
- label_studio_sdk/import_storage/client.py +107 -0
- label_studio_sdk/import_storage/gcs/__init__.py +5 -0
- label_studio_sdk/import_storage/gcs/client.py +812 -0
- label_studio_sdk/import_storage/gcs/types/__init__.py +6 -0
- label_studio_sdk/import_storage/gcs/types/gcs_create_response.py +72 -0
- label_studio_sdk/import_storage/gcs/types/gcs_update_response.py +72 -0
- label_studio_sdk/import_storage/local/__init__.py +5 -0
- label_studio_sdk/import_storage/local/client.py +690 -0
- label_studio_sdk/import_storage/local/types/__init__.py +6 -0
- label_studio_sdk/import_storage/local/types/local_create_response.py +47 -0
- label_studio_sdk/import_storage/local/types/local_update_response.py +47 -0
- label_studio_sdk/import_storage/redis/__init__.py +5 -0
- label_studio_sdk/import_storage/redis/client.py +768 -0
- label_studio_sdk/import_storage/redis/types/__init__.py +6 -0
- label_studio_sdk/import_storage/redis/types/redis_create_response.py +62 -0
- label_studio_sdk/import_storage/redis/types/redis_update_response.py +62 -0
- label_studio_sdk/import_storage/s3/__init__.py +5 -0
- label_studio_sdk/import_storage/s3/client.py +912 -0
- label_studio_sdk/import_storage/s3/types/__init__.py +6 -0
- label_studio_sdk/import_storage/s3/types/s3create_response.py +99 -0
- label_studio_sdk/import_storage/s3/types/s3update_response.py +99 -0
- label_studio_sdk/import_storage/types/__init__.py +5 -0
- label_studio_sdk/import_storage/types/import_storage_list_types_response_item.py +30 -0
- label_studio_sdk/ml/__init__.py +19 -0
- label_studio_sdk/ml/client.py +981 -0
- label_studio_sdk/ml/types/__init__.py +17 -0
- label_studio_sdk/ml/types/ml_create_request_auth_method.py +5 -0
- label_studio_sdk/ml/types/ml_create_response.py +78 -0
- label_studio_sdk/ml/types/ml_create_response_auth_method.py +5 -0
- label_studio_sdk/ml/types/ml_update_request_auth_method.py +5 -0
- label_studio_sdk/ml/types/ml_update_response.py +78 -0
- label_studio_sdk/ml/types/ml_update_response_auth_method.py +5 -0
- label_studio_sdk/predictions/__init__.py +2 -0
- label_studio_sdk/predictions/client.py +638 -0
- label_studio_sdk/projects/__init__.py +6 -0
- label_studio_sdk/projects/client.py +1053 -0
- label_studio_sdk/projects/exports/__init__.py +2 -0
- label_studio_sdk/projects/exports/client.py +930 -0
- label_studio_sdk/projects/types/__init__.py +7 -0
- label_studio_sdk/projects/types/projects_create_response.py +96 -0
- label_studio_sdk/projects/types/projects_import_tasks_response.py +71 -0
- label_studio_sdk/projects/types/projects_list_response.py +33 -0
- label_studio_sdk/py.typed +0 -0
- label_studio_sdk/tasks/__init__.py +5 -0
- label_studio_sdk/tasks/client.py +811 -0
- label_studio_sdk/tasks/types/__init__.py +6 -0
- label_studio_sdk/tasks/types/tasks_list_request_fields.py +5 -0
- label_studio_sdk/tasks/types/tasks_list_response.py +48 -0
- label_studio_sdk/types/__init__.py +115 -0
- label_studio_sdk/types/annotation.py +116 -0
- label_studio_sdk/types/annotation_filter_options.py +42 -0
- label_studio_sdk/types/annotation_last_action.py +19 -0
- label_studio_sdk/types/azure_blob_export_storage.py +112 -0
- label_studio_sdk/types/azure_blob_export_storage_status.py +7 -0
- label_studio_sdk/types/azure_blob_import_storage.py +113 -0
- label_studio_sdk/types/azure_blob_import_storage_status.py +7 -0
- label_studio_sdk/types/base_task.py +113 -0
- label_studio_sdk/types/base_user.py +42 -0
- label_studio_sdk/types/converted_format.py +36 -0
- label_studio_sdk/types/converted_format_status.py +5 -0
- label_studio_sdk/types/export.py +48 -0
- label_studio_sdk/types/export_convert.py +32 -0
- label_studio_sdk/types/export_create.py +54 -0
- label_studio_sdk/types/export_create_status.py +5 -0
- label_studio_sdk/types/export_status.py +5 -0
- label_studio_sdk/types/file_upload.py +30 -0
- label_studio_sdk/types/filter.py +53 -0
- label_studio_sdk/types/filter_group.py +35 -0
- label_studio_sdk/types/gcs_export_storage.py +112 -0
- label_studio_sdk/types/gcs_export_storage_status.py +7 -0
- label_studio_sdk/types/gcs_import_storage.py +113 -0
- label_studio_sdk/types/gcs_import_storage_status.py +7 -0
- label_studio_sdk/types/local_files_export_storage.py +97 -0
- label_studio_sdk/types/local_files_export_storage_status.py +7 -0
- label_studio_sdk/types/local_files_import_storage.py +92 -0
- label_studio_sdk/types/local_files_import_storage_status.py +7 -0
- label_studio_sdk/types/ml_backend.py +89 -0
- label_studio_sdk/types/ml_backend_auth_method.py +5 -0
- label_studio_sdk/types/ml_backend_state.py +5 -0
- label_studio_sdk/types/prediction.py +78 -0
- label_studio_sdk/types/project.py +198 -0
- label_studio_sdk/types/project_import.py +63 -0
- label_studio_sdk/types/project_import_status.py +5 -0
- label_studio_sdk/types/project_label_config.py +32 -0
- label_studio_sdk/types/project_sampling.py +7 -0
- label_studio_sdk/types/project_skip_queue.py +5 -0
- label_studio_sdk/types/redis_export_storage.py +117 -0
- label_studio_sdk/types/redis_export_storage_status.py +7 -0
- label_studio_sdk/types/redis_import_storage.py +112 -0
- label_studio_sdk/types/redis_import_storage_status.py +7 -0
- label_studio_sdk/types/s3export_storage.py +134 -0
- label_studio_sdk/types/s3export_storage_status.py +7 -0
- label_studio_sdk/types/s3import_storage.py +140 -0
- label_studio_sdk/types/s3import_storage_status.py +7 -0
- label_studio_sdk/types/serialization_option.py +36 -0
- label_studio_sdk/types/serialization_options.py +45 -0
- label_studio_sdk/types/task.py +157 -0
- label_studio_sdk/types/task_filter_options.py +49 -0
- label_studio_sdk/types/user_simple.py +37 -0
- label_studio_sdk/types/view.py +55 -0
- label_studio_sdk/types/webhook.py +67 -0
- label_studio_sdk/types/webhook_actions_item.py +21 -0
- label_studio_sdk/types/webhook_serializer_for_update.py +67 -0
- label_studio_sdk/types/webhook_serializer_for_update_actions_item.py +21 -0
- label_studio_sdk/users/__init__.py +5 -0
- label_studio_sdk/users/client.py +830 -0
- label_studio_sdk/users/types/__init__.py +6 -0
- label_studio_sdk/users/types/users_get_token_response.py +36 -0
- label_studio_sdk/users/types/users_reset_token_response.py +36 -0
- label_studio_sdk/version.py +4 -0
- label_studio_sdk/views/__init__.py +31 -0
- label_studio_sdk/views/client.py +564 -0
- label_studio_sdk/views/types/__init__.py +29 -0
- label_studio_sdk/views/types/views_create_request_data.py +43 -0
- label_studio_sdk/views/types/views_create_request_data_filters.py +43 -0
- label_studio_sdk/views/types/views_create_request_data_filters_conjunction.py +5 -0
- label_studio_sdk/views/types/views_create_request_data_filters_items_item.py +47 -0
- label_studio_sdk/views/types/views_create_request_data_ordering_item.py +38 -0
- label_studio_sdk/views/types/views_create_request_data_ordering_item_direction.py +5 -0
- label_studio_sdk/views/types/views_update_request_data.py +43 -0
- label_studio_sdk/views/types/views_update_request_data_filters.py +43 -0
- label_studio_sdk/views/types/views_update_request_data_filters_conjunction.py +5 -0
- label_studio_sdk/views/types/views_update_request_data_filters_items_item.py +47 -0
- label_studio_sdk/views/types/views_update_request_data_ordering_item.py +38 -0
- label_studio_sdk/views/types/views_update_request_data_ordering_item_direction.py +5 -0
- label_studio_sdk/webhooks/__init__.py +5 -0
- label_studio_sdk/webhooks/client.py +636 -0
- label_studio_sdk/webhooks/types/__init__.py +5 -0
- label_studio_sdk/webhooks/types/webhooks_update_request_actions_item.py +21 -0
- label_studio_sdk-1.0.0.dist-info/METADATA +307 -0
- label_studio_sdk-1.0.0.dist-info/RECORD +239 -0
- {label_studio_sdk-0.0.32.dist-info → label_studio_sdk-1.0.0.dist-info}/WHEEL +1 -2
- docs/__init__.py +0 -3
- label_studio_sdk-0.0.32.dist-info/LICENSE +0 -201
- label_studio_sdk-0.0.32.dist-info/METADATA +0 -22
- label_studio_sdk-0.0.32.dist-info/RECORD +0 -15
- label_studio_sdk-0.0.32.dist-info/top_level.txt +0 -3
- tests/test_client.py +0 -26
- {tests → label_studio_sdk/_extensions}/__init__.py +0 -0
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
"""
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
import xml.etree.ElementTree
|
|
5
|
+
from typing import Type, Dict, Optional, List, Tuple, Any, Union
|
|
6
|
+
from pydantic import BaseModel, confloat
|
|
7
|
+
|
|
8
|
+
from .base import LabelStudioTag
|
|
9
|
+
from .region import Region
|
|
10
|
+
from .object_tags import ObjectTag
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
_NOT_CONTROL_TAGS = {
|
|
14
|
+
"Filter",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_TAG_TO_CLASS = {
|
|
18
|
+
"choices": "ChoicesTag",
|
|
19
|
+
"labels": "LabelsTag",
|
|
20
|
+
"brush": "BrushTag",
|
|
21
|
+
"brushlabels": "BrushLabelsTag",
|
|
22
|
+
"ellipse": "EllipseTag",
|
|
23
|
+
"ellipselabels": "EllipseLabelsTag",
|
|
24
|
+
"keypoint": "KeyPointTag",
|
|
25
|
+
"keypointlabels": "KeyPointLabelsTag",
|
|
26
|
+
"polygon": "PolygonTag",
|
|
27
|
+
"polygonlabels": "PolygonLabelsTag",
|
|
28
|
+
"rectangle": "RectangleTag",
|
|
29
|
+
"rectanglelabels": "RectangleLabelsTag",
|
|
30
|
+
"videorectangle": "VideoRectangleTag",
|
|
31
|
+
"number": "NumberTag",
|
|
32
|
+
"datetime": "DateTimeTag",
|
|
33
|
+
"hypertext": "HyperTextLabelsTag",
|
|
34
|
+
"pairwise": "PairwiseTag",
|
|
35
|
+
"paragraphlabels": "ParagraphLabelsTag",
|
|
36
|
+
"ranker": "RankerTag",
|
|
37
|
+
"rating": "RatingTag",
|
|
38
|
+
"relations": "RelationsTag",
|
|
39
|
+
"taxonomy": "TaxonomyTag",
|
|
40
|
+
"textarea": "TextAreaTag",
|
|
41
|
+
"timeserieslabels": "TimeSeriesLabelsTag",
|
|
42
|
+
}
|
|
43
|
+
|
|
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
|
+
class ControlTag(LabelStudioTag):
|
|
52
|
+
"""
|
|
53
|
+
Class that represents a ControlTag in Label Studio
|
|
54
|
+
|
|
55
|
+
Attributes:
|
|
56
|
+
-----------
|
|
57
|
+
name : Optional[str]
|
|
58
|
+
The name of the tag
|
|
59
|
+
to_name : Optional[List[str]]
|
|
60
|
+
The name of the object the tag maps to
|
|
61
|
+
conditionals : Optional[Dict[str, Any]]
|
|
62
|
+
Conditional attributes
|
|
63
|
+
dynamic_value : Optional[bool]
|
|
64
|
+
A flag to indicate if the value is dynamic
|
|
65
|
+
objects : Optional[Any]
|
|
66
|
+
The object tag that the control tag maps to
|
|
67
|
+
labels : Optional[Any]
|
|
68
|
+
The labels for the control tag
|
|
69
|
+
labels_attrs : Optional[Any]
|
|
70
|
+
The labels attributes for the control tag
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
name: Optional[str] = None
|
|
74
|
+
to_name: Optional[List[str]] = None
|
|
75
|
+
conditionals: Optional[Dict[str, Any]] = None
|
|
76
|
+
dynamic_value: Optional[bool] = False
|
|
77
|
+
objects: Optional[Any] = None
|
|
78
|
+
labels: Optional[Any] = None
|
|
79
|
+
labels_attrs: Optional[Any] = None
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def validate_node(cls, tag: xml.etree.ElementTree.Element) -> bool:
|
|
83
|
+
"""
|
|
84
|
+
Naive check if tag is a control tag
|
|
85
|
+
|
|
86
|
+
Parameters:
|
|
87
|
+
-----------
|
|
88
|
+
tag : xml.etree.ElementTree.Element
|
|
89
|
+
The tag to validate
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
--------
|
|
93
|
+
bool
|
|
94
|
+
True if tag is a control tag, False otherwise
|
|
95
|
+
"""
|
|
96
|
+
return bool(
|
|
97
|
+
tag.attrib.get("name")
|
|
98
|
+
and tag.attrib.get("toName")
|
|
99
|
+
and tag.tag not in _NOT_CONTROL_TAGS
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def parse_node(cls, tag: xml.etree.ElementTree.Element) -> "ControlTag":
|
|
104
|
+
"""
|
|
105
|
+
Parse tag into a tag info
|
|
106
|
+
|
|
107
|
+
Parameters:
|
|
108
|
+
-----------
|
|
109
|
+
tag : xml.etree.ElementTree.Element
|
|
110
|
+
The tag to parse
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
--------
|
|
114
|
+
ControlTag
|
|
115
|
+
The parsed tag
|
|
116
|
+
"""
|
|
117
|
+
tag_class = get_tag_class(tag.tag) or cls
|
|
118
|
+
|
|
119
|
+
tag_info = {
|
|
120
|
+
"tag": tag.tag,
|
|
121
|
+
"name": tag.attrib["name"],
|
|
122
|
+
"to_name": tag.attrib["toName"].split(","),
|
|
123
|
+
"attr": dict(tag.attrib),
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Grab conditionals if any
|
|
127
|
+
conditionals = {}
|
|
128
|
+
if tag.attrib.get("perRegion") == "true":
|
|
129
|
+
if tag.attrib.get("whenTagName"):
|
|
130
|
+
conditionals = {"type": "tag", "name": tag.attrib["whenTagName"]}
|
|
131
|
+
elif tag.attrib.get("whenLabelValue"):
|
|
132
|
+
conditionals = {
|
|
133
|
+
"type": "label",
|
|
134
|
+
"name": tag.attrib["whenLabelValue"],
|
|
135
|
+
}
|
|
136
|
+
elif tag.attrib.get("whenChoiceValue"):
|
|
137
|
+
conditionals = {
|
|
138
|
+
"type": "choice",
|
|
139
|
+
"name": tag.attrib["whenChoiceValue"],
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if conditionals:
|
|
143
|
+
tag_info["conditionals"] = conditionals
|
|
144
|
+
|
|
145
|
+
if tag.attrib.get("value", "empty")[0] == "$" or tag.attrib.get("apiUrl"):
|
|
146
|
+
tag_info["dynamic_value"] = True
|
|
147
|
+
|
|
148
|
+
return tag_class(**tag_info)
|
|
149
|
+
|
|
150
|
+
def get_object(self, name=None):
|
|
151
|
+
"""
|
|
152
|
+
This method retrieves the object tag that the control tag maps to.
|
|
153
|
+
|
|
154
|
+
Parameters:
|
|
155
|
+
-----------
|
|
156
|
+
name : Optional[str]
|
|
157
|
+
The name of the object tag to retrieve. If not provided, the method will return the first object tag.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
--------
|
|
161
|
+
Any
|
|
162
|
+
The object tag that the control tag maps to.
|
|
163
|
+
"""
|
|
164
|
+
return self.get_input(name=name)
|
|
165
|
+
|
|
166
|
+
def get_input(self, name=None):
|
|
167
|
+
"""
|
|
168
|
+
This method retrieves the object tag that the control tag maps to based on the provided name.
|
|
169
|
+
|
|
170
|
+
Parameters:
|
|
171
|
+
-----------
|
|
172
|
+
name : Optional[str]
|
|
173
|
+
The name of the object tag to retrieve. If not provided, the method will return the first object tag if there is only one.
|
|
174
|
+
If there are multiple object tags and no name is provided, an exception will be raised.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
--------
|
|
178
|
+
Any
|
|
179
|
+
The object tag that the control tag maps to.
|
|
180
|
+
|
|
181
|
+
Raises:
|
|
182
|
+
-------
|
|
183
|
+
Exception
|
|
184
|
+
If the provided name is not found in the object tags or if there are multiple object tags and no name is provided.
|
|
185
|
+
"""
|
|
186
|
+
if name is not None:
|
|
187
|
+
if name not in self.to_name:
|
|
188
|
+
raise Exception(f"Object name {name} is not found")
|
|
189
|
+
|
|
190
|
+
for tag in self.objects:
|
|
191
|
+
if tag.name == name:
|
|
192
|
+
return tag
|
|
193
|
+
|
|
194
|
+
if len(self.objects) > 1:
|
|
195
|
+
raise Exception("Multiple object tags connected, you should specify name")
|
|
196
|
+
|
|
197
|
+
return self.objects[0]
|
|
198
|
+
|
|
199
|
+
def set_labels_attrs(self, labels_attrs):
|
|
200
|
+
"""
|
|
201
|
+
This method sets the labels attributes for the ControlTag.
|
|
202
|
+
|
|
203
|
+
Parameters:
|
|
204
|
+
-----------
|
|
205
|
+
labels_attrs : Any
|
|
206
|
+
The labels attributes to set for the ControlTag.
|
|
207
|
+
"""
|
|
208
|
+
self.labels_attrs = labels_attrs
|
|
209
|
+
|
|
210
|
+
def set_object(self, tag: ObjectTag):
|
|
211
|
+
"""
|
|
212
|
+
This method sets the object tag that the control tag maps to.
|
|
213
|
+
|
|
214
|
+
Parameters:
|
|
215
|
+
-----------
|
|
216
|
+
tag : ObjectTag
|
|
217
|
+
The object tag to set for the control tag.
|
|
218
|
+
"""
|
|
219
|
+
self.set_objects([tag])
|
|
220
|
+
|
|
221
|
+
def set_objects(self, objects: List[ObjectTag]):
|
|
222
|
+
"""
|
|
223
|
+
This method sets the object tags that the control tag maps to.
|
|
224
|
+
|
|
225
|
+
Parameters:
|
|
226
|
+
-----------
|
|
227
|
+
objects : List[ObjectTag]
|
|
228
|
+
The object tags to set for the control tag.
|
|
229
|
+
"""
|
|
230
|
+
self.objects = objects
|
|
231
|
+
|
|
232
|
+
def set_labels(self, labels: List[str]):
|
|
233
|
+
"""
|
|
234
|
+
Set labels for the ControlTag
|
|
235
|
+
"""
|
|
236
|
+
self.labels = labels
|
|
237
|
+
|
|
238
|
+
def find_object_by_name(self, name: str) -> Optional[ObjectTag]:
|
|
239
|
+
"""
|
|
240
|
+
This method finds and returns an object tag with the specified name from the list of object tags.
|
|
241
|
+
|
|
242
|
+
Parameters:
|
|
243
|
+
-----------
|
|
244
|
+
name : str
|
|
245
|
+
The name of the object tag to find.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
--------
|
|
249
|
+
Optional[ObjectTag]
|
|
250
|
+
The object tag with the specified name if found, None otherwise.
|
|
251
|
+
"""
|
|
252
|
+
for obj in self.objects:
|
|
253
|
+
if obj.name == name:
|
|
254
|
+
return obj
|
|
255
|
+
|
|
256
|
+
def _validate_labels(self, labels):
|
|
257
|
+
"""Check that labels is a subset of self.labels, used for
|
|
258
|
+
example when you're validate the annotaion or prediction to
|
|
259
|
+
make sure there no undefined labels used.
|
|
260
|
+
|
|
261
|
+
"""
|
|
262
|
+
if not self.labels:
|
|
263
|
+
return True
|
|
264
|
+
|
|
265
|
+
return set(labels).issubset(set(self.labels))
|
|
266
|
+
|
|
267
|
+
def _validate_value_labels(self, value):
|
|
268
|
+
""" """
|
|
269
|
+
if self._label_attr_name not in value:
|
|
270
|
+
return False
|
|
271
|
+
|
|
272
|
+
return self._validate_labels(value.get(self._label_attr_name))
|
|
273
|
+
|
|
274
|
+
def validate_value(self, value: dict) -> bool:
|
|
275
|
+
"""
|
|
276
|
+
Given "value" from [annotation result format](https://labelstud.io/guide/task_format),
|
|
277
|
+
validate if it's a valid value for this control tag.
|
|
278
|
+
|
|
279
|
+
Parameters:
|
|
280
|
+
-----------
|
|
281
|
+
value : dict
|
|
282
|
+
The value to validate
|
|
283
|
+
Example:
|
|
284
|
+
```python
|
|
285
|
+
RectangleTag(name="rect", to_name=["img"], tag="rectangle", attr={}).validate_value({"x": 10, "y": 10, "width": 10, "height": 10, "rotation": 10})
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
--------
|
|
290
|
+
bool
|
|
291
|
+
True if the value is valid, False otherwise
|
|
292
|
+
"""
|
|
293
|
+
if hasattr(self, "_label_attr_name"):
|
|
294
|
+
if not self._validate_value_labels(value):
|
|
295
|
+
return False
|
|
296
|
+
|
|
297
|
+
try:
|
|
298
|
+
inst = self._value_class(**value)
|
|
299
|
+
return True
|
|
300
|
+
except Exception as e:
|
|
301
|
+
return False
|
|
302
|
+
|
|
303
|
+
def _resolve_to_name(self, to_name: Optional[str] = None) -> str:
|
|
304
|
+
"""
|
|
305
|
+
This method resolves the name of the object tag that the control tag maps to.
|
|
306
|
+
If a name is provided and it is found in the control tag, it is returned.
|
|
307
|
+
If no name is provided and there is only one object tag, its name is returned.
|
|
308
|
+
If no name is provided and there are multiple object tags, an exception is raised.
|
|
309
|
+
|
|
310
|
+
Parameters:
|
|
311
|
+
-----------
|
|
312
|
+
to_name : Optional[str]
|
|
313
|
+
The name of the object tag to resolve. If not provided, the method will return the name of the first object tag if there is only one.
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
--------
|
|
317
|
+
str
|
|
318
|
+
The name of the object tag that the control tag maps to.
|
|
319
|
+
|
|
320
|
+
Raises:
|
|
321
|
+
-------
|
|
322
|
+
Exception
|
|
323
|
+
If the provided name is not found in the object tags or if there are multiple object tags and no name is provided.
|
|
324
|
+
"""
|
|
325
|
+
if to_name:
|
|
326
|
+
if to_name not in self.to_name:
|
|
327
|
+
raise Exception("To name is not found in control tag")
|
|
328
|
+
|
|
329
|
+
return to_name
|
|
330
|
+
else:
|
|
331
|
+
if len(self.to_name) > 1:
|
|
332
|
+
raise Exception(
|
|
333
|
+
"Multiple to_name in control tag, specify to_name in function"
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
return self.to_name[0]
|
|
337
|
+
|
|
338
|
+
def _label_simple(self, to_name: Optional[str] = None, *args, **kwargs) -> Region:
|
|
339
|
+
"""
|
|
340
|
+
This method creates a new Region object with the specified label applied.
|
|
341
|
+
It first resolves the name of the object tag that the control tag maps to.
|
|
342
|
+
Then it finds the object tag with the resolved name.
|
|
343
|
+
It creates a new instance of the value class with the provided arguments and keyword arguments.
|
|
344
|
+
Finally, it returns a new Region object with the current control tag, the found object tag, and the created value.
|
|
345
|
+
|
|
346
|
+
Parameters:
|
|
347
|
+
-----------
|
|
348
|
+
to_name : Optional[str]
|
|
349
|
+
The name of the object tag to resolve. If not provided, the method will return the name of the first object tag if there is only one.
|
|
350
|
+
*args : tuple
|
|
351
|
+
Variable length argument list.
|
|
352
|
+
**kwargs : dict
|
|
353
|
+
Arbitrary keyword arguments.
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
--------
|
|
357
|
+
Region
|
|
358
|
+
A new Region object with the specified label applied.
|
|
359
|
+
"""
|
|
360
|
+
to_name = self._resolve_to_name(to_name)
|
|
361
|
+
obj = self.find_object_by_name(to_name)
|
|
362
|
+
cls = self._value_class
|
|
363
|
+
value = cls(**kwargs)
|
|
364
|
+
|
|
365
|
+
return Region(from_tag=self, to_tag=obj, value=value)
|
|
366
|
+
|
|
367
|
+
def _label_with_labels(
|
|
368
|
+
self,
|
|
369
|
+
label: Union[str, List[str]] = None,
|
|
370
|
+
to_name: Optional[str] = None,
|
|
371
|
+
*args,
|
|
372
|
+
**kwargs,
|
|
373
|
+
) -> Region:
|
|
374
|
+
"""
|
|
375
|
+
This method creates a new Region object with the specified label applied.
|
|
376
|
+
It first checks if the label is a string and if so, converts it to a list.
|
|
377
|
+
Then it validates the labels and raises an exception if they are not valid.
|
|
378
|
+
It adds the labels to the keyword arguments under the attribute name for labels.
|
|
379
|
+
Finally, it calls the _label_simple method to create and return a new Region object.
|
|
380
|
+
|
|
381
|
+
Parameters:
|
|
382
|
+
-----------
|
|
383
|
+
label : Union[str, List[str]], optional
|
|
384
|
+
The label to be applied. If a string is provided, it is converted to a list.
|
|
385
|
+
to_name : Optional[str], optional
|
|
386
|
+
The name of the object tag to resolve. If not provided, the method will return the name of the first object tag if there is only one.
|
|
387
|
+
*args : tuple
|
|
388
|
+
Variable length argument list.
|
|
389
|
+
**kwargs : dict
|
|
390
|
+
Arbitrary keyword arguments.
|
|
391
|
+
|
|
392
|
+
Returns:
|
|
393
|
+
--------
|
|
394
|
+
Region
|
|
395
|
+
A new Region object with the specified label applied.
|
|
396
|
+
|
|
397
|
+
Raises:
|
|
398
|
+
-------
|
|
399
|
+
Exception
|
|
400
|
+
If the labels are not valid.
|
|
401
|
+
"""
|
|
402
|
+
if isinstance(label, str):
|
|
403
|
+
label = [label]
|
|
404
|
+
|
|
405
|
+
if not self._validate_labels(label):
|
|
406
|
+
raise ValueError(
|
|
407
|
+
f"Using labels not defined in labeling config, possible values: {set(self.labels)}"
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
kwargs[self._label_attr_name] = label
|
|
411
|
+
|
|
412
|
+
return self._label_simple(to_name=to_name, **kwargs)
|
|
413
|
+
|
|
414
|
+
def label(
|
|
415
|
+
self,
|
|
416
|
+
label: Optional[Union[str, List[str]]] = None,
|
|
417
|
+
to_name: Optional[str] = None,
|
|
418
|
+
*args,
|
|
419
|
+
**kwargs,
|
|
420
|
+
) -> Region:
|
|
421
|
+
"""
|
|
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.
|
|
424
|
+
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
|
+
|
|
426
|
+
Parameters:
|
|
427
|
+
-----------
|
|
428
|
+
label : Optional[Union[str, List[str]]]
|
|
429
|
+
The label to be applied. If a string is provided, it is converted to a list.
|
|
430
|
+
to_name : Optional[str]
|
|
431
|
+
The name of the object tag to resolve. If not provided, the method will return the name of the first object tag if there is only one.
|
|
432
|
+
*args : tuple
|
|
433
|
+
Variable length argument list.
|
|
434
|
+
**kwargs : dict
|
|
435
|
+
Arbitrary keyword arguments.
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
--------
|
|
439
|
+
Region
|
|
440
|
+
A new Region object with the specified label applied.
|
|
441
|
+
"""
|
|
442
|
+
if hasattr(self, "_label_attr_name"):
|
|
443
|
+
return self._label_with_labels(
|
|
444
|
+
label=label, to_name=to_name, *args, **kwargs
|
|
445
|
+
)
|
|
446
|
+
else:
|
|
447
|
+
return self._label_simple(to_name=to_name, *args, **kwargs)
|
|
448
|
+
|
|
449
|
+
def as_tuple(self):
|
|
450
|
+
""" """
|
|
451
|
+
from_name = self.name
|
|
452
|
+
to_name = self.to_name
|
|
453
|
+
tag_type = self.tag
|
|
454
|
+
|
|
455
|
+
if isinstance(to_name, list):
|
|
456
|
+
to_name = ",".join(to_name)
|
|
457
|
+
|
|
458
|
+
return "|".join([from_name, to_name, type.lower()])
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
class SpanSelection(BaseModel):
|
|
462
|
+
start: str
|
|
463
|
+
end: str
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class SpanSelectionOffsets(SpanSelection):
|
|
467
|
+
startOffset: int
|
|
468
|
+
endOffset: int
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class ChoicesValue(BaseModel):
|
|
472
|
+
choices: List[str]
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
class ChoicesTag(ControlTag):
|
|
476
|
+
""" """
|
|
477
|
+
|
|
478
|
+
_label_attr_name: str = "choices"
|
|
479
|
+
_value_class: Type[ChoicesValue] = ChoicesValue
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
class LabelsValue(SpanSelection):
|
|
483
|
+
labels: List[str]
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class LabelsTag(ControlTag):
|
|
487
|
+
""" """
|
|
488
|
+
|
|
489
|
+
_label_attr_name: str = "labels"
|
|
490
|
+
_value_class: Type[LabelsValue] = LabelsValue
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
## Image tags
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
class BrushValue(BaseModel):
|
|
497
|
+
format: str
|
|
498
|
+
rle: List[int]
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
class BrushLabelsValue(BrushValue):
|
|
502
|
+
brushlabels: List[str]
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
class BrushTag(ControlTag):
|
|
506
|
+
""" """
|
|
507
|
+
|
|
508
|
+
_value_class: Type[BrushValue] = BrushValue
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
class BrushLabelsTag(ControlTag):
|
|
512
|
+
""" """
|
|
513
|
+
|
|
514
|
+
_label_attr_name: str = "brushlabels"
|
|
515
|
+
_value_class: Type[BrushLabelsValue] = BrushLabelsValue
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
class EllipseValue(BaseModel):
|
|
519
|
+
x: confloat(le=100)
|
|
520
|
+
y: confloat(le=100)
|
|
521
|
+
radiusX: confloat(le=50)
|
|
522
|
+
radiusY: confloat(le=50)
|
|
523
|
+
rotation: confloat(le=360) = 0
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class EllipseLabelsValue(EllipseValue):
|
|
527
|
+
ellipselabels: List[str]
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
class EllipseTag(ControlTag):
|
|
531
|
+
""" """
|
|
532
|
+
|
|
533
|
+
_value_class: Type[EllipseValue] = EllipseValue
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
class EllipseLabelsTag(ControlTag):
|
|
537
|
+
""" """
|
|
538
|
+
|
|
539
|
+
_label_attr_name: str = "ellipselabels"
|
|
540
|
+
_value_class: Type[EllipseLabelsValue] = EllipseLabelsValue
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
class KeyPointValue(BaseModel):
|
|
544
|
+
x: confloat(le=100)
|
|
545
|
+
y: confloat(le=100)
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
class KeyPointLabelsValue(KeyPointValue):
|
|
549
|
+
keypointlabels: List[str]
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
class KeyPointTag(ControlTag):
|
|
553
|
+
""" """
|
|
554
|
+
|
|
555
|
+
_value_class: Type[KeyPointValue] = KeyPointValue
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
class KeyPointLabelsTag(ControlTag):
|
|
559
|
+
""" """
|
|
560
|
+
|
|
561
|
+
_label_attr_name: str = "keypointlabels"
|
|
562
|
+
_value_class: Type[KeyPointLabelsValue] = KeyPointLabelsValue
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
class PolygonValue(BaseModel):
|
|
566
|
+
points: Tuple[confloat(le=100), confloat(le=100)]
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
class PolygonLabelsValue(PolygonValue):
|
|
570
|
+
polygonlabels: List[str]
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
class PolygonTag(ControlTag):
|
|
574
|
+
""" """
|
|
575
|
+
|
|
576
|
+
_value_class: Type[PolygonValue] = PolygonValue
|
|
577
|
+
|
|
578
|
+
def label(self, *args, **kwargs):
|
|
579
|
+
""" """
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
class PolygonLabelsTag(ControlTag):
|
|
583
|
+
""" """
|
|
584
|
+
|
|
585
|
+
_label_attr_name: str = "polygonlabels"
|
|
586
|
+
_value_class: Type[PolygonLabelsValue] = PolygonLabelsValue
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
class RectangleValue(BaseModel):
|
|
590
|
+
x: confloat(le=100)
|
|
591
|
+
y: confloat(le=100)
|
|
592
|
+
width: confloat(le=100)
|
|
593
|
+
height: confloat(le=100)
|
|
594
|
+
rotation: confloat(le=360)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
class RectangleLabelsValue(RectangleValue):
|
|
598
|
+
rectanglelabels: List[str]
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
class RectangleTag(ControlTag):
|
|
602
|
+
""" """
|
|
603
|
+
|
|
604
|
+
_value_class: Type[RectangleValue] = RectangleValue
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
class RectangleLabelsTag(ControlTag):
|
|
608
|
+
""" """
|
|
609
|
+
|
|
610
|
+
_label_attr_name: str = "rectanglelabels"
|
|
611
|
+
_value_class: Type[RectangleLabelsValue] = RectangleLabelsValue
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
class VideoRectangleValue(BaseModel):
|
|
615
|
+
x: float
|
|
616
|
+
y: float
|
|
617
|
+
width: float
|
|
618
|
+
height: float
|
|
619
|
+
rotation: float
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
class VideoRectangleTag(ControlTag):
|
|
623
|
+
""" """
|
|
624
|
+
|
|
625
|
+
_value_class: Type[VideoRectangleValue] = VideoRectangleValue
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
class NumberTag(ControlTag):
|
|
629
|
+
""" """
|
|
630
|
+
|
|
631
|
+
def validate_value(self, value) -> bool:
|
|
632
|
+
""" """
|
|
633
|
+
# TODO implement
|
|
634
|
+
return True
|
|
635
|
+
|
|
636
|
+
def label(self, *args, **kwargs):
|
|
637
|
+
""" """
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
class DateTimeTag(ControlTag):
|
|
641
|
+
""" """
|
|
642
|
+
|
|
643
|
+
def validate_value(self, value) -> bool:
|
|
644
|
+
""" """
|
|
645
|
+
# TODO implement
|
|
646
|
+
return True
|
|
647
|
+
|
|
648
|
+
def label(self, *args, **kwargs):
|
|
649
|
+
""" """
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
class HyperTextLabelsValue(SpanSelectionOffsets):
|
|
653
|
+
htmllabels: List[str]
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
class HyperTextLabelsTag(ControlTag):
|
|
657
|
+
""" """
|
|
658
|
+
|
|
659
|
+
_label_attr_name: str = "htmllabels"
|
|
660
|
+
_value_class: Type[HyperTextLabelsValue] = HyperTextLabelsValue
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
class PairwiseValue(BaseModel):
|
|
664
|
+
selected: str
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
class PairwiseTag(ControlTag):
|
|
668
|
+
""" """
|
|
669
|
+
|
|
670
|
+
_value_class: Type[PairwiseValue] = PairwiseValue
|
|
671
|
+
|
|
672
|
+
def label(self, *args, **kwargs):
|
|
673
|
+
""" """
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
class ParagraphLabelsValue(SpanSelectionOffsets):
|
|
677
|
+
paragraphlabels: List[str]
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
class ParagraphLabelsTag(ControlTag):
|
|
681
|
+
""" """
|
|
682
|
+
|
|
683
|
+
_label_attr_name: str = "paragraphlabels"
|
|
684
|
+
_value_class: Type[ParagraphLabelsValue] = ParagraphLabelsValue
|
|
685
|
+
|
|
686
|
+
def label(self, *args, **kwargs):
|
|
687
|
+
""" """
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
class RankerTag(ControlTag):
|
|
691
|
+
""" """
|
|
692
|
+
|
|
693
|
+
def validate_value(self, value) -> bool:
|
|
694
|
+
""" """
|
|
695
|
+
# TODO
|
|
696
|
+
return True
|
|
697
|
+
|
|
698
|
+
def label(self, *args, **kwargs):
|
|
699
|
+
""" """
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
class RatingValue(BaseModel):
|
|
703
|
+
rating: int
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
class RatingTag(ControlTag):
|
|
707
|
+
""" """
|
|
708
|
+
|
|
709
|
+
_value_class: Type[RatingValue] = RatingValue
|
|
710
|
+
|
|
711
|
+
def label(self, *args, **kwargs):
|
|
712
|
+
""" """
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
class RelationsTag(ControlTag):
|
|
716
|
+
""" """
|
|
717
|
+
|
|
718
|
+
def validate_value(self, value) -> bool:
|
|
719
|
+
""" """
|
|
720
|
+
# TODO
|
|
721
|
+
return True
|
|
722
|
+
|
|
723
|
+
def label(self, *args, **kwargs):
|
|
724
|
+
""" """
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
class TaxonomyValue(BaseModel):
|
|
728
|
+
taxonomy: List[List[str]]
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
class TaxonomyTag(ControlTag):
|
|
732
|
+
""" """
|
|
733
|
+
|
|
734
|
+
_value_class: Type[TaxonomyValue] = TaxonomyValue
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
class TextAreaValue(BaseModel):
|
|
738
|
+
text: List[str]
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
class TextAreaTag(ControlTag):
|
|
742
|
+
""" """
|
|
743
|
+
|
|
744
|
+
_value_class: Type[TextAreaValue] = TextAreaValue
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
class TimeSeriesValue(SpanSelection):
|
|
748
|
+
instant: bool
|
|
749
|
+
timeserieslabels: List[str]
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
class TimeSeriesLabelsTag(ControlTag):
|
|
753
|
+
""" """
|
|
754
|
+
|
|
755
|
+
_label_attr_name: str = "timeserieslabels"
|
|
756
|
+
_value_class: Type[TimeSeriesValue] = TimeSeriesValue
|