label-studio-sdk 1.0.8__py3-none-any.whl → 1.0.10__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 label-studio-sdk might be problematic. Click here for more details.
- label_studio_sdk/__init__.py +20 -7
- label_studio_sdk/_extensions/label_studio_tools/core/utils/io.py +16 -4
- label_studio_sdk/_extensions/pager_ext.py +8 -0
- label_studio_sdk/actions/client.py +91 -40
- label_studio_sdk/actions/types/actions_create_request_filters.py +14 -24
- label_studio_sdk/actions/types/actions_create_request_filters_items_item.py +16 -26
- label_studio_sdk/actions/types/actions_create_request_filters_items_item_value.py +3 -1
- label_studio_sdk/actions/types/actions_create_request_selected_items.py +1 -2
- label_studio_sdk/actions/types/actions_create_request_selected_items_excluded.py +15 -25
- label_studio_sdk/actions/types/actions_create_request_selected_items_included.py +15 -25
- label_studio_sdk/annotations/__init__.py +2 -2
- label_studio_sdk/annotations/client.py +278 -104
- label_studio_sdk/annotations/types/__init__.py +2 -1
- label_studio_sdk/annotations/types/annotations_create_bulk_request_selected_items.py +34 -0
- label_studio_sdk/annotations/types/annotations_create_bulk_response_item.py +11 -21
- label_studio_sdk/base_client.py +46 -27
- label_studio_sdk/client.py +1 -0
- label_studio_sdk/comments/client.py +190 -44
- label_studio_sdk/converter/converter.py +56 -13
- label_studio_sdk/converter/imports/yolo.py +1 -1
- label_studio_sdk/converter/utils.py +3 -2
- label_studio_sdk/core/__init__.py +21 -4
- label_studio_sdk/core/client_wrapper.py +9 -10
- label_studio_sdk/core/file.py +37 -8
- label_studio_sdk/core/http_client.py +52 -28
- label_studio_sdk/core/jsonable_encoder.py +33 -31
- label_studio_sdk/core/pagination.py +5 -4
- label_studio_sdk/core/pydantic_utilities.py +272 -4
- label_studio_sdk/core/query_encoder.py +38 -13
- label_studio_sdk/core/request_options.py +3 -0
- label_studio_sdk/core/serialization.py +272 -0
- label_studio_sdk/errors/bad_request_error.py +2 -3
- label_studio_sdk/export_storage/azure/client.py +228 -58
- label_studio_sdk/export_storage/azure/types/azure_create_response.py +19 -29
- label_studio_sdk/export_storage/azure/types/azure_update_response.py +19 -29
- label_studio_sdk/export_storage/client.py +48 -18
- label_studio_sdk/export_storage/gcs/client.py +228 -58
- label_studio_sdk/export_storage/gcs/types/gcs_create_response.py +19 -29
- label_studio_sdk/export_storage/gcs/types/gcs_update_response.py +19 -29
- label_studio_sdk/export_storage/local/client.py +222 -56
- label_studio_sdk/export_storage/local/types/local_create_response.py +17 -27
- label_studio_sdk/export_storage/local/types/local_update_response.py +17 -27
- label_studio_sdk/export_storage/redis/client.py +228 -58
- label_studio_sdk/export_storage/redis/types/redis_create_response.py +20 -30
- label_studio_sdk/export_storage/redis/types/redis_update_response.py +20 -30
- label_studio_sdk/export_storage/s3/client.py +228 -58
- label_studio_sdk/export_storage/s3/types/s3create_response.py +27 -35
- label_studio_sdk/export_storage/s3/types/s3update_response.py +27 -35
- label_studio_sdk/export_storage/s3s/client.py +187 -43
- label_studio_sdk/export_storage/types/export_storage_list_types_response_item.py +11 -21
- label_studio_sdk/files/client.py +172 -56
- label_studio_sdk/import_storage/azure/client.py +223 -53
- label_studio_sdk/import_storage/azure/types/azure_create_response.py +22 -32
- label_studio_sdk/import_storage/azure/types/azure_update_response.py +22 -32
- label_studio_sdk/import_storage/client.py +48 -18
- label_studio_sdk/import_storage/gcs/client.py +223 -53
- label_studio_sdk/import_storage/gcs/types/gcs_create_response.py +22 -32
- label_studio_sdk/import_storage/gcs/types/gcs_update_response.py +22 -32
- label_studio_sdk/import_storage/local/client.py +223 -53
- label_studio_sdk/import_storage/local/types/local_create_response.py +17 -27
- label_studio_sdk/import_storage/local/types/local_update_response.py +17 -27
- label_studio_sdk/import_storage/redis/client.py +223 -53
- label_studio_sdk/import_storage/redis/types/redis_create_response.py +20 -30
- label_studio_sdk/import_storage/redis/types/redis_update_response.py +20 -30
- label_studio_sdk/import_storage/s3/client.py +223 -53
- label_studio_sdk/import_storage/s3/types/s3create_response.py +31 -39
- label_studio_sdk/import_storage/s3/types/s3update_response.py +31 -39
- label_studio_sdk/import_storage/s3s/client.py +222 -52
- label_studio_sdk/import_storage/types/import_storage_list_types_response_item.py +11 -21
- label_studio_sdk/label_interface/control_tags.py +1 -1
- label_studio_sdk/ml/client.py +280 -78
- label_studio_sdk/ml/types/ml_create_response.py +21 -31
- label_studio_sdk/ml/types/ml_update_response.py +21 -31
- label_studio_sdk/model_providers/client.py +173 -56
- label_studio_sdk/predictions/client.py +247 -101
- label_studio_sdk/projects/__init__.py +3 -0
- label_studio_sdk/projects/client.py +309 -115
- label_studio_sdk/projects/client_ext.py +16 -0
- label_studio_sdk/projects/exports/__init__.py +3 -0
- label_studio_sdk/projects/exports/client.py +447 -296
- label_studio_sdk/projects/exports/client_ext.py +134 -0
- label_studio_sdk/projects/exports/types/__init__.py +6 -0
- label_studio_sdk/projects/exports/types/exports_convert_response.py +24 -0
- label_studio_sdk/projects/exports/types/exports_list_formats_response_item.py +44 -0
- label_studio_sdk/projects/types/projects_create_response.py +29 -34
- label_studio_sdk/projects/types/projects_import_tasks_response.py +19 -29
- label_studio_sdk/projects/types/projects_list_response.py +11 -21
- label_studio_sdk/projects/types/projects_update_response.py +24 -34
- label_studio_sdk/prompts/client.py +309 -92
- label_studio_sdk/prompts/indicators/client.py +67 -23
- label_studio_sdk/prompts/runs/client.py +95 -40
- label_studio_sdk/prompts/types/prompts_batch_failed_predictions_request_failed_predictions_item.py +14 -24
- label_studio_sdk/prompts/types/prompts_batch_failed_predictions_response.py +11 -21
- label_studio_sdk/prompts/types/prompts_batch_predictions_request_results_item.py +26 -29
- label_studio_sdk/prompts/types/prompts_batch_predictions_response.py +11 -21
- label_studio_sdk/prompts/versions/client.py +277 -88
- label_studio_sdk/tasks/client.py +263 -90
- label_studio_sdk/tasks/types/tasks_list_response.py +15 -25
- label_studio_sdk/types/__init__.py +10 -6
- label_studio_sdk/types/annotation.py +29 -38
- label_studio_sdk/types/annotation_filter_options.py +14 -24
- label_studio_sdk/types/annotations_dm_field.py +30 -39
- label_studio_sdk/types/azure_blob_export_storage.py +28 -37
- label_studio_sdk/types/azure_blob_import_storage.py +28 -37
- label_studio_sdk/types/base_task.py +30 -39
- label_studio_sdk/types/base_task_updated_by.py +3 -1
- label_studio_sdk/types/base_user.py +14 -21
- label_studio_sdk/types/comment.py +12 -21
- label_studio_sdk/types/comment_created_by.py +1 -1
- label_studio_sdk/types/converted_format.py +12 -22
- label_studio_sdk/types/data_manager_task_serializer.py +31 -40
- label_studio_sdk/types/data_manager_task_serializer_annotators_item.py +1 -1
- label_studio_sdk/types/data_manager_task_serializer_drafts_item.py +13 -22
- label_studio_sdk/types/data_manager_task_serializer_predictions_item.py +15 -24
- label_studio_sdk/types/export.py +17 -26
- label_studio_sdk/types/export_format.py +25 -0
- label_studio_sdk/types/export_snapshot.py +45 -0
- label_studio_sdk/types/export_snapshot_status.py +5 -0
- label_studio_sdk/types/file_upload.py +11 -21
- label_studio_sdk/types/filter.py +16 -26
- label_studio_sdk/types/filter_group.py +12 -22
- label_studio_sdk/types/gcs_export_storage.py +28 -37
- label_studio_sdk/types/gcs_import_storage.py +28 -37
- label_studio_sdk/types/inference_run.py +14 -23
- label_studio_sdk/types/inference_run_cost_estimate.py +17 -27
- label_studio_sdk/types/inference_run_created_by.py +1 -1
- label_studio_sdk/types/inference_run_organization.py +1 -1
- label_studio_sdk/types/key_indicator_value.py +12 -22
- label_studio_sdk/types/key_indicators.py +0 -1
- label_studio_sdk/types/key_indicators_item.py +15 -25
- label_studio_sdk/types/key_indicators_item_additional_kpis_item.py +13 -23
- label_studio_sdk/types/key_indicators_item_extra_kpis_item.py +13 -23
- label_studio_sdk/types/local_files_export_storage.py +25 -34
- label_studio_sdk/types/local_files_import_storage.py +24 -33
- label_studio_sdk/types/ml_backend.py +23 -32
- label_studio_sdk/types/model_provider_connection.py +22 -31
- label_studio_sdk/types/model_provider_connection_created_by.py +1 -1
- label_studio_sdk/types/model_provider_connection_organization.py +1 -1
- label_studio_sdk/types/model_provider_connection_provider.py +3 -1
- label_studio_sdk/types/prediction.py +21 -30
- label_studio_sdk/types/project.py +48 -55
- label_studio_sdk/types/project_import.py +21 -30
- label_studio_sdk/types/project_label_config.py +12 -22
- label_studio_sdk/types/prompt.py +24 -32
- label_studio_sdk/types/prompt_associated_projects_item.py +6 -0
- label_studio_sdk/types/prompt_associated_projects_item_id.py +20 -0
- label_studio_sdk/types/prompt_created_by.py +1 -1
- label_studio_sdk/types/prompt_organization.py +1 -1
- label_studio_sdk/types/prompt_version.py +13 -22
- label_studio_sdk/types/prompt_version_created_by.py +1 -1
- label_studio_sdk/types/prompt_version_organization.py +1 -1
- label_studio_sdk/types/prompt_version_provider.py +3 -1
- label_studio_sdk/types/redis_export_storage.py +29 -38
- label_studio_sdk/types/redis_import_storage.py +28 -37
- label_studio_sdk/types/refined_prompt_response.py +19 -29
- label_studio_sdk/types/s3export_storage.py +36 -43
- label_studio_sdk/types/s3import_storage.py +37 -44
- label_studio_sdk/types/s3s_export_storage.py +26 -33
- label_studio_sdk/types/s3s_import_storage.py +35 -42
- label_studio_sdk/types/serialization_option.py +12 -22
- label_studio_sdk/types/serialization_options.py +18 -28
- label_studio_sdk/types/task.py +44 -47
- label_studio_sdk/types/task_annotators_item.py +1 -1
- label_studio_sdk/types/task_comment_authors_item.py +1 -1
- label_studio_sdk/types/task_filter_options.py +15 -25
- label_studio_sdk/types/user_simple.py +11 -21
- label_studio_sdk/types/view.py +16 -26
- label_studio_sdk/types/webhook.py +19 -28
- label_studio_sdk/types/webhook_serializer_for_update.py +19 -28
- label_studio_sdk/types/workspace.py +22 -31
- label_studio_sdk/users/client.py +257 -63
- label_studio_sdk/users/types/users_get_token_response.py +12 -22
- label_studio_sdk/users/types/users_reset_token_response.py +12 -22
- label_studio_sdk/version.py +0 -1
- label_studio_sdk/versions/__init__.py +5 -0
- label_studio_sdk/versions/client.py +112 -0
- label_studio_sdk/versions/types/__init__.py +6 -0
- label_studio_sdk/versions/types/versions_get_response.py +73 -0
- label_studio_sdk/versions/types/versions_get_response_edition.py +5 -0
- label_studio_sdk/views/client.py +219 -52
- label_studio_sdk/views/types/views_create_request_data.py +13 -23
- label_studio_sdk/views/types/views_create_request_data_filters.py +14 -24
- label_studio_sdk/views/types/views_create_request_data_filters_items_item.py +16 -26
- label_studio_sdk/views/types/views_create_request_data_filters_items_item_value.py +3 -1
- label_studio_sdk/views/types/views_update_request_data.py +13 -23
- label_studio_sdk/views/types/views_update_request_data_filters.py +14 -24
- label_studio_sdk/views/types/views_update_request_data_filters_items_item.py +16 -26
- label_studio_sdk/views/types/views_update_request_data_filters_items_item_value.py +3 -1
- label_studio_sdk/webhooks/client.py +191 -61
- label_studio_sdk/workspaces/client.py +164 -41
- label_studio_sdk/workspaces/members/client.py +109 -31
- label_studio_sdk/workspaces/members/types/members_create_response.py +12 -22
- label_studio_sdk/workspaces/members/types/members_list_response_item.py +12 -22
- {label_studio_sdk-1.0.8.dist-info → label_studio_sdk-1.0.10.dist-info}/METADATA +7 -5
- {label_studio_sdk-1.0.8.dist-info → label_studio_sdk-1.0.10.dist-info}/RECORD +197 -184
- {label_studio_sdk-1.0.8.dist-info → label_studio_sdk-1.0.10.dist-info}/WHEEL +1 -1
- label_studio_sdk/types/export_convert.py +0 -32
- label_studio_sdk/types/export_create.py +0 -54
- label_studio_sdk/types/export_create_status.py +0 -5
- {label_studio_sdk-1.0.8.dist-info → label_studio_sdk-1.0.10.dist-info}/LICENSE +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
3
|
import typing
|
|
4
|
+
from ..core.client_wrapper import SyncClientWrapper
|
|
5
|
+
from ..core.request_options import RequestOptions
|
|
6
|
+
from ..types.comment import Comment
|
|
7
|
+
from ..core.pydantic_utilities import parse_obj_as
|
|
4
8
|
from json.decoder import JSONDecodeError
|
|
5
|
-
|
|
6
9
|
from ..core.api_error import ApiError
|
|
7
|
-
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
|
|
8
10
|
from ..core.jsonable_encoder import jsonable_encoder
|
|
9
|
-
from ..core.
|
|
10
|
-
from ..core.request_options import RequestOptions
|
|
11
|
-
from ..types.comment import Comment
|
|
11
|
+
from ..core.client_wrapper import AsyncClientWrapper
|
|
12
12
|
|
|
13
13
|
# this is used as the default value for optional parameters
|
|
14
14
|
OMIT = typing.cast(typing.Any, ...)
|
|
@@ -27,6 +27,7 @@ class CommentsClient:
|
|
|
27
27
|
request_options: typing.Optional[RequestOptions] = None,
|
|
28
28
|
) -> typing.List[Comment]:
|
|
29
29
|
"""
|
|
30
|
+
|
|
30
31
|
Get a list of comments for a specific project.
|
|
31
32
|
|
|
32
33
|
Parameters
|
|
@@ -50,7 +51,7 @@ class CommentsClient:
|
|
|
50
51
|
|
|
51
52
|
Examples
|
|
52
53
|
--------
|
|
53
|
-
from label_studio_sdk
|
|
54
|
+
from label_studio_sdk import LabelStudio
|
|
54
55
|
|
|
55
56
|
client = LabelStudio(
|
|
56
57
|
api_key="YOUR_API_KEY",
|
|
@@ -60,12 +61,22 @@ class CommentsClient:
|
|
|
60
61
|
_response = self._client_wrapper.httpx_client.request(
|
|
61
62
|
"api/comments/",
|
|
62
63
|
method="GET",
|
|
63
|
-
params={
|
|
64
|
+
params={
|
|
65
|
+
"project": project,
|
|
66
|
+
"expand_created_by": expand_created_by,
|
|
67
|
+
"annotation": annotation,
|
|
68
|
+
},
|
|
64
69
|
request_options=request_options,
|
|
65
70
|
)
|
|
66
71
|
try:
|
|
67
72
|
if 200 <= _response.status_code < 300:
|
|
68
|
-
return
|
|
73
|
+
return typing.cast(
|
|
74
|
+
typing.List[Comment],
|
|
75
|
+
parse_obj_as(
|
|
76
|
+
type_=typing.List[Comment], # type: ignore
|
|
77
|
+
object_=_response.json(),
|
|
78
|
+
),
|
|
79
|
+
)
|
|
69
80
|
_response_json = _response.json()
|
|
70
81
|
except JSONDecodeError:
|
|
71
82
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -81,6 +92,7 @@ class CommentsClient:
|
|
|
81
92
|
request_options: typing.Optional[RequestOptions] = None,
|
|
82
93
|
) -> Comment:
|
|
83
94
|
"""
|
|
95
|
+
|
|
84
96
|
Create a new comment.
|
|
85
97
|
|
|
86
98
|
Parameters
|
|
@@ -103,7 +115,7 @@ class CommentsClient:
|
|
|
103
115
|
|
|
104
116
|
Examples
|
|
105
117
|
--------
|
|
106
|
-
from label_studio_sdk
|
|
118
|
+
from label_studio_sdk import LabelStudio
|
|
107
119
|
|
|
108
120
|
client = LabelStudio(
|
|
109
121
|
api_key="YOUR_API_KEY",
|
|
@@ -113,13 +125,27 @@ class CommentsClient:
|
|
|
113
125
|
_response = self._client_wrapper.httpx_client.request(
|
|
114
126
|
"api/comments/",
|
|
115
127
|
method="POST",
|
|
116
|
-
json={
|
|
128
|
+
json={
|
|
129
|
+
"annotation": annotation,
|
|
130
|
+
"project": project,
|
|
131
|
+
"text": text,
|
|
132
|
+
"is_resolved": is_resolved,
|
|
133
|
+
},
|
|
134
|
+
headers={
|
|
135
|
+
"content-type": "application/json",
|
|
136
|
+
},
|
|
117
137
|
request_options=request_options,
|
|
118
138
|
omit=OMIT,
|
|
119
139
|
)
|
|
120
140
|
try:
|
|
121
141
|
if 200 <= _response.status_code < 300:
|
|
122
|
-
return
|
|
142
|
+
return typing.cast(
|
|
143
|
+
Comment,
|
|
144
|
+
parse_obj_as(
|
|
145
|
+
type_=Comment, # type: ignore
|
|
146
|
+
object_=_response.json(),
|
|
147
|
+
),
|
|
148
|
+
)
|
|
123
149
|
_response_json = _response.json()
|
|
124
150
|
except JSONDecodeError:
|
|
125
151
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -127,6 +153,7 @@ class CommentsClient:
|
|
|
127
153
|
|
|
128
154
|
def get(self, id: int, *, request_options: typing.Optional[RequestOptions] = None) -> Comment:
|
|
129
155
|
"""
|
|
156
|
+
|
|
130
157
|
Get a specific comment.
|
|
131
158
|
|
|
132
159
|
Parameters
|
|
@@ -144,7 +171,7 @@ class CommentsClient:
|
|
|
144
171
|
|
|
145
172
|
Examples
|
|
146
173
|
--------
|
|
147
|
-
from label_studio_sdk
|
|
174
|
+
from label_studio_sdk import LabelStudio
|
|
148
175
|
|
|
149
176
|
client = LabelStudio(
|
|
150
177
|
api_key="YOUR_API_KEY",
|
|
@@ -154,11 +181,19 @@ class CommentsClient:
|
|
|
154
181
|
)
|
|
155
182
|
"""
|
|
156
183
|
_response = self._client_wrapper.httpx_client.request(
|
|
157
|
-
f"api/comments/{jsonable_encoder(id)}",
|
|
184
|
+
f"api/comments/{jsonable_encoder(id)}",
|
|
185
|
+
method="GET",
|
|
186
|
+
request_options=request_options,
|
|
158
187
|
)
|
|
159
188
|
try:
|
|
160
189
|
if 200 <= _response.status_code < 300:
|
|
161
|
-
return
|
|
190
|
+
return typing.cast(
|
|
191
|
+
Comment,
|
|
192
|
+
parse_obj_as(
|
|
193
|
+
type_=Comment, # type: ignore
|
|
194
|
+
object_=_response.json(),
|
|
195
|
+
),
|
|
196
|
+
)
|
|
162
197
|
_response_json = _response.json()
|
|
163
198
|
except JSONDecodeError:
|
|
164
199
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -166,6 +201,7 @@ class CommentsClient:
|
|
|
166
201
|
|
|
167
202
|
def delete(self, id: int, *, request_options: typing.Optional[RequestOptions] = None) -> None:
|
|
168
203
|
"""
|
|
204
|
+
|
|
169
205
|
Delete a specific comment.
|
|
170
206
|
|
|
171
207
|
Parameters
|
|
@@ -182,7 +218,7 @@ class CommentsClient:
|
|
|
182
218
|
|
|
183
219
|
Examples
|
|
184
220
|
--------
|
|
185
|
-
from label_studio_sdk
|
|
221
|
+
from label_studio_sdk import LabelStudio
|
|
186
222
|
|
|
187
223
|
client = LabelStudio(
|
|
188
224
|
api_key="YOUR_API_KEY",
|
|
@@ -192,7 +228,9 @@ class CommentsClient:
|
|
|
192
228
|
)
|
|
193
229
|
"""
|
|
194
230
|
_response = self._client_wrapper.httpx_client.request(
|
|
195
|
-
f"api/comments/{jsonable_encoder(id)}",
|
|
231
|
+
f"api/comments/{jsonable_encoder(id)}",
|
|
232
|
+
method="DELETE",
|
|
233
|
+
request_options=request_options,
|
|
196
234
|
)
|
|
197
235
|
try:
|
|
198
236
|
if 200 <= _response.status_code < 300:
|
|
@@ -213,6 +251,7 @@ class CommentsClient:
|
|
|
213
251
|
request_options: typing.Optional[RequestOptions] = None,
|
|
214
252
|
) -> Comment:
|
|
215
253
|
"""
|
|
254
|
+
|
|
216
255
|
Update a specific comment.
|
|
217
256
|
|
|
218
257
|
Parameters
|
|
@@ -238,7 +277,7 @@ class CommentsClient:
|
|
|
238
277
|
|
|
239
278
|
Examples
|
|
240
279
|
--------
|
|
241
|
-
from label_studio_sdk
|
|
280
|
+
from label_studio_sdk import LabelStudio
|
|
242
281
|
|
|
243
282
|
client = LabelStudio(
|
|
244
283
|
api_key="YOUR_API_KEY",
|
|
@@ -250,13 +289,27 @@ class CommentsClient:
|
|
|
250
289
|
_response = self._client_wrapper.httpx_client.request(
|
|
251
290
|
f"api/comments/{jsonable_encoder(id)}",
|
|
252
291
|
method="PATCH",
|
|
253
|
-
json={
|
|
292
|
+
json={
|
|
293
|
+
"annotation": annotation,
|
|
294
|
+
"project": project,
|
|
295
|
+
"text": text,
|
|
296
|
+
"is_resolved": is_resolved,
|
|
297
|
+
},
|
|
298
|
+
headers={
|
|
299
|
+
"content-type": "application/json",
|
|
300
|
+
},
|
|
254
301
|
request_options=request_options,
|
|
255
302
|
omit=OMIT,
|
|
256
303
|
)
|
|
257
304
|
try:
|
|
258
305
|
if 200 <= _response.status_code < 300:
|
|
259
|
-
return
|
|
306
|
+
return typing.cast(
|
|
307
|
+
Comment,
|
|
308
|
+
parse_obj_as(
|
|
309
|
+
type_=Comment, # type: ignore
|
|
310
|
+
object_=_response.json(),
|
|
311
|
+
),
|
|
312
|
+
)
|
|
260
313
|
_response_json = _response.json()
|
|
261
314
|
except JSONDecodeError:
|
|
262
315
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -276,6 +329,7 @@ class AsyncCommentsClient:
|
|
|
276
329
|
request_options: typing.Optional[RequestOptions] = None,
|
|
277
330
|
) -> typing.List[Comment]:
|
|
278
331
|
"""
|
|
332
|
+
|
|
279
333
|
Get a list of comments for a specific project.
|
|
280
334
|
|
|
281
335
|
Parameters
|
|
@@ -299,22 +353,40 @@ class AsyncCommentsClient:
|
|
|
299
353
|
|
|
300
354
|
Examples
|
|
301
355
|
--------
|
|
302
|
-
|
|
356
|
+
import asyncio
|
|
357
|
+
|
|
358
|
+
from label_studio_sdk import AsyncLabelStudio
|
|
303
359
|
|
|
304
360
|
client = AsyncLabelStudio(
|
|
305
361
|
api_key="YOUR_API_KEY",
|
|
306
362
|
)
|
|
307
|
-
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
async def main() -> None:
|
|
366
|
+
await client.comments.list()
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
asyncio.run(main())
|
|
308
370
|
"""
|
|
309
371
|
_response = await self._client_wrapper.httpx_client.request(
|
|
310
372
|
"api/comments/",
|
|
311
373
|
method="GET",
|
|
312
|
-
params={
|
|
374
|
+
params={
|
|
375
|
+
"project": project,
|
|
376
|
+
"expand_created_by": expand_created_by,
|
|
377
|
+
"annotation": annotation,
|
|
378
|
+
},
|
|
313
379
|
request_options=request_options,
|
|
314
380
|
)
|
|
315
381
|
try:
|
|
316
382
|
if 200 <= _response.status_code < 300:
|
|
317
|
-
return
|
|
383
|
+
return typing.cast(
|
|
384
|
+
typing.List[Comment],
|
|
385
|
+
parse_obj_as(
|
|
386
|
+
type_=typing.List[Comment], # type: ignore
|
|
387
|
+
object_=_response.json(),
|
|
388
|
+
),
|
|
389
|
+
)
|
|
318
390
|
_response_json = _response.json()
|
|
319
391
|
except JSONDecodeError:
|
|
320
392
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -330,6 +402,7 @@ class AsyncCommentsClient:
|
|
|
330
402
|
request_options: typing.Optional[RequestOptions] = None,
|
|
331
403
|
) -> Comment:
|
|
332
404
|
"""
|
|
405
|
+
|
|
333
406
|
Create a new comment.
|
|
334
407
|
|
|
335
408
|
Parameters
|
|
@@ -352,23 +425,45 @@ class AsyncCommentsClient:
|
|
|
352
425
|
|
|
353
426
|
Examples
|
|
354
427
|
--------
|
|
355
|
-
|
|
428
|
+
import asyncio
|
|
429
|
+
|
|
430
|
+
from label_studio_sdk import AsyncLabelStudio
|
|
356
431
|
|
|
357
432
|
client = AsyncLabelStudio(
|
|
358
433
|
api_key="YOUR_API_KEY",
|
|
359
434
|
)
|
|
360
|
-
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
async def main() -> None:
|
|
438
|
+
await client.comments.create()
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
asyncio.run(main())
|
|
361
442
|
"""
|
|
362
443
|
_response = await self._client_wrapper.httpx_client.request(
|
|
363
444
|
"api/comments/",
|
|
364
445
|
method="POST",
|
|
365
|
-
json={
|
|
446
|
+
json={
|
|
447
|
+
"annotation": annotation,
|
|
448
|
+
"project": project,
|
|
449
|
+
"text": text,
|
|
450
|
+
"is_resolved": is_resolved,
|
|
451
|
+
},
|
|
452
|
+
headers={
|
|
453
|
+
"content-type": "application/json",
|
|
454
|
+
},
|
|
366
455
|
request_options=request_options,
|
|
367
456
|
omit=OMIT,
|
|
368
457
|
)
|
|
369
458
|
try:
|
|
370
459
|
if 200 <= _response.status_code < 300:
|
|
371
|
-
return
|
|
460
|
+
return typing.cast(
|
|
461
|
+
Comment,
|
|
462
|
+
parse_obj_as(
|
|
463
|
+
type_=Comment, # type: ignore
|
|
464
|
+
object_=_response.json(),
|
|
465
|
+
),
|
|
466
|
+
)
|
|
372
467
|
_response_json = _response.json()
|
|
373
468
|
except JSONDecodeError:
|
|
374
469
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -376,6 +471,7 @@ class AsyncCommentsClient:
|
|
|
376
471
|
|
|
377
472
|
async def get(self, id: int, *, request_options: typing.Optional[RequestOptions] = None) -> Comment:
|
|
378
473
|
"""
|
|
474
|
+
|
|
379
475
|
Get a specific comment.
|
|
380
476
|
|
|
381
477
|
Parameters
|
|
@@ -393,21 +489,37 @@ class AsyncCommentsClient:
|
|
|
393
489
|
|
|
394
490
|
Examples
|
|
395
491
|
--------
|
|
396
|
-
|
|
492
|
+
import asyncio
|
|
493
|
+
|
|
494
|
+
from label_studio_sdk import AsyncLabelStudio
|
|
397
495
|
|
|
398
496
|
client = AsyncLabelStudio(
|
|
399
497
|
api_key="YOUR_API_KEY",
|
|
400
498
|
)
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
)
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
async def main() -> None:
|
|
502
|
+
await client.comments.get(
|
|
503
|
+
id=1,
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
asyncio.run(main())
|
|
404
508
|
"""
|
|
405
509
|
_response = await self._client_wrapper.httpx_client.request(
|
|
406
|
-
f"api/comments/{jsonable_encoder(id)}",
|
|
510
|
+
f"api/comments/{jsonable_encoder(id)}",
|
|
511
|
+
method="GET",
|
|
512
|
+
request_options=request_options,
|
|
407
513
|
)
|
|
408
514
|
try:
|
|
409
515
|
if 200 <= _response.status_code < 300:
|
|
410
|
-
return
|
|
516
|
+
return typing.cast(
|
|
517
|
+
Comment,
|
|
518
|
+
parse_obj_as(
|
|
519
|
+
type_=Comment, # type: ignore
|
|
520
|
+
object_=_response.json(),
|
|
521
|
+
),
|
|
522
|
+
)
|
|
411
523
|
_response_json = _response.json()
|
|
412
524
|
except JSONDecodeError:
|
|
413
525
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -415,6 +527,7 @@ class AsyncCommentsClient:
|
|
|
415
527
|
|
|
416
528
|
async def delete(self, id: int, *, request_options: typing.Optional[RequestOptions] = None) -> None:
|
|
417
529
|
"""
|
|
530
|
+
|
|
418
531
|
Delete a specific comment.
|
|
419
532
|
|
|
420
533
|
Parameters
|
|
@@ -431,17 +544,27 @@ class AsyncCommentsClient:
|
|
|
431
544
|
|
|
432
545
|
Examples
|
|
433
546
|
--------
|
|
434
|
-
|
|
547
|
+
import asyncio
|
|
548
|
+
|
|
549
|
+
from label_studio_sdk import AsyncLabelStudio
|
|
435
550
|
|
|
436
551
|
client = AsyncLabelStudio(
|
|
437
552
|
api_key="YOUR_API_KEY",
|
|
438
553
|
)
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
)
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
async def main() -> None:
|
|
557
|
+
await client.comments.delete(
|
|
558
|
+
id=1,
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
asyncio.run(main())
|
|
442
563
|
"""
|
|
443
564
|
_response = await self._client_wrapper.httpx_client.request(
|
|
444
|
-
f"api/comments/{jsonable_encoder(id)}",
|
|
565
|
+
f"api/comments/{jsonable_encoder(id)}",
|
|
566
|
+
method="DELETE",
|
|
567
|
+
request_options=request_options,
|
|
445
568
|
)
|
|
446
569
|
try:
|
|
447
570
|
if 200 <= _response.status_code < 300:
|
|
@@ -462,6 +585,7 @@ class AsyncCommentsClient:
|
|
|
462
585
|
request_options: typing.Optional[RequestOptions] = None,
|
|
463
586
|
) -> Comment:
|
|
464
587
|
"""
|
|
588
|
+
|
|
465
589
|
Update a specific comment.
|
|
466
590
|
|
|
467
591
|
Parameters
|
|
@@ -487,25 +611,47 @@ class AsyncCommentsClient:
|
|
|
487
611
|
|
|
488
612
|
Examples
|
|
489
613
|
--------
|
|
490
|
-
|
|
614
|
+
import asyncio
|
|
615
|
+
|
|
616
|
+
from label_studio_sdk import AsyncLabelStudio
|
|
491
617
|
|
|
492
618
|
client = AsyncLabelStudio(
|
|
493
619
|
api_key="YOUR_API_KEY",
|
|
494
620
|
)
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
)
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
async def main() -> None:
|
|
624
|
+
await client.comments.update(
|
|
625
|
+
id=1,
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
asyncio.run(main())
|
|
498
630
|
"""
|
|
499
631
|
_response = await self._client_wrapper.httpx_client.request(
|
|
500
632
|
f"api/comments/{jsonable_encoder(id)}",
|
|
501
633
|
method="PATCH",
|
|
502
|
-
json={
|
|
634
|
+
json={
|
|
635
|
+
"annotation": annotation,
|
|
636
|
+
"project": project,
|
|
637
|
+
"text": text,
|
|
638
|
+
"is_resolved": is_resolved,
|
|
639
|
+
},
|
|
640
|
+
headers={
|
|
641
|
+
"content-type": "application/json",
|
|
642
|
+
},
|
|
503
643
|
request_options=request_options,
|
|
504
644
|
omit=OMIT,
|
|
505
645
|
)
|
|
506
646
|
try:
|
|
507
647
|
if 200 <= _response.status_code < 300:
|
|
508
|
-
return
|
|
648
|
+
return typing.cast(
|
|
649
|
+
Comment,
|
|
650
|
+
parse_obj_as(
|
|
651
|
+
type_=Comment, # type: ignore
|
|
652
|
+
object_=_response.json(),
|
|
653
|
+
),
|
|
654
|
+
)
|
|
509
655
|
_response_json = _response.json()
|
|
510
656
|
except JSONDecodeError:
|
|
511
657
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
@@ -33,6 +33,7 @@ from label_studio_sdk.converter.utils import (
|
|
|
33
33
|
convert_annotation_to_yolo,
|
|
34
34
|
convert_annotation_to_yolo_obb,
|
|
35
35
|
)
|
|
36
|
+
from label_studio_sdk._extensions.label_studio_tools.core.utils.io import get_local_path
|
|
36
37
|
|
|
37
38
|
logger = logging.getLogger(__name__)
|
|
38
39
|
|
|
@@ -55,6 +56,9 @@ class Format(Enum):
|
|
|
55
56
|
YOLO = 11
|
|
56
57
|
YOLO_OBB = 12
|
|
57
58
|
CSV_OLD = 13
|
|
59
|
+
YOLO_WITH_IMAGES = 14
|
|
60
|
+
COCO_WITH_IMAGES = 15
|
|
61
|
+
YOLO_OBB_WITH_IMAGES = 16
|
|
58
62
|
|
|
59
63
|
def __str__(self):
|
|
60
64
|
return self.name
|
|
@@ -106,6 +110,12 @@ class Converter(object):
|
|
|
106
110
|
"link": "https://labelstud.io/guide/export.html#COCO",
|
|
107
111
|
"tags": ["image segmentation", "object detection"],
|
|
108
112
|
},
|
|
113
|
+
Format.COCO_WITH_IMAGES: {
|
|
114
|
+
"title": "COCO with Images",
|
|
115
|
+
"description": "COCO format with images downloaded.",
|
|
116
|
+
"link": "https://labelstud.io/guide/export.html#COCO",
|
|
117
|
+
"tags": ["image segmentation", "object detection"],
|
|
118
|
+
},
|
|
109
119
|
Format.VOC: {
|
|
110
120
|
"title": "Pascal VOC XML",
|
|
111
121
|
"description": "Popular XML format used for object detection and polygon image segmentation tasks.",
|
|
@@ -119,6 +129,12 @@ class Converter(object):
|
|
|
119
129
|
"link": "https://labelstud.io/guide/export.html#YOLO",
|
|
120
130
|
"tags": ["image segmentation", "object detection"],
|
|
121
131
|
},
|
|
132
|
+
Format.YOLO_WITH_IMAGES: {
|
|
133
|
+
"title": "YOLO with Images",
|
|
134
|
+
"description": "YOLO format with images downloaded.",
|
|
135
|
+
"link": "https://labelstud.io/guide/export.html#YOLO",
|
|
136
|
+
"tags": ["image segmentation", "object detection"],
|
|
137
|
+
},
|
|
122
138
|
Format.YOLO_OBB: {
|
|
123
139
|
"title": "YOLOv8 OBB",
|
|
124
140
|
"description": "Popular TXT format is created for each image file. Each txt file contains annotations for "
|
|
@@ -127,6 +143,12 @@ class Converter(object):
|
|
|
127
143
|
"link": "https://labelstud.io/guide/export.html#YOLO",
|
|
128
144
|
"tags": ["image segmentation", "object detection"],
|
|
129
145
|
},
|
|
146
|
+
Format.YOLO_OBB_WITH_IMAGES: {
|
|
147
|
+
"title": "YOLOv8 OBB with Images",
|
|
148
|
+
"description": "YOLOv8 OBB format with images downloaded.",
|
|
149
|
+
"link": "https://labelstud.io/guide/export.html#YOLO",
|
|
150
|
+
"tags": ["image segmentation", "object detection"],
|
|
151
|
+
},
|
|
130
152
|
Format.BRUSH_TO_NUMPY: {
|
|
131
153
|
"title": "Brush labels to NumPy",
|
|
132
154
|
"description": "Export your brush labels as NumPy 2d arrays. Each label outputs as one image.",
|
|
@@ -158,6 +180,8 @@ class Converter(object):
|
|
|
158
180
|
output_tags=None,
|
|
159
181
|
upload_dir=None,
|
|
160
182
|
download_resources=True,
|
|
183
|
+
access_token=None,
|
|
184
|
+
hostname=None,
|
|
161
185
|
):
|
|
162
186
|
"""Initialize Label Studio Converter for Exports
|
|
163
187
|
|
|
@@ -171,6 +195,8 @@ class Converter(object):
|
|
|
171
195
|
self.upload_dir = upload_dir
|
|
172
196
|
self.download_resources = download_resources
|
|
173
197
|
self._schema = None
|
|
198
|
+
self.access_token = access_token
|
|
199
|
+
self.hostname = hostname
|
|
174
200
|
|
|
175
201
|
if isinstance(config, dict):
|
|
176
202
|
self._schema = config
|
|
@@ -216,21 +242,23 @@ class Converter(object):
|
|
|
216
242
|
)
|
|
217
243
|
elif format == Format.CONLL2003:
|
|
218
244
|
self.convert_to_conll2003(input_data, output_data, is_dir=is_dir)
|
|
219
|
-
elif format
|
|
245
|
+
elif format in [Format.COCO, Format.COCO_WITH_IMAGES]:
|
|
220
246
|
image_dir = kwargs.get("image_dir")
|
|
247
|
+
self.download_resources = format == Format.COCO_WITH_IMAGES
|
|
221
248
|
self.convert_to_coco(
|
|
222
249
|
input_data, output_data, output_image_dir=image_dir, is_dir=is_dir
|
|
223
250
|
)
|
|
224
|
-
elif format
|
|
251
|
+
elif format in [Format.YOLO, Format.YOLO_OBB, Format.YOLO_OBB_WITH_IMAGES, Format.YOLO_WITH_IMAGES]:
|
|
225
252
|
image_dir = kwargs.get("image_dir")
|
|
226
253
|
label_dir = kwargs.get("label_dir")
|
|
254
|
+
self.download_resources = format in [Format.YOLO_WITH_IMAGES, Format.YOLO_OBB_WITH_IMAGES]
|
|
227
255
|
self.convert_to_yolo(
|
|
228
256
|
input_data,
|
|
229
257
|
output_data,
|
|
230
258
|
output_image_dir=image_dir,
|
|
231
259
|
output_label_dir=label_dir,
|
|
232
260
|
is_dir=is_dir,
|
|
233
|
-
is_obb=(format
|
|
261
|
+
is_obb=(format in [Format.YOLO_OBB, Format.YOLO_OBB_WITH_IMAGES]),
|
|
234
262
|
)
|
|
235
263
|
elif format == Format.VOC:
|
|
236
264
|
image_dir = kwargs.get("image_dir")
|
|
@@ -334,7 +362,9 @@ class Converter(object):
|
|
|
334
362
|
and "Labels" in output_tag_types
|
|
335
363
|
):
|
|
336
364
|
all_formats.remove(Format.COCO.name)
|
|
365
|
+
all_formats.remove(Format.COCO_WITH_IMAGES.name)
|
|
337
366
|
all_formats.remove(Format.YOLO.name)
|
|
367
|
+
all_formats.remove(Format.YOLO_WITH_IMAGES.name)
|
|
338
368
|
if not (
|
|
339
369
|
"Image" in input_tag_types
|
|
340
370
|
and (
|
|
@@ -353,6 +383,7 @@ class Converter(object):
|
|
|
353
383
|
all_formats.remove(Format.ASR_MANIFEST.name)
|
|
354
384
|
if is_mig or ('Video' in input_tag_types and 'TimelineLabels' in output_tag_types):
|
|
355
385
|
all_formats.remove(Format.YOLO_OBB.name)
|
|
386
|
+
all_formats.remove(Format.YOLO_OBB_WITH_IMAGES.name)
|
|
356
387
|
|
|
357
388
|
return all_formats
|
|
358
389
|
|
|
@@ -593,20 +624,25 @@ class Converter(object):
|
|
|
593
624
|
)
|
|
594
625
|
for item_idx, item in enumerate(item_iterator):
|
|
595
626
|
image_path = item["input"][data_key]
|
|
627
|
+
task_id = item["id"]
|
|
596
628
|
image_id = len(images)
|
|
597
629
|
width = None
|
|
598
630
|
height = None
|
|
599
631
|
# download all images of the dataset, including the ones without annotations
|
|
600
632
|
if not os.path.exists(image_path):
|
|
601
633
|
try:
|
|
602
|
-
image_path =
|
|
603
|
-
image_path,
|
|
604
|
-
|
|
634
|
+
image_path = get_local_path(
|
|
635
|
+
url=image_path,
|
|
636
|
+
hostname=self.hostname,
|
|
605
637
|
project_dir=self.project_dir,
|
|
606
|
-
|
|
607
|
-
|
|
638
|
+
image_dir=self.upload_dir,
|
|
639
|
+
cache_dir=output_image_dir,
|
|
608
640
|
download_resources=self.download_resources,
|
|
641
|
+
access_token=self.access_token,
|
|
642
|
+
task_id=task_id,
|
|
609
643
|
)
|
|
644
|
+
# make path relative to output_image_dir
|
|
645
|
+
image_path = os.path.relpath(image_path, output_dir)
|
|
610
646
|
except:
|
|
611
647
|
logger.info(
|
|
612
648
|
"Unable to download {image_path}. The image of {item} will be skipped".format(
|
|
@@ -801,19 +837,24 @@ class Converter(object):
|
|
|
801
837
|
image_paths = [image_paths] if isinstance(image_paths, str) else image_paths
|
|
802
838
|
# download image(s)
|
|
803
839
|
image_path = None
|
|
840
|
+
task_id = item["id"]
|
|
804
841
|
# TODO: for multi-page annotation, this code won't produce correct relationships between page and annotated shapes
|
|
805
842
|
# fixing the issue in RND-84
|
|
806
843
|
for image_path in reversed(image_paths):
|
|
807
844
|
if not os.path.exists(image_path):
|
|
808
845
|
try:
|
|
809
|
-
image_path =
|
|
810
|
-
image_path,
|
|
811
|
-
|
|
846
|
+
image_path = get_local_path(
|
|
847
|
+
url=image_path,
|
|
848
|
+
hostname=self.hostname,
|
|
812
849
|
project_dir=self.project_dir,
|
|
813
|
-
|
|
814
|
-
|
|
850
|
+
image_dir=self.upload_dir,
|
|
851
|
+
cache_dir=output_image_dir,
|
|
815
852
|
download_resources=self.download_resources,
|
|
853
|
+
access_token=self.access_token,
|
|
854
|
+
task_id=task_id,
|
|
816
855
|
)
|
|
856
|
+
# make path relative to output_image_dir
|
|
857
|
+
image_path = os.path.relpath(image_path, output_dir)
|
|
817
858
|
except:
|
|
818
859
|
logger.info(
|
|
819
860
|
"Unable to download {image_path}. The item {item} will be skipped".format(
|
|
@@ -920,6 +961,8 @@ class Converter(object):
|
|
|
920
961
|
annotations.append([category_id, x, y, w, h])
|
|
921
962
|
|
|
922
963
|
elif "polygonlabels" in label or "polygon" in label:
|
|
964
|
+
if not ('points' in label):
|
|
965
|
+
continue
|
|
923
966
|
points_abs = [(x / 100, y / 100) for x, y in label["points"]]
|
|
924
967
|
annotations.append(
|
|
925
968
|
[category_id]
|