label-studio-sdk 0.0.34__py3-none-any.whl → 1.0.1__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 (272) hide show
  1. label_studio_sdk/__init__.py +232 -9
  2. label_studio_sdk/_extensions/label_studio_tools/__init__.py +0 -0
  3. label_studio_sdk/_extensions/label_studio_tools/core/__init__.py +0 -0
  4. label_studio_sdk/_extensions/label_studio_tools/core/label_config.py +163 -0
  5. label_studio_sdk/_extensions/label_studio_tools/core/utils/__init__.py +0 -0
  6. label_studio_sdk/_extensions/label_studio_tools/core/utils/exceptions.py +2 -0
  7. label_studio_sdk/_extensions/label_studio_tools/core/utils/io.py +228 -0
  8. label_studio_sdk/_extensions/label_studio_tools/core/utils/params.py +45 -0
  9. label_studio_sdk/_extensions/label_studio_tools/etl/__init__.py +1 -0
  10. label_studio_sdk/_extensions/label_studio_tools/etl/beam.py +34 -0
  11. label_studio_sdk/_extensions/label_studio_tools/etl/example.py +17 -0
  12. label_studio_sdk/_extensions/label_studio_tools/etl/registry.py +67 -0
  13. label_studio_sdk/_extensions/label_studio_tools/postprocessing/__init__.py +0 -0
  14. label_studio_sdk/_extensions/label_studio_tools/postprocessing/video.py +97 -0
  15. label_studio_sdk/_extensions/pager_ext.py +49 -0
  16. label_studio_sdk/_legacy/__init__.py +11 -0
  17. label_studio_sdk/_legacy/client.py +471 -0
  18. label_studio_sdk/_legacy/objects.py +74 -0
  19. label_studio_sdk/{project.py → _legacy/project.py} +2 -2
  20. label_studio_sdk/{schema → _legacy/schema}/label_config_schema.json +14 -14
  21. label_studio_sdk/actions/__init__.py +27 -0
  22. label_studio_sdk/actions/client.py +223 -0
  23. label_studio_sdk/actions/types/__init__.py +25 -0
  24. label_studio_sdk/actions/types/actions_create_request_filters.py +43 -0
  25. label_studio_sdk/actions/types/actions_create_request_filters_conjunction.py +5 -0
  26. label_studio_sdk/actions/types/actions_create_request_filters_items_item.py +49 -0
  27. label_studio_sdk/actions/types/actions_create_request_filters_items_item_filter.py +31 -0
  28. label_studio_sdk/actions/types/actions_create_request_filters_items_item_operator.py +23 -0
  29. label_studio_sdk/actions/types/actions_create_request_id.py +19 -0
  30. label_studio_sdk/actions/types/actions_create_request_ordering_item.py +31 -0
  31. label_studio_sdk/actions/types/actions_create_request_selected_items.py +10 -0
  32. label_studio_sdk/actions/types/actions_create_request_selected_items_excluded.py +39 -0
  33. label_studio_sdk/actions/types/actions_create_request_selected_items_included.py +39 -0
  34. label_studio_sdk/annotations/__init__.py +2 -0
  35. label_studio_sdk/annotations/client.py +750 -0
  36. label_studio_sdk/base_client.py +183 -0
  37. label_studio_sdk/client.py +17 -463
  38. label_studio_sdk/converter/__init__.py +7 -0
  39. label_studio_sdk/converter/audio.py +56 -0
  40. label_studio_sdk/converter/brush.py +452 -0
  41. label_studio_sdk/converter/converter.py +1175 -0
  42. label_studio_sdk/converter/exports/__init__.py +0 -0
  43. label_studio_sdk/converter/exports/csv.py +82 -0
  44. label_studio_sdk/converter/exports/csv2.py +103 -0
  45. label_studio_sdk/converter/funsd.py +85 -0
  46. label_studio_sdk/converter/imports/__init__.py +0 -0
  47. label_studio_sdk/converter/imports/coco.py +314 -0
  48. label_studio_sdk/converter/imports/colors.py +198 -0
  49. label_studio_sdk/converter/imports/label_config.py +45 -0
  50. label_studio_sdk/converter/imports/pathtrack.py +269 -0
  51. label_studio_sdk/converter/imports/yolo.py +236 -0
  52. label_studio_sdk/converter/main.py +202 -0
  53. label_studio_sdk/converter/utils.py +473 -0
  54. label_studio_sdk/core/__init__.py +33 -0
  55. label_studio_sdk/core/api_error.py +15 -0
  56. label_studio_sdk/core/client_wrapper.py +55 -0
  57. label_studio_sdk/core/datetime_utils.py +28 -0
  58. label_studio_sdk/core/file.py +38 -0
  59. label_studio_sdk/core/http_client.py +447 -0
  60. label_studio_sdk/core/jsonable_encoder.py +99 -0
  61. label_studio_sdk/core/pagination.py +87 -0
  62. label_studio_sdk/core/pydantic_utilities.py +28 -0
  63. label_studio_sdk/core/query_encoder.py +33 -0
  64. label_studio_sdk/core/remove_none_from_dict.py +11 -0
  65. label_studio_sdk/core/request_options.py +32 -0
  66. label_studio_sdk/environment.py +7 -0
  67. label_studio_sdk/errors/__init__.py +6 -0
  68. label_studio_sdk/errors/bad_request_error.py +8 -0
  69. label_studio_sdk/errors/internal_server_error.py +8 -0
  70. label_studio_sdk/export_storage/__init__.py +28 -0
  71. label_studio_sdk/export_storage/azure/__init__.py +5 -0
  72. label_studio_sdk/export_storage/azure/client.py +888 -0
  73. label_studio_sdk/export_storage/azure/types/__init__.py +6 -0
  74. label_studio_sdk/export_storage/azure/types/azure_create_response.py +67 -0
  75. label_studio_sdk/export_storage/azure/types/azure_update_response.py +67 -0
  76. label_studio_sdk/export_storage/client.py +107 -0
  77. label_studio_sdk/export_storage/gcs/__init__.py +5 -0
  78. label_studio_sdk/export_storage/gcs/client.py +888 -0
  79. label_studio_sdk/export_storage/gcs/types/__init__.py +6 -0
  80. label_studio_sdk/export_storage/gcs/types/gcs_create_response.py +67 -0
  81. label_studio_sdk/export_storage/gcs/types/gcs_update_response.py +67 -0
  82. label_studio_sdk/export_storage/local/__init__.py +5 -0
  83. label_studio_sdk/export_storage/local/client.py +834 -0
  84. label_studio_sdk/export_storage/local/types/__init__.py +6 -0
  85. label_studio_sdk/export_storage/local/types/local_create_response.py +57 -0
  86. label_studio_sdk/export_storage/local/types/local_update_response.py +57 -0
  87. label_studio_sdk/export_storage/redis/__init__.py +5 -0
  88. label_studio_sdk/export_storage/redis/client.py +918 -0
  89. label_studio_sdk/export_storage/redis/types/__init__.py +6 -0
  90. label_studio_sdk/export_storage/redis/types/redis_create_response.py +72 -0
  91. label_studio_sdk/export_storage/redis/types/redis_update_response.py +72 -0
  92. label_studio_sdk/export_storage/s3/__init__.py +5 -0
  93. label_studio_sdk/export_storage/s3/client.py +1008 -0
  94. label_studio_sdk/export_storage/s3/types/__init__.py +6 -0
  95. label_studio_sdk/export_storage/s3/types/s3create_response.py +89 -0
  96. label_studio_sdk/export_storage/s3/types/s3update_response.py +89 -0
  97. label_studio_sdk/export_storage/types/__init__.py +5 -0
  98. label_studio_sdk/export_storage/types/export_storage_list_types_response_item.py +30 -0
  99. label_studio_sdk/files/__init__.py +2 -0
  100. label_studio_sdk/files/client.py +556 -0
  101. label_studio_sdk/import_storage/__init__.py +28 -0
  102. label_studio_sdk/import_storage/azure/__init__.py +5 -0
  103. label_studio_sdk/import_storage/azure/client.py +988 -0
  104. label_studio_sdk/import_storage/azure/types/__init__.py +6 -0
  105. label_studio_sdk/import_storage/azure/types/azure_create_response.py +82 -0
  106. label_studio_sdk/import_storage/azure/types/azure_update_response.py +82 -0
  107. label_studio_sdk/import_storage/client.py +107 -0
  108. label_studio_sdk/import_storage/gcs/__init__.py +5 -0
  109. label_studio_sdk/import_storage/gcs/client.py +988 -0
  110. label_studio_sdk/import_storage/gcs/types/__init__.py +6 -0
  111. label_studio_sdk/import_storage/gcs/types/gcs_create_response.py +82 -0
  112. label_studio_sdk/import_storage/gcs/types/gcs_update_response.py +82 -0
  113. label_studio_sdk/import_storage/local/__init__.py +5 -0
  114. label_studio_sdk/import_storage/local/client.py +836 -0
  115. label_studio_sdk/import_storage/local/types/__init__.py +6 -0
  116. label_studio_sdk/import_storage/local/types/local_create_response.py +57 -0
  117. label_studio_sdk/import_storage/local/types/local_update_response.py +57 -0
  118. label_studio_sdk/import_storage/redis/__init__.py +5 -0
  119. label_studio_sdk/import_storage/redis/client.py +924 -0
  120. label_studio_sdk/import_storage/redis/types/__init__.py +6 -0
  121. label_studio_sdk/import_storage/redis/types/redis_create_response.py +72 -0
  122. label_studio_sdk/import_storage/redis/types/redis_update_response.py +72 -0
  123. label_studio_sdk/import_storage/s3/__init__.py +5 -0
  124. label_studio_sdk/import_storage/s3/client.py +1138 -0
  125. label_studio_sdk/import_storage/s3/types/__init__.py +6 -0
  126. label_studio_sdk/import_storage/s3/types/s3create_response.py +109 -0
  127. label_studio_sdk/import_storage/s3/types/s3update_response.py +109 -0
  128. label_studio_sdk/import_storage/types/__init__.py +5 -0
  129. label_studio_sdk/import_storage/types/import_storage_list_types_response_item.py +30 -0
  130. label_studio_sdk/label_interface/base.py +10 -0
  131. label_studio_sdk/label_interface/control_tags.py +109 -71
  132. label_studio_sdk/label_interface/data_examples.json +96 -0
  133. label_studio_sdk/label_interface/interface.py +102 -53
  134. label_studio_sdk/label_interface/object_tags.py +8 -13
  135. label_studio_sdk/label_interface/region.py +33 -1
  136. label_studio_sdk/ml/__init__.py +19 -0
  137. label_studio_sdk/ml/client.py +981 -0
  138. label_studio_sdk/ml/types/__init__.py +17 -0
  139. label_studio_sdk/ml/types/ml_create_request_auth_method.py +5 -0
  140. label_studio_sdk/ml/types/ml_create_response.py +78 -0
  141. label_studio_sdk/ml/types/ml_create_response_auth_method.py +5 -0
  142. label_studio_sdk/ml/types/ml_update_request_auth_method.py +5 -0
  143. label_studio_sdk/ml/types/ml_update_response.py +78 -0
  144. label_studio_sdk/ml/types/ml_update_response_auth_method.py +5 -0
  145. label_studio_sdk/predictions/__init__.py +2 -0
  146. label_studio_sdk/predictions/client.py +638 -0
  147. label_studio_sdk/projects/__init__.py +6 -0
  148. label_studio_sdk/projects/client.py +1055 -0
  149. label_studio_sdk/projects/client_ext.py +19 -0
  150. label_studio_sdk/projects/exports/__init__.py +2 -0
  151. label_studio_sdk/projects/exports/client.py +930 -0
  152. label_studio_sdk/projects/types/__init__.py +7 -0
  153. label_studio_sdk/projects/types/projects_create_response.py +96 -0
  154. label_studio_sdk/projects/types/projects_import_tasks_response.py +71 -0
  155. label_studio_sdk/projects/types/projects_list_response.py +33 -0
  156. label_studio_sdk/py.typed +0 -0
  157. label_studio_sdk/tasks/__init__.py +5 -0
  158. label_studio_sdk/tasks/client.py +835 -0
  159. label_studio_sdk/tasks/client_ext.py +18 -0
  160. label_studio_sdk/tasks/types/__init__.py +6 -0
  161. label_studio_sdk/tasks/types/tasks_list_request_fields.py +5 -0
  162. label_studio_sdk/tasks/types/tasks_list_response.py +48 -0
  163. label_studio_sdk/types/__init__.py +115 -0
  164. label_studio_sdk/types/annotation.py +116 -0
  165. label_studio_sdk/types/annotation_filter_options.py +42 -0
  166. label_studio_sdk/types/annotation_last_action.py +19 -0
  167. label_studio_sdk/types/azure_blob_export_storage.py +112 -0
  168. label_studio_sdk/types/azure_blob_export_storage_status.py +7 -0
  169. label_studio_sdk/types/azure_blob_import_storage.py +113 -0
  170. label_studio_sdk/types/azure_blob_import_storage_status.py +7 -0
  171. label_studio_sdk/types/base_task.py +113 -0
  172. label_studio_sdk/types/base_user.py +42 -0
  173. label_studio_sdk/types/converted_format.py +36 -0
  174. label_studio_sdk/types/converted_format_status.py +5 -0
  175. label_studio_sdk/types/export.py +48 -0
  176. label_studio_sdk/types/export_convert.py +32 -0
  177. label_studio_sdk/types/export_create.py +54 -0
  178. label_studio_sdk/types/export_create_status.py +5 -0
  179. label_studio_sdk/types/export_status.py +5 -0
  180. label_studio_sdk/types/file_upload.py +30 -0
  181. label_studio_sdk/types/filter.py +53 -0
  182. label_studio_sdk/types/filter_group.py +35 -0
  183. label_studio_sdk/types/gcs_export_storage.py +112 -0
  184. label_studio_sdk/types/gcs_export_storage_status.py +7 -0
  185. label_studio_sdk/types/gcs_import_storage.py +113 -0
  186. label_studio_sdk/types/gcs_import_storage_status.py +7 -0
  187. label_studio_sdk/types/local_files_export_storage.py +97 -0
  188. label_studio_sdk/types/local_files_export_storage_status.py +7 -0
  189. label_studio_sdk/types/local_files_import_storage.py +92 -0
  190. label_studio_sdk/types/local_files_import_storage_status.py +7 -0
  191. label_studio_sdk/types/ml_backend.py +89 -0
  192. label_studio_sdk/types/ml_backend_auth_method.py +5 -0
  193. label_studio_sdk/types/ml_backend_state.py +5 -0
  194. label_studio_sdk/types/prediction.py +78 -0
  195. label_studio_sdk/types/project.py +198 -0
  196. label_studio_sdk/types/project_import.py +63 -0
  197. label_studio_sdk/types/project_import_status.py +5 -0
  198. label_studio_sdk/types/project_label_config.py +32 -0
  199. label_studio_sdk/types/project_sampling.py +7 -0
  200. label_studio_sdk/types/project_skip_queue.py +5 -0
  201. label_studio_sdk/types/redis_export_storage.py +117 -0
  202. label_studio_sdk/types/redis_export_storage_status.py +7 -0
  203. label_studio_sdk/types/redis_import_storage.py +112 -0
  204. label_studio_sdk/types/redis_import_storage_status.py +7 -0
  205. label_studio_sdk/types/s3export_storage.py +134 -0
  206. label_studio_sdk/types/s3export_storage_status.py +7 -0
  207. label_studio_sdk/types/s3import_storage.py +140 -0
  208. label_studio_sdk/types/s3import_storage_status.py +7 -0
  209. label_studio_sdk/types/serialization_option.py +36 -0
  210. label_studio_sdk/types/serialization_options.py +45 -0
  211. label_studio_sdk/types/task.py +157 -0
  212. label_studio_sdk/types/task_filter_options.py +49 -0
  213. label_studio_sdk/types/user_simple.py +37 -0
  214. label_studio_sdk/types/view.py +55 -0
  215. label_studio_sdk/types/webhook.py +67 -0
  216. label_studio_sdk/types/webhook_actions_item.py +21 -0
  217. label_studio_sdk/types/webhook_serializer_for_update.py +67 -0
  218. label_studio_sdk/types/webhook_serializer_for_update_actions_item.py +21 -0
  219. label_studio_sdk/users/__init__.py +5 -0
  220. label_studio_sdk/users/client.py +830 -0
  221. label_studio_sdk/users/types/__init__.py +6 -0
  222. label_studio_sdk/users/types/users_get_token_response.py +36 -0
  223. label_studio_sdk/users/types/users_reset_token_response.py +36 -0
  224. label_studio_sdk/version.py +4 -0
  225. label_studio_sdk/views/__init__.py +35 -0
  226. label_studio_sdk/views/client.py +564 -0
  227. label_studio_sdk/views/types/__init__.py +33 -0
  228. label_studio_sdk/views/types/views_create_request_data.py +43 -0
  229. label_studio_sdk/views/types/views_create_request_data_filters.py +43 -0
  230. label_studio_sdk/views/types/views_create_request_data_filters_conjunction.py +5 -0
  231. label_studio_sdk/views/types/views_create_request_data_filters_items_item.py +49 -0
  232. label_studio_sdk/views/types/views_create_request_data_filters_items_item_filter.py +31 -0
  233. label_studio_sdk/views/types/views_create_request_data_filters_items_item_operator.py +23 -0
  234. label_studio_sdk/views/types/views_create_request_data_ordering_item.py +31 -0
  235. label_studio_sdk/views/types/views_update_request_data.py +43 -0
  236. label_studio_sdk/views/types/views_update_request_data_filters.py +43 -0
  237. label_studio_sdk/views/types/views_update_request_data_filters_conjunction.py +5 -0
  238. label_studio_sdk/views/types/views_update_request_data_filters_items_item.py +49 -0
  239. label_studio_sdk/views/types/views_update_request_data_filters_items_item_filter.py +31 -0
  240. label_studio_sdk/views/types/views_update_request_data_filters_items_item_operator.py +23 -0
  241. label_studio_sdk/views/types/views_update_request_data_ordering_item.py +31 -0
  242. label_studio_sdk/webhooks/__init__.py +5 -0
  243. label_studio_sdk/webhooks/client.py +636 -0
  244. label_studio_sdk/webhooks/types/__init__.py +5 -0
  245. label_studio_sdk/webhooks/types/webhooks_update_request_actions_item.py +21 -0
  246. label_studio_sdk-1.0.1.dist-info/METADATA +163 -0
  247. label_studio_sdk-1.0.1.dist-info/RECORD +256 -0
  248. {label_studio_sdk-0.0.34.dist-info → label_studio_sdk-1.0.1.dist-info}/WHEEL +1 -2
  249. label_studio_sdk/objects.py +0 -35
  250. label_studio_sdk-0.0.34.dist-info/LICENSE +0 -201
  251. label_studio_sdk-0.0.34.dist-info/METADATA +0 -24
  252. label_studio_sdk-0.0.34.dist-info/RECORD +0 -37
  253. label_studio_sdk-0.0.34.dist-info/top_level.txt +0 -2
  254. tests/test_client.py +0 -37
  255. tests/test_export.py +0 -105
  256. tests/test_interface/__init__.py +0 -1
  257. tests/test_interface/configs.py +0 -137
  258. tests/test_interface/mockups.py +0 -22
  259. tests/test_interface/test_compat.py +0 -64
  260. tests/test_interface/test_control_tags.py +0 -55
  261. tests/test_interface/test_data_generation.py +0 -45
  262. tests/test_interface/test_lpi.py +0 -15
  263. tests/test_interface/test_main.py +0 -196
  264. tests/test_interface/test_object_tags.py +0 -36
  265. tests/test_interface/test_region.py +0 -36
  266. tests/test_interface/test_validate_summary.py +0 -35
  267. tests/test_interface/test_validation.py +0 -59
  268. {tests → label_studio_sdk/_extensions}/__init__.py +0 -0
  269. /label_studio_sdk/{exceptions.py → _legacy/exceptions.py} +0 -0
  270. /label_studio_sdk/{users.py → _legacy/users.py} +0 -0
  271. /label_studio_sdk/{utils.py → _legacy/utils.py} +0 -0
  272. /label_studio_sdk/{workspaces.py → _legacy/workspaces.py} +0 -0
@@ -0,0 +1,34 @@
1
+ import apache_beam as beam
2
+ from registry import dataloader, call_dataloader
3
+
4
+
5
+ class CallDataLoader(beam.DoFn):
6
+ def __init__(self, dataloader_name):
7
+ self.dataloader_name = dataloader_name
8
+
9
+ def setup(self):
10
+ print("Setup!")
11
+ pass
12
+
13
+ def process(self, element, *args, **kwargs):
14
+ return call_dataloader(self.dataloader_name, element, *args, **kwargs)
15
+
16
+ def teardown(self):
17
+ print("Teardown!")
18
+ pass
19
+
20
+
21
+ @dataloader("test")
22
+ def f(i, k):
23
+ print("I!!", k)
24
+ yield i
25
+
26
+
27
+ with beam.Pipeline() as pipeline:
28
+ results = (
29
+ pipeline
30
+ | "Get storage keys" >> beam.io.gcp.gcsio.list_files("bucket")
31
+ | "Run dataloader"
32
+ >> beam.FlatMap(fn=CallDataLoader("test"), **dataloader_kwargs)
33
+ | "Load into Vector DB" >> beam.ParDo(fn=LoadDataRecordInDB)
34
+ )
@@ -0,0 +1,17 @@
1
+ from label_studio_sdk._extensions.label_studio_tools.etl.registry import (
2
+ transform,
3
+ call_dataloader,
4
+ )
5
+
6
+
7
+ @transform.datarecords("read_base64_from_blob")
8
+ def gcs_blob_to_base64(
9
+ key: str,
10
+ bucket_name: str,
11
+ google_project_id: str = None,
12
+ ):
13
+ print(key, bucket_name)
14
+
15
+
16
+ if __name__ == "__main__":
17
+ call_dataloader("gcs_blob_reader", key=12, bucket_name=34)
@@ -0,0 +1,67 @@
1
+ import logging
2
+
3
+ from functools import wraps
4
+ from typing import Callable, Iterable, Dict, Any
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ class extract:
10
+ pass
11
+
12
+
13
+ class transform:
14
+ DataRecords = Iterable[Dict[str, Any]]
15
+ DataRecordsProducer = Callable[..., DataRecords]
16
+
17
+ class NameAlreadyExists(KeyError):
18
+ pass
19
+
20
+ class NameNotFound(NotImplementedError):
21
+ pass
22
+
23
+ class WrongOutput(ValueError):
24
+ pass
25
+
26
+ registry = {}
27
+
28
+ @staticmethod
29
+ def datarecords(name: str = None):
30
+ """Class method to register transform function to produce DataRecords
31
+ with specified name to the internal registry.
32
+ Can output any iterable for dicts (generators, iterators, list, tuples)
33
+ For example:
34
+
35
+ @transform.datarecords("DataRecords from GCS file")
36
+ def read_image(bucket_name, key):
37
+ yield {"image": blob.download_as_string()}
38
+ """
39
+
40
+ def register_transform_func(
41
+ transform_func: transform.DataRecordsProducer,
42
+ ) -> transform.DataRecordsProducer:
43
+ if name in transform.registry:
44
+ raise transform.NameAlreadyExists(
45
+ f"Dataloader {name} already exists. Will replace it"
46
+ )
47
+ transform.registry[name] = transform_func
48
+
49
+ @wraps(transform_func)
50
+ def inner_call_transform_func(*args, **kwargs) -> transform.DataRecords:
51
+ data_records = transform_func(*args, **kwargs)
52
+ # TODO: assert Data record type in a proper way, typing.assert_type is supported in Python 3.11
53
+ return data_records
54
+
55
+ return inner_call_transform_func
56
+
57
+ return register_transform_func
58
+
59
+ @staticmethod
60
+ def invoke(name, *args, **kwargs):
61
+ if name not in transform.registry:
62
+ raise transform.NameNotFound(name)
63
+ return transform.registry[name](*args, **kwargs)
64
+
65
+
66
+ class load:
67
+ pass
@@ -0,0 +1,97 @@
1
+ from copy import deepcopy
2
+ from operator import itemgetter
3
+
4
+ from label_studio_sdk._extensions.label_studio_tools.core.label_config import (
5
+ _VIDEO_TRACKING_TAGS,
6
+ )
7
+
8
+
9
+ def extract_key_frames(results):
10
+ """
11
+ Extract frames from key frames from video annotation results
12
+ :param results: Annotation results
13
+ :return: Frames in LS format
14
+ """
15
+ final_results = []
16
+ for result in results:
17
+ temp = deepcopy(result)
18
+ if result["type"].lower() not in _VIDEO_TRACKING_TAGS:
19
+ final_results.append(result)
20
+ continue
21
+ sequence = result["value"]["sequence"]
22
+ if len(sequence) < 1:
23
+ continue
24
+ sequence = sorted(sequence, key=lambda d: d["frame"])
25
+ exclude_first = False
26
+ for i in range(len(sequence)):
27
+ frame_a = sequence[i]
28
+ frame_b = {} if i == len(sequence) - 1 else sequence[i + 1]
29
+ temp["value"]["sequence"].extend(
30
+ _construct_result_from_frames(
31
+ frame1=frame_a,
32
+ frame2=frame_b,
33
+ frameCount=result["value"].get("framesCount", 0),
34
+ duration=result["value"].get("duration", 0),
35
+ exclude_first=exclude_first,
36
+ )
37
+ )
38
+ exclude_first = frame_a["enabled"]
39
+ temp["value"]["sequence"] = sorted(
40
+ temp["value"]["sequence"], key=itemgetter("frame")
41
+ )
42
+ final_results.append(temp)
43
+ return final_results
44
+
45
+
46
+ def _construct_result_from_frames(
47
+ frame1, frame2, frameCount=0, duration=0, exclude_first=True
48
+ ):
49
+ """
50
+ Construct frames between 2 keyframes
51
+ :param frame1: First frame in sequence
52
+ :param frame2: Next frame in sequence
53
+ :param frameCount: Total frame count in the video
54
+ :param duration: Total duration of the video
55
+ :param exclude_first: Exclude first result to deduplicate results
56
+ :return: List of frames
57
+ """
58
+ final_results = []
59
+ if not frame1["enabled"]:
60
+ return []
61
+ if len(frame2) > 0:
62
+ if frame1["frame"] > frame2["frame"]:
63
+ return []
64
+ frame_count = frame2["frame"] - frame1["frame"] + 1
65
+ else:
66
+ frame_count = frameCount - frame1["frame"] + 1
67
+ start_i = 1 if exclude_first else 0
68
+ for i in range(start_i, frame_count):
69
+ frame_number = i + frame1["frame"]
70
+ delta = i / max(1, (frame_count - 1))
71
+ deltas = {}
72
+ for v in ["x", "y", "rotation", "width", "height", "time"]:
73
+ deltas[v] = (
74
+ 0
75
+ if (frame1[v] == frame2.get(v) or not frame2)
76
+ else (frame2.get(v, 0) - frame1[v]) * delta
77
+ )
78
+ result = deepcopy(frame1)
79
+ result.update(
80
+ {
81
+ "x": frame1["x"] + deltas["x"],
82
+ "y": frame1["y"] + deltas["y"],
83
+ "width": frame1["width"] + deltas["width"],
84
+ "height": frame1["height"] + deltas["height"],
85
+ "rotation": frame1["rotation"] + deltas["rotation"],
86
+ "frame": frame_number,
87
+ "time": round(frame1["time"] + deltas["time"], 2),
88
+ }
89
+ )
90
+ if frame_number not in [frame1.get("frame"), frame2.get("frame")]:
91
+ result["auto"] = True
92
+ if deltas["time"] == 0 and duration > 0:
93
+ result["time"] = round(
94
+ frame1["time"] + delta * (duration - frame1["time"]), 2
95
+ )
96
+ final_results.append(result)
97
+ return final_results
@@ -0,0 +1,49 @@
1
+ import typing
2
+ from label_studio_sdk.core.pagination import SyncPager, AsyncPager, T
3
+ from label_studio_sdk.core.api_error import ApiError
4
+
5
+ # This is a custom extension of the autogenerated SyncPager and AsyncPager classes
6
+ # that works with the Label Studio SDK's default pagination behavior
7
+ # that throws 404 errors at the end of the pagination.
8
+
9
+
10
+ class SyncPagerExt(SyncPager, typing.Generic[T]):
11
+
12
+ @classmethod
13
+ def from_sync_pager(cls, sync_pager: SyncPager) -> 'SyncPagerExt':
14
+ return cls(
15
+ get_next=sync_pager.get_next,
16
+ has_next=sync_pager.has_next,
17
+ items=sync_pager.items
18
+ )
19
+
20
+ def __iter__(self) -> typing.Iterator[T]: # type: ignore
21
+ # Extends the iterator to catch 404 errors at the end of the pagination
22
+ try:
23
+ for item in super().__iter__():
24
+ yield item
25
+ except ApiError as exc:
26
+ if exc.status_code == 404:
27
+ return
28
+ raise
29
+
30
+
31
+ class AsyncPagerExt(AsyncPager, typing.Generic[T]):
32
+
33
+ @classmethod
34
+ async def from_async_pager(cls, async_pager: AsyncPager) -> 'AsyncPagerExt':
35
+ return cls(
36
+ get_next=async_pager.get_next,
37
+ has_next=async_pager.has_next,
38
+ items=async_pager.items
39
+ )
40
+
41
+ async def __aiter__(self) -> typing.AsyncIterator[T]: # type: ignore
42
+ # Extends the iterator to catch 404 errors at the end of the pagination
43
+ try:
44
+ async for item in super().__aiter__():
45
+ yield item
46
+ except ApiError as exc:
47
+ if exc.status_code == 404:
48
+ return
49
+ raise
@@ -0,0 +1,11 @@
1
+ """ .. include::../docs/index.md
2
+ """
3
+
4
+ from .client import Client
5
+ from .project import Project
6
+ from .utils import parse_config
7
+
8
+ __pdoc__ = {"label_interface": False}
9
+
10
+
11
+ __version__ = '0.0.35.dev'