label-studio-sdk 2.0.5__py3-none-any.whl → 2.0.7__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 (92) hide show
  1. label_studio_sdk/__init__.py +70 -0
  2. label_studio_sdk/annotation_history/__init__.py +5 -0
  3. label_studio_sdk/annotation_history/client.py +415 -0
  4. label_studio_sdk/annotation_history/types/__init__.py +5 -0
  5. label_studio_sdk/annotation_history/types/annotation_history_delete_response.py +22 -0
  6. label_studio_sdk/annotation_reviews/__init__.py +2 -0
  7. label_studio_sdk/annotation_reviews/client.py +713 -0
  8. label_studio_sdk/base_client.py +20 -0
  9. label_studio_sdk/blueprints/__init__.py +2 -0
  10. label_studio_sdk/blueprints/client.py +272 -0
  11. label_studio_sdk/core/client_wrapper.py +2 -1
  12. label_studio_sdk/export_storage/__init__.py +2 -2
  13. label_studio_sdk/export_storage/azure_spi/__init__.py +2 -0
  14. label_studio_sdk/export_storage/azure_spi/client.py +1354 -0
  15. label_studio_sdk/export_storage/client.py +8 -0
  16. label_studio_sdk/export_storage/gcswif/__init__.py +2 -0
  17. label_studio_sdk/export_storage/gcswif/client.py +1376 -0
  18. label_studio_sdk/import_storage/__init__.py +2 -2
  19. label_studio_sdk/import_storage/azure_spi/__init__.py +2 -0
  20. label_studio_sdk/import_storage/azure_spi/client.py +1378 -0
  21. label_studio_sdk/import_storage/client.py +8 -0
  22. label_studio_sdk/import_storage/gcswif/__init__.py +2 -0
  23. label_studio_sdk/import_storage/gcswif/client.py +1400 -0
  24. label_studio_sdk/jwt_settings/client.py +10 -8
  25. label_studio_sdk/label_interface/control_tags.py +38 -0
  26. label_studio_sdk/label_interface/data_examples.json +10 -0
  27. label_studio_sdk/label_interface/interface.py +13 -0
  28. label_studio_sdk/label_interface/object_tags.py +9 -0
  29. label_studio_sdk/ml/client.py +124 -0
  30. label_studio_sdk/organizations/__init__.py +3 -2
  31. label_studio_sdk/organizations/client.py +536 -1
  32. label_studio_sdk/organizations/invites/__init__.py +2 -0
  33. label_studio_sdk/organizations/invites/client.py +368 -0
  34. label_studio_sdk/organizations/types/__init__.py +5 -0
  35. label_studio_sdk/organizations/types/patched_default_role_request_custom_scripts_editable_by.py +7 -0
  36. label_studio_sdk/project_templates/__init__.py +2 -0
  37. label_studio_sdk/project_templates/client.py +909 -0
  38. label_studio_sdk/projects/client.py +8 -0
  39. label_studio_sdk/projects/members/__init__.py +2 -2
  40. label_studio_sdk/projects/members/bulk/client.py +46 -2
  41. label_studio_sdk/projects/members/client.py +4 -0
  42. label_studio_sdk/projects/members/paginated/__init__.py +2 -0
  43. label_studio_sdk/projects/members/paginated/client.py +248 -0
  44. label_studio_sdk/session_policy/__init__.py +2 -0
  45. label_studio_sdk/session_policy/client.py +247 -0
  46. label_studio_sdk/tasks/client.py +371 -0
  47. label_studio_sdk/types/__init__.py +56 -0
  48. label_studio_sdk/types/action_enum.py +19 -0
  49. label_studio_sdk/types/all_roles_project_list.py +1 -1
  50. label_studio_sdk/types/annotation.py +7 -0
  51. label_studio_sdk/types/annotation_history.py +81 -0
  52. label_studio_sdk/types/annotation_history_action.py +7 -0
  53. label_studio_sdk/types/annotation_request.py +7 -0
  54. label_studio_sdk/types/annotation_review.py +61 -0
  55. label_studio_sdk/types/annotation_review_request.py +41 -0
  56. label_studio_sdk/types/azure_service_principal_export_storage.py +114 -0
  57. label_studio_sdk/types/azure_service_principal_export_storage_request.py +107 -0
  58. label_studio_sdk/types/azure_service_principal_import_storage.py +115 -0
  59. label_studio_sdk/types/azure_service_principal_import_storage_request.py +108 -0
  60. label_studio_sdk/types/blueprint.py +41 -0
  61. label_studio_sdk/types/default_role.py +75 -0
  62. label_studio_sdk/types/default_role_custom_scripts_editable_by.py +7 -0
  63. label_studio_sdk/types/gcswif_export_storage.py +119 -0
  64. label_studio_sdk/types/gcswif_export_storage_request.py +112 -0
  65. label_studio_sdk/types/gcswif_import_storage.py +120 -0
  66. label_studio_sdk/types/gcswif_import_storage_request.py +113 -0
  67. label_studio_sdk/types/lse_project.py +223 -0
  68. label_studio_sdk/types/lse_project_sampling.py +7 -0
  69. label_studio_sdk/types/lse_project_skip_queue.py +7 -0
  70. label_studio_sdk/types/lse_project_update.py +1 -0
  71. label_studio_sdk/types/lse_task.py +1 -0
  72. label_studio_sdk/types/lse_task_serializer_for_reviewers.py +1 -0
  73. label_studio_sdk/types/lsejwt_settings.py +1 -5
  74. label_studio_sdk/types/paginated_annotation_history_list.py +23 -0
  75. label_studio_sdk/types/paginated_lse_user_list.py +23 -0
  76. label_studio_sdk/types/paginated_paginated_project_member_list.py +23 -0
  77. label_studio_sdk/types/paginated_project_member.py +50 -0
  78. label_studio_sdk/types/project_member_bulk_assign_roles_request.py +21 -0
  79. label_studio_sdk/types/project_template.py +41 -0
  80. label_studio_sdk/types/project_template_request.py +38 -0
  81. label_studio_sdk/types/review_settings.py +5 -0
  82. label_studio_sdk/types/review_settings_request.py +5 -0
  83. label_studio_sdk/types/session_timeout_policy.py +31 -0
  84. label_studio_sdk/types/task_event.py +61 -0
  85. label_studio_sdk/workspaces/members/__init__.py +2 -2
  86. label_studio_sdk/workspaces/members/client.py +4 -0
  87. label_studio_sdk/workspaces/members/paginated/__init__.py +2 -0
  88. label_studio_sdk/workspaces/members/paginated/client.py +212 -0
  89. {label_studio_sdk-2.0.5.dist-info → label_studio_sdk-2.0.7.dist-info}/METADATA +2 -2
  90. {label_studio_sdk-2.0.5.dist-info → label_studio_sdk-2.0.7.dist-info}/RECORD +92 -36
  91. {label_studio_sdk-2.0.5.dist-info → label_studio_sdk-2.0.7.dist-info}/LICENSE +0 -0
  92. {label_studio_sdk-2.0.5.dist-info → label_studio_sdk-2.0.7.dist-info}/WHEEL +0 -0
@@ -0,0 +1,247 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+ from ..core.client_wrapper import SyncClientWrapper
5
+ from ..core.request_options import RequestOptions
6
+ from ..types.session_timeout_policy import SessionTimeoutPolicy
7
+ from ..core.unchecked_base_model import construct_type
8
+ from json.decoder import JSONDecodeError
9
+ from ..core.api_error import ApiError
10
+ from ..core.client_wrapper import AsyncClientWrapper
11
+
12
+ # this is used as the default value for optional parameters
13
+ OMIT = typing.cast(typing.Any, ...)
14
+
15
+
16
+ class SessionPolicyClient:
17
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
18
+ self._client_wrapper = client_wrapper
19
+
20
+ def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> SessionTimeoutPolicy:
21
+ """
22
+ Retrieve session timeout policy for the currently active organization.
23
+
24
+ Parameters
25
+ ----------
26
+ request_options : typing.Optional[RequestOptions]
27
+ Request-specific configuration.
28
+
29
+ Returns
30
+ -------
31
+ SessionTimeoutPolicy
32
+
33
+
34
+ Examples
35
+ --------
36
+ from label_studio_sdk import LabelStudio
37
+
38
+ client = LabelStudio(
39
+ api_key="YOUR_API_KEY",
40
+ )
41
+ client.session_policy.get()
42
+ """
43
+ _response = self._client_wrapper.httpx_client.request(
44
+ "api/session-policy/",
45
+ method="GET",
46
+ request_options=request_options,
47
+ )
48
+ try:
49
+ if 200 <= _response.status_code < 300:
50
+ return typing.cast(
51
+ SessionTimeoutPolicy,
52
+ construct_type(
53
+ type_=SessionTimeoutPolicy, # type: ignore
54
+ object_=_response.json(),
55
+ ),
56
+ )
57
+ _response_json = _response.json()
58
+ except JSONDecodeError:
59
+ raise ApiError(status_code=_response.status_code, body=_response.text)
60
+ raise ApiError(status_code=_response.status_code, body=_response_json)
61
+
62
+ def update(
63
+ self,
64
+ *,
65
+ max_session_age: typing.Optional[int] = OMIT,
66
+ max_time_between_activity: typing.Optional[int] = OMIT,
67
+ request_options: typing.Optional[RequestOptions] = None,
68
+ ) -> SessionTimeoutPolicy:
69
+ """
70
+ Update session timeout policy for the currently active organization.
71
+
72
+ Parameters
73
+ ----------
74
+ max_session_age : typing.Optional[int]
75
+ Number of minutes that a session can be active before needing to re-login
76
+
77
+ max_time_between_activity : typing.Optional[int]
78
+ Number of minutes that a session stays active without any activity
79
+
80
+ request_options : typing.Optional[RequestOptions]
81
+ Request-specific configuration.
82
+
83
+ Returns
84
+ -------
85
+ SessionTimeoutPolicy
86
+
87
+
88
+ Examples
89
+ --------
90
+ from label_studio_sdk import LabelStudio
91
+
92
+ client = LabelStudio(
93
+ api_key="YOUR_API_KEY",
94
+ )
95
+ client.session_policy.update()
96
+ """
97
+ _response = self._client_wrapper.httpx_client.request(
98
+ "api/session-policy/",
99
+ method="PATCH",
100
+ json={
101
+ "max_session_age": max_session_age,
102
+ "max_time_between_activity": max_time_between_activity,
103
+ },
104
+ headers={
105
+ "content-type": "application/json",
106
+ },
107
+ request_options=request_options,
108
+ omit=OMIT,
109
+ )
110
+ try:
111
+ if 200 <= _response.status_code < 300:
112
+ return typing.cast(
113
+ SessionTimeoutPolicy,
114
+ construct_type(
115
+ type_=SessionTimeoutPolicy, # type: ignore
116
+ object_=_response.json(),
117
+ ),
118
+ )
119
+ _response_json = _response.json()
120
+ except JSONDecodeError:
121
+ raise ApiError(status_code=_response.status_code, body=_response.text)
122
+ raise ApiError(status_code=_response.status_code, body=_response_json)
123
+
124
+
125
+ class AsyncSessionPolicyClient:
126
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
127
+ self._client_wrapper = client_wrapper
128
+
129
+ async def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> SessionTimeoutPolicy:
130
+ """
131
+ Retrieve session timeout policy for the currently active organization.
132
+
133
+ Parameters
134
+ ----------
135
+ request_options : typing.Optional[RequestOptions]
136
+ Request-specific configuration.
137
+
138
+ Returns
139
+ -------
140
+ SessionTimeoutPolicy
141
+
142
+
143
+ Examples
144
+ --------
145
+ import asyncio
146
+
147
+ from label_studio_sdk import AsyncLabelStudio
148
+
149
+ client = AsyncLabelStudio(
150
+ api_key="YOUR_API_KEY",
151
+ )
152
+
153
+
154
+ async def main() -> None:
155
+ await client.session_policy.get()
156
+
157
+
158
+ asyncio.run(main())
159
+ """
160
+ _response = await self._client_wrapper.httpx_client.request(
161
+ "api/session-policy/",
162
+ method="GET",
163
+ request_options=request_options,
164
+ )
165
+ try:
166
+ if 200 <= _response.status_code < 300:
167
+ return typing.cast(
168
+ SessionTimeoutPolicy,
169
+ construct_type(
170
+ type_=SessionTimeoutPolicy, # type: ignore
171
+ object_=_response.json(),
172
+ ),
173
+ )
174
+ _response_json = _response.json()
175
+ except JSONDecodeError:
176
+ raise ApiError(status_code=_response.status_code, body=_response.text)
177
+ raise ApiError(status_code=_response.status_code, body=_response_json)
178
+
179
+ async def update(
180
+ self,
181
+ *,
182
+ max_session_age: typing.Optional[int] = OMIT,
183
+ max_time_between_activity: typing.Optional[int] = OMIT,
184
+ request_options: typing.Optional[RequestOptions] = None,
185
+ ) -> SessionTimeoutPolicy:
186
+ """
187
+ Update session timeout policy for the currently active organization.
188
+
189
+ Parameters
190
+ ----------
191
+ max_session_age : typing.Optional[int]
192
+ Number of minutes that a session can be active before needing to re-login
193
+
194
+ max_time_between_activity : typing.Optional[int]
195
+ Number of minutes that a session stays active without any activity
196
+
197
+ request_options : typing.Optional[RequestOptions]
198
+ Request-specific configuration.
199
+
200
+ Returns
201
+ -------
202
+ SessionTimeoutPolicy
203
+
204
+
205
+ Examples
206
+ --------
207
+ import asyncio
208
+
209
+ from label_studio_sdk import AsyncLabelStudio
210
+
211
+ client = AsyncLabelStudio(
212
+ api_key="YOUR_API_KEY",
213
+ )
214
+
215
+
216
+ async def main() -> None:
217
+ await client.session_policy.update()
218
+
219
+
220
+ asyncio.run(main())
221
+ """
222
+ _response = await self._client_wrapper.httpx_client.request(
223
+ "api/session-policy/",
224
+ method="PATCH",
225
+ json={
226
+ "max_session_age": max_session_age,
227
+ "max_time_between_activity": max_time_between_activity,
228
+ },
229
+ headers={
230
+ "content-type": "application/json",
231
+ },
232
+ request_options=request_options,
233
+ omit=OMIT,
234
+ )
235
+ try:
236
+ if 200 <= _response.status_code < 300:
237
+ return typing.cast(
238
+ SessionTimeoutPolicy,
239
+ construct_type(
240
+ type_=SessionTimeoutPolicy, # type: ignore
241
+ object_=_response.json(),
242
+ ),
243
+ )
244
+ _response_json = _response.json()
245
+ except JSONDecodeError:
246
+ raise ApiError(status_code=_response.status_code, body=_response.text)
247
+ raise ApiError(status_code=_response.status_code, body=_response_json)
@@ -17,6 +17,8 @@ from ..errors.unauthorized_error import UnauthorizedError
17
17
  from ..errors.forbidden_error import ForbiddenError
18
18
  import datetime as dt
19
19
  from ..types.lse_task import LseTask
20
+ from ..types.task_event import TaskEvent
21
+ from ..errors.not_found_error import NotFoundError
20
22
  from ..core.client_wrapper import AsyncClientWrapper
21
23
  from ..core.pagination import AsyncPager
22
24
 
@@ -644,6 +646,187 @@ class TasksClient:
644
646
  raise ApiError(status_code=_response.status_code, body=_response.text)
645
647
  raise ApiError(status_code=_response.status_code, body=_response_json)
646
648
 
649
+ def create_event(
650
+ self,
651
+ id: int,
652
+ *,
653
+ event_key: str,
654
+ event_time: dt.datetime,
655
+ annotation: typing.Optional[int] = OMIT,
656
+ annotation_draft: typing.Optional[int] = OMIT,
657
+ meta: typing.Optional[typing.Optional[typing.Any]] = OMIT,
658
+ review: typing.Optional[int] = OMIT,
659
+ request_options: typing.Optional[RequestOptions] = None,
660
+ ) -> TaskEvent:
661
+ """
662
+
663
+ Create a new task event to track user interactions and system events during annotation.
664
+
665
+ This endpoint is designed to receive events from the frontend labeling interface to enable
666
+ accurate lead time calculation and detailed annotation analytics.
667
+
668
+ ## Event Types
669
+
670
+ **Core Annotation Events:**
671
+ - `annotation_loaded` - When annotation interface is loaded
672
+ - `annotation_submitted` - When annotation is submitted
673
+ - `annotation_updated` - When annotation is modified
674
+ - `annotation_reviewed` - When annotation is reviewed
675
+
676
+ **User Activity Events:**
677
+ - `visibility_change` - When page visibility changes (tab switch, minimize)
678
+ - `idle_detected` - When user goes idle
679
+ - `idle_resumed` - When user returns from idle
680
+
681
+ **Interaction Events:**
682
+ - `region_finished_drawing` - When annotation region is completed
683
+ - `region_deleted` - When annotation regions are removed
684
+ - `hotkey_pressed` - When keyboard shortcuts are used
685
+
686
+ **Media Events:**
687
+ - `video_playback_start/end` - Video playback control
688
+ - `audio_playback_start/end` - Audio playback control
689
+ - `video_scrub` - Video timeline scrubbing
690
+
691
+ ## Usage
692
+
693
+ Events are automatically associated with the task specified in the URL path.
694
+ The current user is automatically set as the actor. Project and organization
695
+ are derived from the task context.
696
+
697
+ ## Example Request
698
+
699
+ ```json
700
+ {
701
+ "event_key": "annotation_loaded",
702
+ "event_time": "2024-01-15T10:30:00Z",
703
+ "annotation": 123,
704
+ "meta": {
705
+ "annotation_count": 5,
706
+ "estimated_time": 300
707
+ }
708
+ }
709
+ ```
710
+
711
+
712
+ Parameters
713
+ ----------
714
+ id : int
715
+ Task ID to associate the event with
716
+
717
+ event_key : str
718
+ Event type identifier (e.g., "annotation_loaded", "region_finished_drawing")
719
+
720
+ event_time : dt.datetime
721
+ Timestamp when the event occurred (frontend time)
722
+
723
+ annotation : typing.Optional[int]
724
+ Annotation ID associated with this event
725
+
726
+ annotation_draft : typing.Optional[int]
727
+ Draft annotation ID associated with this event
728
+
729
+ meta : typing.Optional[typing.Optional[typing.Any]]
730
+
731
+ review : typing.Optional[int]
732
+ Review ID associated with this event
733
+
734
+ request_options : typing.Optional[RequestOptions]
735
+ Request-specific configuration.
736
+
737
+ Returns
738
+ -------
739
+ TaskEvent
740
+
741
+
742
+ Examples
743
+ --------
744
+ import datetime
745
+
746
+ from label_studio_sdk import LabelStudio
747
+
748
+ client = LabelStudio(
749
+ api_key="YOUR_API_KEY",
750
+ )
751
+ client.tasks.create_event(
752
+ id=1,
753
+ event_key="event_key",
754
+ event_time=datetime.datetime.fromisoformat(
755
+ "2024-01-15 09:30:00+00:00",
756
+ ),
757
+ )
758
+ """
759
+ _response = self._client_wrapper.httpx_client.request(
760
+ f"api/tasks/{jsonable_encoder(id)}/events/",
761
+ method="POST",
762
+ json={
763
+ "annotation": annotation,
764
+ "annotation_draft": annotation_draft,
765
+ "event_key": event_key,
766
+ "event_time": event_time,
767
+ "meta": meta,
768
+ "review": review,
769
+ },
770
+ headers={
771
+ "content-type": "application/json",
772
+ },
773
+ request_options=request_options,
774
+ omit=OMIT,
775
+ )
776
+ try:
777
+ if 200 <= _response.status_code < 300:
778
+ return typing.cast(
779
+ TaskEvent,
780
+ construct_type(
781
+ type_=TaskEvent, # type: ignore
782
+ object_=_response.json(),
783
+ ),
784
+ )
785
+ if _response.status_code == 400:
786
+ raise BadRequestError(
787
+ typing.cast(
788
+ typing.Optional[typing.Any],
789
+ construct_type(
790
+ type_=typing.Optional[typing.Any], # type: ignore
791
+ object_=_response.json(),
792
+ ),
793
+ )
794
+ )
795
+ if _response.status_code == 401:
796
+ raise UnauthorizedError(
797
+ typing.cast(
798
+ typing.Optional[typing.Any],
799
+ construct_type(
800
+ type_=typing.Optional[typing.Any], # type: ignore
801
+ object_=_response.json(),
802
+ ),
803
+ )
804
+ )
805
+ if _response.status_code == 403:
806
+ raise ForbiddenError(
807
+ typing.cast(
808
+ typing.Optional[typing.Any],
809
+ construct_type(
810
+ type_=typing.Optional[typing.Any], # type: ignore
811
+ object_=_response.json(),
812
+ ),
813
+ )
814
+ )
815
+ if _response.status_code == 404:
816
+ raise NotFoundError(
817
+ typing.cast(
818
+ typing.Optional[typing.Any],
819
+ construct_type(
820
+ type_=typing.Optional[typing.Any], # type: ignore
821
+ object_=_response.json(),
822
+ ),
823
+ )
824
+ )
825
+ _response_json = _response.json()
826
+ except JSONDecodeError:
827
+ raise ApiError(status_code=_response.status_code, body=_response.text)
828
+ raise ApiError(status_code=_response.status_code, body=_response_json)
829
+
647
830
 
648
831
  class AsyncTasksClient:
649
832
  def __init__(self, *, client_wrapper: AsyncClientWrapper):
@@ -1320,3 +1503,191 @@ class AsyncTasksClient:
1320
1503
  except JSONDecodeError:
1321
1504
  raise ApiError(status_code=_response.status_code, body=_response.text)
1322
1505
  raise ApiError(status_code=_response.status_code, body=_response_json)
1506
+
1507
+ async def create_event(
1508
+ self,
1509
+ id: int,
1510
+ *,
1511
+ event_key: str,
1512
+ event_time: dt.datetime,
1513
+ annotation: typing.Optional[int] = OMIT,
1514
+ annotation_draft: typing.Optional[int] = OMIT,
1515
+ meta: typing.Optional[typing.Optional[typing.Any]] = OMIT,
1516
+ review: typing.Optional[int] = OMIT,
1517
+ request_options: typing.Optional[RequestOptions] = None,
1518
+ ) -> TaskEvent:
1519
+ """
1520
+
1521
+ Create a new task event to track user interactions and system events during annotation.
1522
+
1523
+ This endpoint is designed to receive events from the frontend labeling interface to enable
1524
+ accurate lead time calculation and detailed annotation analytics.
1525
+
1526
+ ## Event Types
1527
+
1528
+ **Core Annotation Events:**
1529
+ - `annotation_loaded` - When annotation interface is loaded
1530
+ - `annotation_submitted` - When annotation is submitted
1531
+ - `annotation_updated` - When annotation is modified
1532
+ - `annotation_reviewed` - When annotation is reviewed
1533
+
1534
+ **User Activity Events:**
1535
+ - `visibility_change` - When page visibility changes (tab switch, minimize)
1536
+ - `idle_detected` - When user goes idle
1537
+ - `idle_resumed` - When user returns from idle
1538
+
1539
+ **Interaction Events:**
1540
+ - `region_finished_drawing` - When annotation region is completed
1541
+ - `region_deleted` - When annotation regions are removed
1542
+ - `hotkey_pressed` - When keyboard shortcuts are used
1543
+
1544
+ **Media Events:**
1545
+ - `video_playback_start/end` - Video playback control
1546
+ - `audio_playback_start/end` - Audio playback control
1547
+ - `video_scrub` - Video timeline scrubbing
1548
+
1549
+ ## Usage
1550
+
1551
+ Events are automatically associated with the task specified in the URL path.
1552
+ The current user is automatically set as the actor. Project and organization
1553
+ are derived from the task context.
1554
+
1555
+ ## Example Request
1556
+
1557
+ ```json
1558
+ {
1559
+ "event_key": "annotation_loaded",
1560
+ "event_time": "2024-01-15T10:30:00Z",
1561
+ "annotation": 123,
1562
+ "meta": {
1563
+ "annotation_count": 5,
1564
+ "estimated_time": 300
1565
+ }
1566
+ }
1567
+ ```
1568
+
1569
+
1570
+ Parameters
1571
+ ----------
1572
+ id : int
1573
+ Task ID to associate the event with
1574
+
1575
+ event_key : str
1576
+ Event type identifier (e.g., "annotation_loaded", "region_finished_drawing")
1577
+
1578
+ event_time : dt.datetime
1579
+ Timestamp when the event occurred (frontend time)
1580
+
1581
+ annotation : typing.Optional[int]
1582
+ Annotation ID associated with this event
1583
+
1584
+ annotation_draft : typing.Optional[int]
1585
+ Draft annotation ID associated with this event
1586
+
1587
+ meta : typing.Optional[typing.Optional[typing.Any]]
1588
+
1589
+ review : typing.Optional[int]
1590
+ Review ID associated with this event
1591
+
1592
+ request_options : typing.Optional[RequestOptions]
1593
+ Request-specific configuration.
1594
+
1595
+ Returns
1596
+ -------
1597
+ TaskEvent
1598
+
1599
+
1600
+ Examples
1601
+ --------
1602
+ import asyncio
1603
+ import datetime
1604
+
1605
+ from label_studio_sdk import AsyncLabelStudio
1606
+
1607
+ client = AsyncLabelStudio(
1608
+ api_key="YOUR_API_KEY",
1609
+ )
1610
+
1611
+
1612
+ async def main() -> None:
1613
+ await client.tasks.create_event(
1614
+ id=1,
1615
+ event_key="event_key",
1616
+ event_time=datetime.datetime.fromisoformat(
1617
+ "2024-01-15 09:30:00+00:00",
1618
+ ),
1619
+ )
1620
+
1621
+
1622
+ asyncio.run(main())
1623
+ """
1624
+ _response = await self._client_wrapper.httpx_client.request(
1625
+ f"api/tasks/{jsonable_encoder(id)}/events/",
1626
+ method="POST",
1627
+ json={
1628
+ "annotation": annotation,
1629
+ "annotation_draft": annotation_draft,
1630
+ "event_key": event_key,
1631
+ "event_time": event_time,
1632
+ "meta": meta,
1633
+ "review": review,
1634
+ },
1635
+ headers={
1636
+ "content-type": "application/json",
1637
+ },
1638
+ request_options=request_options,
1639
+ omit=OMIT,
1640
+ )
1641
+ try:
1642
+ if 200 <= _response.status_code < 300:
1643
+ return typing.cast(
1644
+ TaskEvent,
1645
+ construct_type(
1646
+ type_=TaskEvent, # type: ignore
1647
+ object_=_response.json(),
1648
+ ),
1649
+ )
1650
+ if _response.status_code == 400:
1651
+ raise BadRequestError(
1652
+ typing.cast(
1653
+ typing.Optional[typing.Any],
1654
+ construct_type(
1655
+ type_=typing.Optional[typing.Any], # type: ignore
1656
+ object_=_response.json(),
1657
+ ),
1658
+ )
1659
+ )
1660
+ if _response.status_code == 401:
1661
+ raise UnauthorizedError(
1662
+ typing.cast(
1663
+ typing.Optional[typing.Any],
1664
+ construct_type(
1665
+ type_=typing.Optional[typing.Any], # type: ignore
1666
+ object_=_response.json(),
1667
+ ),
1668
+ )
1669
+ )
1670
+ if _response.status_code == 403:
1671
+ raise ForbiddenError(
1672
+ typing.cast(
1673
+ typing.Optional[typing.Any],
1674
+ construct_type(
1675
+ type_=typing.Optional[typing.Any], # type: ignore
1676
+ object_=_response.json(),
1677
+ ),
1678
+ )
1679
+ )
1680
+ if _response.status_code == 404:
1681
+ raise NotFoundError(
1682
+ typing.cast(
1683
+ typing.Optional[typing.Any],
1684
+ construct_type(
1685
+ type_=typing.Optional[typing.Any], # type: ignore
1686
+ object_=_response.json(),
1687
+ ),
1688
+ )
1689
+ )
1690
+ _response_json = _response.json()
1691
+ except JSONDecodeError:
1692
+ raise ApiError(status_code=_response.status_code, body=_response.text)
1693
+ raise ApiError(status_code=_response.status_code, body=_response_json)