label-studio-sdk 1.0.7__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.

Files changed (206) hide show
  1. label_studio_sdk/__init__.py +26 -7
  2. label_studio_sdk/_extensions/label_studio_tools/core/label_config.py +13 -4
  3. label_studio_sdk/_extensions/label_studio_tools/core/utils/io.py +16 -4
  4. label_studio_sdk/_extensions/label_studio_tools/core/utils/json_schema.py +86 -0
  5. label_studio_sdk/_extensions/pager_ext.py +8 -0
  6. label_studio_sdk/_legacy/schema/label_config_schema.json +42 -11
  7. label_studio_sdk/actions/client.py +91 -40
  8. label_studio_sdk/actions/types/actions_create_request_filters.py +14 -24
  9. label_studio_sdk/actions/types/actions_create_request_filters_items_item.py +16 -26
  10. label_studio_sdk/actions/types/actions_create_request_filters_items_item_value.py +3 -1
  11. label_studio_sdk/actions/types/actions_create_request_selected_items.py +1 -2
  12. label_studio_sdk/actions/types/actions_create_request_selected_items_excluded.py +15 -25
  13. label_studio_sdk/actions/types/actions_create_request_selected_items_included.py +15 -25
  14. label_studio_sdk/annotations/__init__.py +2 -2
  15. label_studio_sdk/annotations/client.py +278 -104
  16. label_studio_sdk/annotations/types/__init__.py +2 -1
  17. label_studio_sdk/annotations/types/annotations_create_bulk_request_selected_items.py +34 -0
  18. label_studio_sdk/annotations/types/annotations_create_bulk_response_item.py +11 -21
  19. label_studio_sdk/base_client.py +46 -27
  20. label_studio_sdk/client.py +1 -0
  21. label_studio_sdk/comments/client.py +190 -44
  22. label_studio_sdk/converter/converter.py +66 -18
  23. label_studio_sdk/converter/imports/yolo.py +1 -1
  24. label_studio_sdk/converter/utils.py +3 -2
  25. label_studio_sdk/core/__init__.py +21 -4
  26. label_studio_sdk/core/client_wrapper.py +9 -10
  27. label_studio_sdk/core/file.py +37 -8
  28. label_studio_sdk/core/http_client.py +52 -28
  29. label_studio_sdk/core/jsonable_encoder.py +33 -31
  30. label_studio_sdk/core/pagination.py +5 -4
  31. label_studio_sdk/core/pydantic_utilities.py +272 -4
  32. label_studio_sdk/core/query_encoder.py +38 -13
  33. label_studio_sdk/core/request_options.py +3 -0
  34. label_studio_sdk/core/serialization.py +272 -0
  35. label_studio_sdk/errors/bad_request_error.py +2 -3
  36. label_studio_sdk/export_storage/azure/client.py +228 -58
  37. label_studio_sdk/export_storage/azure/types/azure_create_response.py +19 -29
  38. label_studio_sdk/export_storage/azure/types/azure_update_response.py +19 -29
  39. label_studio_sdk/export_storage/client.py +48 -18
  40. label_studio_sdk/export_storage/gcs/client.py +228 -58
  41. label_studio_sdk/export_storage/gcs/types/gcs_create_response.py +19 -29
  42. label_studio_sdk/export_storage/gcs/types/gcs_update_response.py +19 -29
  43. label_studio_sdk/export_storage/local/client.py +222 -56
  44. label_studio_sdk/export_storage/local/types/local_create_response.py +17 -27
  45. label_studio_sdk/export_storage/local/types/local_update_response.py +17 -27
  46. label_studio_sdk/export_storage/redis/client.py +228 -58
  47. label_studio_sdk/export_storage/redis/types/redis_create_response.py +20 -30
  48. label_studio_sdk/export_storage/redis/types/redis_update_response.py +20 -30
  49. label_studio_sdk/export_storage/s3/client.py +228 -58
  50. label_studio_sdk/export_storage/s3/types/s3create_response.py +27 -35
  51. label_studio_sdk/export_storage/s3/types/s3update_response.py +27 -35
  52. label_studio_sdk/export_storage/s3s/client.py +187 -43
  53. label_studio_sdk/export_storage/types/export_storage_list_types_response_item.py +11 -21
  54. label_studio_sdk/files/client.py +172 -56
  55. label_studio_sdk/import_storage/azure/client.py +223 -53
  56. label_studio_sdk/import_storage/azure/types/azure_create_response.py +22 -32
  57. label_studio_sdk/import_storage/azure/types/azure_update_response.py +22 -32
  58. label_studio_sdk/import_storage/client.py +48 -18
  59. label_studio_sdk/import_storage/gcs/client.py +223 -53
  60. label_studio_sdk/import_storage/gcs/types/gcs_create_response.py +22 -32
  61. label_studio_sdk/import_storage/gcs/types/gcs_update_response.py +22 -32
  62. label_studio_sdk/import_storage/local/client.py +223 -53
  63. label_studio_sdk/import_storage/local/types/local_create_response.py +17 -27
  64. label_studio_sdk/import_storage/local/types/local_update_response.py +17 -27
  65. label_studio_sdk/import_storage/redis/client.py +223 -53
  66. label_studio_sdk/import_storage/redis/types/redis_create_response.py +20 -30
  67. label_studio_sdk/import_storage/redis/types/redis_update_response.py +20 -30
  68. label_studio_sdk/import_storage/s3/client.py +223 -53
  69. label_studio_sdk/import_storage/s3/types/s3create_response.py +31 -39
  70. label_studio_sdk/import_storage/s3/types/s3update_response.py +31 -39
  71. label_studio_sdk/import_storage/s3s/client.py +222 -52
  72. label_studio_sdk/import_storage/types/import_storage_list_types_response_item.py +11 -21
  73. label_studio_sdk/label_interface/control_tags.py +205 -10
  74. label_studio_sdk/label_interface/interface.py +80 -6
  75. label_studio_sdk/label_interface/region.py +1 -10
  76. label_studio_sdk/ml/client.py +280 -78
  77. label_studio_sdk/ml/types/ml_create_response.py +21 -31
  78. label_studio_sdk/ml/types/ml_update_response.py +21 -31
  79. label_studio_sdk/model_providers/client.py +656 -21
  80. label_studio_sdk/predictions/client.py +247 -101
  81. label_studio_sdk/projects/__init__.py +3 -0
  82. label_studio_sdk/projects/client.py +309 -115
  83. label_studio_sdk/projects/client_ext.py +16 -0
  84. label_studio_sdk/projects/exports/__init__.py +3 -0
  85. label_studio_sdk/projects/exports/client.py +447 -296
  86. label_studio_sdk/projects/exports/client_ext.py +134 -0
  87. label_studio_sdk/projects/exports/types/__init__.py +6 -0
  88. label_studio_sdk/projects/exports/types/exports_convert_response.py +24 -0
  89. label_studio_sdk/projects/exports/types/exports_list_formats_response_item.py +44 -0
  90. label_studio_sdk/projects/types/projects_create_response.py +29 -34
  91. label_studio_sdk/projects/types/projects_import_tasks_response.py +19 -29
  92. label_studio_sdk/projects/types/projects_list_response.py +11 -21
  93. label_studio_sdk/projects/types/projects_update_response.py +24 -34
  94. label_studio_sdk/prompts/client.py +309 -92
  95. label_studio_sdk/prompts/indicators/client.py +67 -23
  96. label_studio_sdk/prompts/runs/client.py +95 -40
  97. label_studio_sdk/prompts/types/prompts_batch_failed_predictions_request_failed_predictions_item.py +14 -24
  98. label_studio_sdk/prompts/types/prompts_batch_failed_predictions_response.py +11 -21
  99. label_studio_sdk/prompts/types/prompts_batch_predictions_request_results_item.py +26 -29
  100. label_studio_sdk/prompts/types/prompts_batch_predictions_response.py +11 -21
  101. label_studio_sdk/prompts/versions/client.py +389 -75
  102. label_studio_sdk/tasks/client.py +263 -90
  103. label_studio_sdk/tasks/types/tasks_list_response.py +15 -25
  104. label_studio_sdk/types/__init__.py +16 -6
  105. label_studio_sdk/types/annotation.py +29 -38
  106. label_studio_sdk/types/annotation_filter_options.py +14 -24
  107. label_studio_sdk/types/annotations_dm_field.py +30 -39
  108. label_studio_sdk/types/azure_blob_export_storage.py +28 -37
  109. label_studio_sdk/types/azure_blob_import_storage.py +28 -37
  110. label_studio_sdk/types/base_task.py +30 -39
  111. label_studio_sdk/types/base_task_updated_by.py +3 -1
  112. label_studio_sdk/types/base_user.py +14 -21
  113. label_studio_sdk/types/comment.py +12 -21
  114. label_studio_sdk/types/comment_created_by.py +1 -1
  115. label_studio_sdk/types/converted_format.py +12 -22
  116. label_studio_sdk/types/data_manager_task_serializer.py +31 -40
  117. label_studio_sdk/types/data_manager_task_serializer_annotators_item.py +1 -1
  118. label_studio_sdk/types/data_manager_task_serializer_drafts_item.py +13 -22
  119. label_studio_sdk/types/data_manager_task_serializer_predictions_item.py +15 -24
  120. label_studio_sdk/types/export.py +17 -26
  121. label_studio_sdk/types/export_format.py +25 -0
  122. label_studio_sdk/types/export_snapshot.py +45 -0
  123. label_studio_sdk/types/export_snapshot_status.py +5 -0
  124. label_studio_sdk/types/file_upload.py +11 -21
  125. label_studio_sdk/types/filter.py +16 -26
  126. label_studio_sdk/types/filter_group.py +12 -22
  127. label_studio_sdk/types/gcs_export_storage.py +28 -37
  128. label_studio_sdk/types/gcs_import_storage.py +28 -37
  129. label_studio_sdk/types/inference_run.py +14 -23
  130. label_studio_sdk/types/inference_run_cost_estimate.py +47 -0
  131. label_studio_sdk/types/inference_run_created_by.py +1 -1
  132. label_studio_sdk/types/inference_run_organization.py +1 -1
  133. label_studio_sdk/types/key_indicator_value.py +12 -22
  134. label_studio_sdk/types/key_indicators.py +0 -1
  135. label_studio_sdk/types/key_indicators_item.py +15 -25
  136. label_studio_sdk/types/key_indicators_item_additional_kpis_item.py +13 -23
  137. label_studio_sdk/types/key_indicators_item_extra_kpis_item.py +13 -23
  138. label_studio_sdk/types/local_files_export_storage.py +25 -34
  139. label_studio_sdk/types/local_files_import_storage.py +24 -33
  140. label_studio_sdk/types/ml_backend.py +23 -32
  141. label_studio_sdk/types/model_provider_connection.py +47 -26
  142. label_studio_sdk/types/model_provider_connection_budget_reset_period.py +5 -0
  143. label_studio_sdk/types/model_provider_connection_created_by.py +1 -1
  144. label_studio_sdk/types/model_provider_connection_organization.py +1 -1
  145. label_studio_sdk/types/model_provider_connection_provider.py +3 -1
  146. label_studio_sdk/types/prediction.py +21 -30
  147. label_studio_sdk/types/project.py +48 -55
  148. label_studio_sdk/types/project_import.py +21 -30
  149. label_studio_sdk/types/project_label_config.py +12 -22
  150. label_studio_sdk/types/prompt.py +24 -32
  151. label_studio_sdk/types/prompt_associated_projects_item.py +6 -0
  152. label_studio_sdk/types/prompt_associated_projects_item_id.py +20 -0
  153. label_studio_sdk/types/prompt_created_by.py +1 -1
  154. label_studio_sdk/types/prompt_organization.py +1 -1
  155. label_studio_sdk/types/prompt_version.py +13 -22
  156. label_studio_sdk/types/prompt_version_created_by.py +1 -1
  157. label_studio_sdk/types/prompt_version_organization.py +1 -1
  158. label_studio_sdk/types/prompt_version_provider.py +3 -1
  159. label_studio_sdk/types/redis_export_storage.py +29 -38
  160. label_studio_sdk/types/redis_import_storage.py +28 -37
  161. label_studio_sdk/types/refined_prompt_response.py +19 -29
  162. label_studio_sdk/types/s3export_storage.py +36 -43
  163. label_studio_sdk/types/s3import_storage.py +37 -44
  164. label_studio_sdk/types/s3s_export_storage.py +26 -33
  165. label_studio_sdk/types/s3s_import_storage.py +35 -42
  166. label_studio_sdk/types/serialization_option.py +12 -22
  167. label_studio_sdk/types/serialization_options.py +18 -28
  168. label_studio_sdk/types/task.py +46 -48
  169. label_studio_sdk/types/task_annotators_item.py +1 -1
  170. label_studio_sdk/types/task_comment_authors_item.py +5 -0
  171. label_studio_sdk/types/task_filter_options.py +15 -25
  172. label_studio_sdk/types/user_simple.py +11 -21
  173. label_studio_sdk/types/view.py +16 -26
  174. label_studio_sdk/types/webhook.py +19 -28
  175. label_studio_sdk/types/webhook_serializer_for_update.py +19 -28
  176. label_studio_sdk/types/workspace.py +22 -31
  177. label_studio_sdk/users/client.py +257 -63
  178. label_studio_sdk/users/types/users_get_token_response.py +12 -22
  179. label_studio_sdk/users/types/users_reset_token_response.py +12 -22
  180. label_studio_sdk/version.py +0 -1
  181. label_studio_sdk/versions/__init__.py +5 -0
  182. label_studio_sdk/versions/client.py +112 -0
  183. label_studio_sdk/versions/types/__init__.py +6 -0
  184. label_studio_sdk/versions/types/versions_get_response.py +73 -0
  185. label_studio_sdk/versions/types/versions_get_response_edition.py +5 -0
  186. label_studio_sdk/views/client.py +219 -52
  187. label_studio_sdk/views/types/views_create_request_data.py +13 -23
  188. label_studio_sdk/views/types/views_create_request_data_filters.py +14 -24
  189. label_studio_sdk/views/types/views_create_request_data_filters_items_item.py +16 -26
  190. label_studio_sdk/views/types/views_create_request_data_filters_items_item_value.py +3 -1
  191. label_studio_sdk/views/types/views_update_request_data.py +13 -23
  192. label_studio_sdk/views/types/views_update_request_data_filters.py +14 -24
  193. label_studio_sdk/views/types/views_update_request_data_filters_items_item.py +16 -26
  194. label_studio_sdk/views/types/views_update_request_data_filters_items_item_value.py +3 -1
  195. label_studio_sdk/webhooks/client.py +191 -61
  196. label_studio_sdk/workspaces/client.py +164 -41
  197. label_studio_sdk/workspaces/members/client.py +109 -31
  198. label_studio_sdk/workspaces/members/types/members_create_response.py +12 -22
  199. label_studio_sdk/workspaces/members/types/members_list_response_item.py +12 -22
  200. {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.10.dist-info}/METADATA +9 -5
  201. {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.10.dist-info}/RECORD +203 -186
  202. {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.10.dist-info}/WHEEL +1 -1
  203. label_studio_sdk/types/export_convert.py +0 -32
  204. label_studio_sdk/types/export_create.py +0 -54
  205. label_studio_sdk/types/export_create_status.py +0 -5
  206. {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.10.dist-info}/LICENSE +0 -0
@@ -23,9 +23,9 @@ from .types import (
23
23
  DataManagerTaskSerializerDraftsItem,
24
24
  DataManagerTaskSerializerPredictionsItem,
25
25
  Export,
26
- ExportConvert,
27
- ExportCreate,
28
- ExportCreateStatus,
26
+ ExportFormat,
27
+ ExportSnapshot,
28
+ ExportSnapshotStatus,
29
29
  ExportStatus,
30
30
  FileUpload,
31
31
  Filter,
@@ -35,6 +35,7 @@ from .types import (
35
35
  GcsImportStorage,
36
36
  GcsImportStorageStatus,
37
37
  InferenceRun,
38
+ InferenceRunCostEstimate,
38
39
  InferenceRunCreatedBy,
39
40
  InferenceRunOrganization,
40
41
  InferenceRunProjectSubset,
@@ -52,6 +53,7 @@ from .types import (
52
53
  MlBackendAuthMethod,
53
54
  MlBackendState,
54
55
  ModelProviderConnection,
56
+ ModelProviderConnectionBudgetResetPeriod,
55
57
  ModelProviderConnectionCreatedBy,
56
58
  ModelProviderConnectionOrganization,
57
59
  ModelProviderConnectionProvider,
@@ -64,6 +66,8 @@ from .types import (
64
66
  ProjectSampling,
65
67
  ProjectSkipQueue,
66
68
  Prompt,
69
+ PromptAssociatedProjectsItem,
70
+ PromptAssociatedProjectsItemId,
67
71
  PromptCreatedBy,
68
72
  PromptOrganization,
69
73
  PromptVersion,
@@ -87,6 +91,7 @@ from .types import (
87
91
  SerializationOptions,
88
92
  Task,
89
93
  TaskAnnotatorsItem,
94
+ TaskCommentAuthorsItem,
90
95
  TaskFilterOptions,
91
96
  UserSimple,
92
97
  View,
@@ -111,6 +116,7 @@ from . import (
111
116
  prompts,
112
117
  tasks,
113
118
  users,
119
+ versions,
114
120
  views,
115
121
  webhooks,
116
122
  workspaces,
@@ -129,7 +135,8 @@ from .actions import (
129
135
  ActionsCreateRequestSelectedItemsExcluded,
130
136
  ActionsCreateRequestSelectedItemsIncluded,
131
137
  )
132
- from .annotations import AnnotationsCreateBulkResponseItem
138
+ from .annotations import AnnotationsCreateBulkRequestSelectedItems, AnnotationsCreateBulkResponseItem
139
+ from .client import AsyncLabelStudio, LabelStudio
133
140
  from .environment import LabelStudioEnvironment
134
141
  from .export_storage import ExportStorageListTypesResponseItem
135
142
  from .import_storage import ImportStorageListTypesResponseItem
@@ -151,6 +158,7 @@ from .prompts import (
151
158
  from .tasks import TasksListRequestFields, TasksListResponse
152
159
  from .users import UsersGetTokenResponse, UsersResetTokenResponse
153
160
  from .version import __version__
161
+ from .versions import VersionsGetResponse, VersionsGetResponseEdition
154
162
  from .views import (
155
163
  ViewsCreateRequestData,
156
164
  ViewsCreateRequestDataFilters,
@@ -186,9 +194,11 @@ __all__ = [
186
194
  "Annotation",
187
195
  "AnnotationFilterOptions",
188
196
  "AnnotationLastAction",
197
+ "AnnotationsCreateBulkRequestSelectedItems",
189
198
  "AnnotationsCreateBulkResponseItem",
190
199
  "AnnotationsDmField",
191
200
  "AnnotationsDmFieldLastAction",
201
+ "AsyncLabelStudio",
192
202
  "AzureBlobExportStorage",
193
203
  "AzureBlobExportStorageStatus",
194
204
  "AzureBlobImportStorage",
@@ -208,9 +218,9 @@ __all__ = [
208
218
  "DataManagerTaskSerializerDraftsItem",
209
219
  "DataManagerTaskSerializerPredictionsItem",
210
220
  "Export",
211
- "ExportConvert",
212
- "ExportCreate",
213
- "ExportCreateStatus",
221
+ "ExportFormat",
222
+ "ExportSnapshot",
223
+ "ExportSnapshotStatus",
214
224
  "ExportStatus",
215
225
  "ExportStorageListTypesResponseItem",
216
226
  "FileUpload",
@@ -222,6 +232,7 @@ __all__ = [
222
232
  "GcsImportStorageStatus",
223
233
  "ImportStorageListTypesResponseItem",
224
234
  "InferenceRun",
235
+ "InferenceRunCostEstimate",
225
236
  "InferenceRunCreatedBy",
226
237
  "InferenceRunOrganization",
227
238
  "InferenceRunProjectSubset",
@@ -232,6 +243,7 @@ __all__ = [
232
243
  "KeyIndicatorsItem",
233
244
  "KeyIndicatorsItemAdditionalKpisItem",
234
245
  "KeyIndicatorsItemExtraKpisItem",
246
+ "LabelStudio",
235
247
  "LabelStudioEnvironment",
236
248
  "LocalFilesExportStorage",
237
249
  "LocalFilesExportStorageStatus",
@@ -247,6 +259,7 @@ __all__ = [
247
259
  "MlUpdateResponse",
248
260
  "MlUpdateResponseAuthMethod",
249
261
  "ModelProviderConnection",
262
+ "ModelProviderConnectionBudgetResetPeriod",
250
263
  "ModelProviderConnectionCreatedBy",
251
264
  "ModelProviderConnectionOrganization",
252
265
  "ModelProviderConnectionProvider",
@@ -263,6 +276,8 @@ __all__ = [
263
276
  "ProjectsListResponse",
264
277
  "ProjectsUpdateResponse",
265
278
  "Prompt",
279
+ "PromptAssociatedProjectsItem",
280
+ "PromptAssociatedProjectsItemId",
266
281
  "PromptCreatedBy",
267
282
  "PromptOrganization",
268
283
  "PromptVersion",
@@ -290,12 +305,15 @@ __all__ = [
290
305
  "SerializationOptions",
291
306
  "Task",
292
307
  "TaskAnnotatorsItem",
308
+ "TaskCommentAuthorsItem",
293
309
  "TaskFilterOptions",
294
310
  "TasksListRequestFields",
295
311
  "TasksListResponse",
296
312
  "UserSimple",
297
313
  "UsersGetTokenResponse",
298
314
  "UsersResetTokenResponse",
315
+ "VersionsGetResponse",
316
+ "VersionsGetResponseEdition",
299
317
  "View",
300
318
  "ViewsCreateRequestData",
301
319
  "ViewsCreateRequestDataFilters",
@@ -333,6 +351,7 @@ __all__ = [
333
351
  "prompts",
334
352
  "tasks",
335
353
  "users",
354
+ "versions",
336
355
  "views",
337
356
  "webhooks",
338
357
  "workspaces",
@@ -82,17 +82,26 @@ def parse_config(config_string):
82
82
  elif _is_input_tag(tag):
83
83
  inputs[tag.attrib["name"]] = {
84
84
  "type": tag.tag,
85
- "value": tag.attrib["value"].lstrip("$"),
86
85
  "valueType": tag.attrib.get("valueType"),
87
86
  }
87
+ if 'value' in tag.attrib:
88
+ inputs[tag.attrib["name"]]["value"] = tag.attrib["value"].lstrip("$")
89
+ elif 'valueList' in tag.attrib:
90
+ inputs[tag.attrib["name"]]["valueList"] = tag.attrib["valueList"].lstrip("$")
91
+ else:
92
+ raise ValueError(
93
+ 'Inspecting tag {tag_name}... found no "value" or "valueList" attributes.'.format(
94
+ tag_name=etree.tostring(tag, encoding="unicode").strip()[:50]
95
+ )
96
+ )
88
97
  if tag.tag not in _LABEL_TAGS:
89
98
  continue
90
99
  parent_name = _get_parent_output_tag_name(tag, outputs)
91
100
  if parent_name is not None:
92
- actual_value = tag.attrib.get("alias") or tag.attrib.get("value")
101
+ actual_value = tag.attrib.get("alias") or tag.attrib.get("value") or tag.attrib.get("valueList")
93
102
  if not actual_value:
94
103
  logger.debug(
95
- 'Inspecting tag {tag_name}... found no "value" or "alias" attributes.'.format(
104
+ 'Inspecting tag {tag_name}... found no "value", "valueList", or "alias" attributes.'.format(
96
105
  tag_name=etree.tostring(tag, encoding="unicode").strip()[:50]
97
106
  )
98
107
  )
@@ -137,7 +146,7 @@ def _is_input_tag(tag):
137
146
  """
138
147
  Check if tag is input
139
148
  """
140
- return tag.attrib.get("name") and tag.attrib.get("value")
149
+ return tag.attrib.get("name") and (tag.attrib.get("value") or tag.attrib.get("valueList"))
141
150
 
142
151
 
143
152
  def _is_output_tag(tag):
@@ -37,6 +37,17 @@ def get_cache_dir():
37
37
  return cache_dir
38
38
 
39
39
 
40
+ def safe_build_path(base_dir: str, user_path: str) -> str:
41
+ combined_path = os.path.join(base_dir, user_path)
42
+ absolute_path = os.path.abspath(combined_path)
43
+ base_dir_abs = os.path.abspath(base_dir)
44
+
45
+ if os.path.commonpath([absolute_path, base_dir_abs]) != base_dir_abs:
46
+ raise ValueError(f"Invalid path: {user_path}")
47
+
48
+ return absolute_path
49
+
50
+
40
51
  def get_local_path(
41
52
  url,
42
53
  cache_dir=None,
@@ -103,7 +114,7 @@ def get_local_path(
103
114
  # instead of downloading them from LS instance
104
115
  if is_local_storage_file:
105
116
  filepath = url.split("?d=")[1]
106
- filepath = os.path.join(LOCAL_FILES_DOCUMENT_ROOT, filepath)
117
+ filepath = safe_build_path(LOCAL_FILES_DOCUMENT_ROOT, filepath)
107
118
  if os.path.exists(filepath):
108
119
  logger.debug(
109
120
  f"Local Storage file path exists locally, use it as a local file: {filepath}"
@@ -124,9 +135,9 @@ def get_local_path(
124
135
  if is_uploaded_file and os.path.exists(image_dir):
125
136
  project_id = url.split("/")[-2] # To retrieve project_id
126
137
  filepath = os.path.join(image_dir, project_id, os.path.basename(url))
127
- if cache_dir and download_resources:
128
- shutil.copy(filepath, cache_dir)
129
138
  if os.path.exists(filepath):
139
+ if cache_dir and download_resources:
140
+ shutil.copy(filepath, cache_dir)
130
141
  logger.debug(f"Uploaded file: Path exists in image_dir: {filepath}")
131
142
  return filepath
132
143
 
@@ -202,7 +213,7 @@ def download_and_cache(
202
213
  filepath = os.path.join(cache_dir, url_hash + "__" + url_filename)
203
214
 
204
215
  if not os.path.exists(filepath):
205
- logger.info("Download {url} to {filepath}".format(url=url, filepath=filepath))
216
+ logger.info("Download {url} to {filepath}. download_resources: {download_resources}".format(url=url, filepath=filepath, download_resources=download_resources))
206
217
  if download_resources:
207
218
  headers = {
208
219
  # avoid requests.exceptions.HTTPError: 403 Client Error: Forbidden. Please comply with the User-Agent policy:
@@ -227,6 +238,7 @@ def download_and_cache(
227
238
  raise e
228
239
  with io.open(filepath, mode="wb") as fout:
229
240
  fout.write(r.content)
241
+ logger.info(f"File downloaded to {filepath}")
230
242
  return filepath
231
243
 
232
244
 
@@ -0,0 +1,86 @@
1
+ import json
2
+ import types
3
+ import sys
4
+ import functools
5
+ from typing import Type, Dict, Any, Tuple, Generator
6
+ from pathlib import Path
7
+ from tempfile import TemporaryDirectory
8
+ from datamodel_code_generator import DataModelType, PythonVersion, LiteralType
9
+ from datamodel_code_generator.model import get_data_model_types
10
+ from datamodel_code_generator.parser.jsonschema import JsonSchemaParser
11
+ from pydantic import BaseModel
12
+ from contextlib import contextmanager
13
+
14
+
15
+ @functools.lru_cache(maxsize=128)
16
+ def _generate_model_code(json_schema_str: str, class_name: str = 'MyModel') -> str:
17
+
18
+ data_model_types = get_data_model_types(
19
+ DataModelType.PydanticV2BaseModel,
20
+ target_python_version=PythonVersion.PY_311
21
+ )
22
+
23
+ parser = JsonSchemaParser(
24
+ json_schema_str,
25
+ data_model_type=data_model_types.data_model,
26
+ data_model_root_type=data_model_types.root_model,
27
+ data_model_field_type=data_model_types.field_model,
28
+ data_type_manager_type=data_model_types.data_type_manager,
29
+ dump_resolve_reference_action=data_model_types.dump_resolve_reference_action,
30
+ enum_field_as_literal=LiteralType.All,
31
+ class_name=class_name
32
+ )
33
+
34
+ model_code = parser.parse()
35
+ return model_code
36
+
37
+ @contextmanager
38
+ def json_schema_to_pydantic(json_schema: dict, class_name: str = 'MyModel') -> Generator[Type[BaseModel], None, None]:
39
+ """
40
+ Convert a JSON schema to a Pydantic model and provide it as a context manager.
41
+
42
+ Args:
43
+ json_schema (dict): The JSON schema to convert.
44
+ class_name (str, optional): The name of the generated Pydantic class. Defaults to 'MyModel'.
45
+
46
+ Example:
47
+ ```python
48
+ example_schema = {
49
+ "type": "object",
50
+ "properties": {
51
+ "sentiment": {
52
+ "type": "string",
53
+ "description": "Sentiment of the text",
54
+ "enum": ["Positive", "Negative", "Neutral"],
55
+ }
56
+ },
57
+ "required": ["sentiment"]
58
+ }
59
+ with json_schema_to_pydantic(example_schema) as ResponseModel:
60
+ instance = ResponseModel(sentiment='Positive')
61
+ print(instance.model_dump())
62
+ ```
63
+ """
64
+ # Convert the JSON schema dictionary to a JSON string
65
+ json_schema_str = json.dumps(json_schema)
66
+
67
+ # Generate Pydantic model code from the JSON schema string
68
+ model_code: str = _generate_model_code(json_schema_str, class_name)
69
+
70
+ # Create a unique module name using the id of the JSON schema string
71
+ module_name = f'dynamic_module_{id(json_schema_str)}'
72
+
73
+ # Create a new module object with the unique name and execute the generated model code in the context of the new module
74
+ mod = types.ModuleType(module_name)
75
+ exec(model_code, mod.__dict__)
76
+ model_class = getattr(mod, class_name)
77
+
78
+ try:
79
+ # Add the new module to sys.modules to make it importable
80
+ # This is necessary to avoid Pydantic errors related to undefined models
81
+ sys.modules[module_name] = mod
82
+ yield model_class
83
+ finally:
84
+ if module_name in sys.modules:
85
+ del sys.modules[module_name]
86
+
@@ -47,3 +47,11 @@ class AsyncPagerExt(AsyncPager, typing.Generic[T]):
47
47
  if exc.status_code == 404:
48
48
  return
49
49
  raise
50
+
51
+ async def __anext__(self) -> T:
52
+ try:
53
+ return await super().__anext__()
54
+ except ApiError as exc:
55
+ if exc.status_code == 404:
56
+ raise StopAsyncIteration
57
+ raise
@@ -35,22 +35,44 @@
35
35
  }
36
36
  }
37
37
  },
38
- "tag_with_value_required_name": {
38
+ "tag_with_name_and_toname": {
39
39
  "type": "object",
40
- "anyOf": [
41
- {
42
- "required": [
43
- "@name",
44
- "@valueList"
45
- ]
46
- },
40
+ "oneOf": [
47
41
  {
48
42
  "required": [
49
43
  "@name",
50
- "@value"
44
+ "@toName"
51
45
  ]
52
46
  }
53
47
  ],
48
+ "properties": {
49
+ "@name": {
50
+ "$ref": "#/definitions/@name"
51
+ },
52
+ "@toName": {
53
+ "$ref": "#/definitions/@toName"
54
+ },
55
+ "$": {
56
+ "$ref": "#/definitions/$"
57
+ }
58
+ }
59
+ },
60
+ "tag_with_value_required_name": {
61
+ "type": "object",
62
+ "oneOf": [
63
+ {
64
+ "required": [
65
+ "@name",
66
+ "@value"
67
+ ]
68
+ },
69
+ {
70
+ "required": [
71
+ "@name",
72
+ "@valueList"
73
+ ]
74
+ }
75
+ ],
54
76
  "properties": {
55
77
  "@value": {
56
78
  "$ref": "#/definitions/@value"
@@ -80,6 +102,13 @@
80
102
  "items": {"$ref": "#/definitions/tag_with_value_required_name"}
81
103
  }, {"$ref": "#/definitions/tag_with_value_required_name"}]
82
104
  },
105
+ "tags_with_name_and_toname": {
106
+ "anyOf": [{"$ref": "#/definitions/tag_with_name_and_toname"},
107
+ {
108
+ "type": "array",
109
+ "items": {"$ref": "#/definitions/tag_with_name_and_toname"}
110
+ }]
111
+ },
83
112
  "View": {
84
113
  "type": "object",
85
114
  "additionalProperties": true,
@@ -92,7 +121,8 @@
92
121
  "Text": {"$ref": "#/definitions/tags_with_value_required_name"},
93
122
  "HyperText": {"$ref": "#/definitions/tags_with_value_required_name"},
94
123
  "View": {"$ref": "#/definitions/MaybeMultipleView"},
95
- "TextArea": {"$ref": "#/definitions/MaybeMultipleTextAreas"}
124
+ "TextArea": {"$ref": "#/definitions/MaybeMultipleTextAreas"},
125
+ "Number": {"$ref": "#/definitions/tags_with_name_and_toname"}
96
126
  }
97
127
  },
98
128
  "MaybeMultipleView": {
@@ -219,7 +249,8 @@
219
249
  "Image": {"$ref": "#/definitions/tags_with_value_required_name"},
220
250
  "Text": {"$ref": "#/definitions/tags_with_value_required_name"},
221
251
  "HyperText": {"$ref": "#/definitions/tags_with_value_required_name"},
222
- "TextArea": {"$ref": "#/definitions/MaybeMultipleTextAreas"}
252
+ "TextArea": {"$ref": "#/definitions/MaybeMultipleTextAreas"},
253
+ "Number": {"$ref": "#/definitions/tags_with_name_and_toname"}
223
254
  }
224
255
  }
225
256
  }
@@ -1,15 +1,16 @@
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
4
6
  from json.decoder import JSONDecodeError
5
-
6
7
  from ..core.api_error import ApiError
7
- from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
8
- from ..core.request_options import RequestOptions
9
- from .types.actions_create_request_filters import ActionsCreateRequestFilters
10
8
  from .types.actions_create_request_id import ActionsCreateRequestId
11
- from .types.actions_create_request_ordering_item import ActionsCreateRequestOrderingItem
9
+ from .types.actions_create_request_filters import ActionsCreateRequestFilters
12
10
  from .types.actions_create_request_selected_items import ActionsCreateRequestSelectedItems
11
+ from .types.actions_create_request_ordering_item import ActionsCreateRequestOrderingItem
12
+ from ..core.serialization import convert_and_respect_annotation_metadata
13
+ from ..core.client_wrapper import AsyncClientWrapper
13
14
 
14
15
  # this is used as the default value for optional parameters
15
16
  OMIT = typing.cast(typing.Any, ...)
@@ -34,7 +35,7 @@ class ActionsClient:
34
35
 
35
36
  Examples
36
37
  --------
37
- from label_studio_sdk.client import LabelStudio
38
+ from label_studio_sdk import LabelStudio
38
39
 
39
40
  client = LabelStudio(
40
41
  api_key="YOUR_API_KEY",
@@ -42,7 +43,9 @@ class ActionsClient:
42
43
  client.actions.list()
43
44
  """
44
45
  _response = self._client_wrapper.httpx_client.request(
45
- "api/dm/actions/", method="GET", request_options=request_options
46
+ "api/dm/actions/",
47
+ method="GET",
48
+ request_options=request_options,
46
49
  )
47
50
  try:
48
51
  if 200 <= _response.status_code < 300:
@@ -61,7 +64,7 @@ class ActionsClient:
61
64
  filters: typing.Optional[ActionsCreateRequestFilters] = OMIT,
62
65
  selected_items: typing.Optional[ActionsCreateRequestSelectedItems] = OMIT,
63
66
  ordering: typing.Optional[typing.Sequence[ActionsCreateRequestOrderingItem]] = OMIT,
64
- request_options: typing.Optional[RequestOptions] = None
67
+ request_options: typing.Optional[RequestOptions] = None,
65
68
  ) -> None:
66
69
  """
67
70
  Perform a Data Manager action with the selected tasks and filters. Note: More complex actions require additional parameters in the request body. Call `GET api/actions?project=<id>` to explore them. <br>Example: `GET api/actions?id=delete_tasks&project=1`
@@ -95,12 +98,12 @@ class ActionsClient:
95
98
 
96
99
  Examples
97
100
  --------
98
- from label_studio_sdk import (
101
+ from label_studio_sdk import LabelStudio
102
+ from label_studio_sdk.actions import (
99
103
  ActionsCreateRequestFilters,
100
104
  ActionsCreateRequestFiltersItemsItem,
101
105
  ActionsCreateRequestSelectedItemsExcluded,
102
106
  )
103
- from label_studio_sdk.client import LabelStudio
104
107
 
105
108
  client = LabelStudio(
106
109
  api_key="YOUR_API_KEY",
@@ -129,8 +132,23 @@ class ActionsClient:
129
132
  _response = self._client_wrapper.httpx_client.request(
130
133
  "api/dm/actions/",
131
134
  method="POST",
132
- params={"id": id, "project": project, "view": view},
133
- json={"filters": filters, "selectedItems": selected_items, "ordering": ordering},
135
+ params={
136
+ "id": id,
137
+ "project": project,
138
+ "view": view,
139
+ },
140
+ json={
141
+ "filters": convert_and_respect_annotation_metadata(
142
+ object_=filters, annotation=ActionsCreateRequestFilters, direction="write"
143
+ ),
144
+ "selectedItems": convert_and_respect_annotation_metadata(
145
+ object_=selected_items, annotation=ActionsCreateRequestSelectedItems, direction="write"
146
+ ),
147
+ "ordering": ordering,
148
+ },
149
+ headers={
150
+ "content-type": "application/json",
151
+ },
134
152
  request_options=request_options,
135
153
  omit=OMIT,
136
154
  )
@@ -162,15 +180,25 @@ class AsyncActionsClient:
162
180
 
163
181
  Examples
164
182
  --------
165
- from label_studio_sdk.client import AsyncLabelStudio
183
+ import asyncio
184
+
185
+ from label_studio_sdk import AsyncLabelStudio
166
186
 
167
187
  client = AsyncLabelStudio(
168
188
  api_key="YOUR_API_KEY",
169
189
  )
170
- await client.actions.list()
190
+
191
+
192
+ async def main() -> None:
193
+ await client.actions.list()
194
+
195
+
196
+ asyncio.run(main())
171
197
  """
172
198
  _response = await self._client_wrapper.httpx_client.request(
173
- "api/dm/actions/", method="GET", request_options=request_options
199
+ "api/dm/actions/",
200
+ method="GET",
201
+ request_options=request_options,
174
202
  )
175
203
  try:
176
204
  if 200 <= _response.status_code < 300:
@@ -189,7 +217,7 @@ class AsyncActionsClient:
189
217
  filters: typing.Optional[ActionsCreateRequestFilters] = OMIT,
190
218
  selected_items: typing.Optional[ActionsCreateRequestSelectedItems] = OMIT,
191
219
  ordering: typing.Optional[typing.Sequence[ActionsCreateRequestOrderingItem]] = OMIT,
192
- request_options: typing.Optional[RequestOptions] = None
220
+ request_options: typing.Optional[RequestOptions] = None,
193
221
  ) -> None:
194
222
  """
195
223
  Perform a Data Manager action with the selected tasks and filters. Note: More complex actions require additional parameters in the request body. Call `GET api/actions?project=<id>` to explore them. <br>Example: `GET api/actions?id=delete_tasks&project=1`
@@ -223,42 +251,65 @@ class AsyncActionsClient:
223
251
 
224
252
  Examples
225
253
  --------
226
- from label_studio_sdk import (
254
+ import asyncio
255
+
256
+ from label_studio_sdk import AsyncLabelStudio
257
+ from label_studio_sdk.actions import (
227
258
  ActionsCreateRequestFilters,
228
259
  ActionsCreateRequestFiltersItemsItem,
229
260
  ActionsCreateRequestSelectedItemsExcluded,
230
261
  )
231
- from label_studio_sdk.client import AsyncLabelStudio
232
262
 
233
263
  client = AsyncLabelStudio(
234
264
  api_key="YOUR_API_KEY",
235
265
  )
236
- await client.actions.create(
237
- id="retrieve_tasks_predictions",
238
- project=1,
239
- filters=ActionsCreateRequestFilters(
240
- conjunction="or",
241
- items=[
242
- ActionsCreateRequestFiltersItemsItem(
243
- filter="filter:tasks:id",
244
- operator="greater",
245
- type="Number",
246
- value=123,
247
- )
248
- ],
249
- ),
250
- selected_items=ActionsCreateRequestSelectedItemsExcluded(
251
- all_=True,
252
- excluded=[124, 125, 126],
253
- ),
254
- ordering=["tasks:total_annotations"],
255
- )
266
+
267
+
268
+ async def main() -> None:
269
+ await client.actions.create(
270
+ id="retrieve_tasks_predictions",
271
+ project=1,
272
+ filters=ActionsCreateRequestFilters(
273
+ conjunction="or",
274
+ items=[
275
+ ActionsCreateRequestFiltersItemsItem(
276
+ filter="filter:tasks:id",
277
+ operator="greater",
278
+ type="Number",
279
+ value=123,
280
+ )
281
+ ],
282
+ ),
283
+ selected_items=ActionsCreateRequestSelectedItemsExcluded(
284
+ all_=True,
285
+ excluded=[124, 125, 126],
286
+ ),
287
+ ordering=["tasks:total_annotations"],
288
+ )
289
+
290
+
291
+ asyncio.run(main())
256
292
  """
257
293
  _response = await self._client_wrapper.httpx_client.request(
258
294
  "api/dm/actions/",
259
295
  method="POST",
260
- params={"id": id, "project": project, "view": view},
261
- json={"filters": filters, "selectedItems": selected_items, "ordering": ordering},
296
+ params={
297
+ "id": id,
298
+ "project": project,
299
+ "view": view,
300
+ },
301
+ json={
302
+ "filters": convert_and_respect_annotation_metadata(
303
+ object_=filters, annotation=ActionsCreateRequestFilters, direction="write"
304
+ ),
305
+ "selectedItems": convert_and_respect_annotation_metadata(
306
+ object_=selected_items, annotation=ActionsCreateRequestSelectedItems, direction="write"
307
+ ),
308
+ "ordering": ordering,
309
+ },
310
+ headers={
311
+ "content-type": "application/json",
312
+ },
262
313
  request_options=request_options,
263
314
  omit=OMIT,
264
315
  )