label-studio-sdk 1.0.10__py3-none-any.whl → 1.0.12__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 +21 -1
- label_studio_sdk/_extensions/label_studio_tools/core/utils/json_schema.py +5 -0
- label_studio_sdk/base_client.py +8 -0
- label_studio_sdk/converter/converter.py +22 -0
- label_studio_sdk/converter/exports/brush_to_coco.py +332 -0
- label_studio_sdk/converter/main.py +14 -0
- label_studio_sdk/core/client_wrapper.py +34 -15
- label_studio_sdk/errors/__init__.py +3 -1
- label_studio_sdk/errors/not_found_error.py +9 -0
- label_studio_sdk/errors/unauthorized_error.py +9 -0
- label_studio_sdk/jwt_settings/__init__.py +2 -0
- label_studio_sdk/jwt_settings/client.py +259 -0
- label_studio_sdk/label_interface/control_tags.py +15 -2
- label_studio_sdk/label_interface/interface.py +80 -1
- label_studio_sdk/label_interface/object_tags.py +2 -2
- label_studio_sdk/projects/__init__.py +2 -1
- label_studio_sdk/projects/client.py +4 -0
- label_studio_sdk/projects/exports/client_ext.py +106 -40
- label_studio_sdk/projects/pauses/__init__.py +2 -0
- label_studio_sdk/projects/pauses/client.py +704 -0
- label_studio_sdk/projects/types/projects_update_response.py +10 -0
- label_studio_sdk/tokens/__init__.py +2 -0
- label_studio_sdk/tokens/client.py +610 -0
- label_studio_sdk/tokens/client_ext.py +94 -0
- label_studio_sdk/types/__init__.py +14 -0
- label_studio_sdk/types/access_token_response.py +22 -0
- label_studio_sdk/types/annotation.py +2 -1
- label_studio_sdk/types/annotation_completed_by.py +6 -0
- label_studio_sdk/types/api_token_response.py +32 -0
- label_studio_sdk/types/jwt_settings_response.py +32 -0
- label_studio_sdk/types/model_provider_connection_provider.py +1 -1
- label_studio_sdk/types/pause.py +34 -0
- label_studio_sdk/types/pause_paused_by.py +5 -0
- label_studio_sdk/types/project.py +10 -0
- label_studio_sdk/types/prompt_version_provider.py +1 -1
- label_studio_sdk/types/rotate_token_response.py +22 -0
- {label_studio_sdk-1.0.10.dist-info → label_studio_sdk-1.0.12.dist-info}/METADATA +3 -2
- {label_studio_sdk-1.0.10.dist-info → label_studio_sdk-1.0.12.dist-info}/RECORD +40 -23
- {label_studio_sdk-1.0.10.dist-info → label_studio_sdk-1.0.12.dist-info}/WHEEL +1 -1
- {label_studio_sdk-1.0.10.dist-info → label_studio_sdk-1.0.12.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
|
2
|
+
|
|
3
|
+
from ..core.api_error import ApiError
|
|
4
|
+
import typing
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class UnauthorizedError(ApiError):
|
|
8
|
+
def __init__(self, body: typing.Optional[typing.Any]):
|
|
9
|
+
super().__init__(status_code=401, body=body)
|
|
@@ -0,0 +1,259 @@
|
|
|
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.jwt_settings_response import JwtSettingsResponse
|
|
7
|
+
from ..core.pydantic_utilities import parse_obj_as
|
|
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 JwtSettingsClient:
|
|
17
|
+
def __init__(self, *, client_wrapper: SyncClientWrapper):
|
|
18
|
+
self._client_wrapper = client_wrapper
|
|
19
|
+
|
|
20
|
+
def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> JwtSettingsResponse:
|
|
21
|
+
"""
|
|
22
|
+
Retrieve JWT settings for the currently-active organization.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
request_options : typing.Optional[RequestOptions]
|
|
27
|
+
Request-specific configuration.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
JwtSettingsResponse
|
|
32
|
+
JWT settings retrieved successfully
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
from label_studio_sdk import LabelStudio
|
|
37
|
+
|
|
38
|
+
client = LabelStudio(
|
|
39
|
+
api_key="YOUR_API_KEY",
|
|
40
|
+
)
|
|
41
|
+
client.jwt_settings.get()
|
|
42
|
+
"""
|
|
43
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
44
|
+
"api/jwt/settings",
|
|
45
|
+
method="GET",
|
|
46
|
+
request_options=request_options,
|
|
47
|
+
)
|
|
48
|
+
try:
|
|
49
|
+
if 200 <= _response.status_code < 300:
|
|
50
|
+
return typing.cast(
|
|
51
|
+
JwtSettingsResponse,
|
|
52
|
+
parse_obj_as(
|
|
53
|
+
type_=JwtSettingsResponse, # 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 create(
|
|
63
|
+
self,
|
|
64
|
+
*,
|
|
65
|
+
api_tokens_enabled: bool,
|
|
66
|
+
legacy_api_tokens_enabled: bool,
|
|
67
|
+
api_token_ttl_days: int,
|
|
68
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
69
|
+
) -> JwtSettingsResponse:
|
|
70
|
+
"""
|
|
71
|
+
Update JWT settings for the currently active organization.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
api_tokens_enabled : bool
|
|
76
|
+
Whether JWT API tokens are enabled
|
|
77
|
+
|
|
78
|
+
legacy_api_tokens_enabled : bool
|
|
79
|
+
Whether legacy API tokens are enabled
|
|
80
|
+
|
|
81
|
+
api_token_ttl_days : int
|
|
82
|
+
Number of days before API tokens expire
|
|
83
|
+
|
|
84
|
+
request_options : typing.Optional[RequestOptions]
|
|
85
|
+
Request-specific configuration.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
JwtSettingsResponse
|
|
90
|
+
JWT settings updated successfully
|
|
91
|
+
|
|
92
|
+
Examples
|
|
93
|
+
--------
|
|
94
|
+
from label_studio_sdk import LabelStudio
|
|
95
|
+
|
|
96
|
+
client = LabelStudio(
|
|
97
|
+
api_key="YOUR_API_KEY",
|
|
98
|
+
)
|
|
99
|
+
client.jwt_settings.create(
|
|
100
|
+
api_tokens_enabled=True,
|
|
101
|
+
legacy_api_tokens_enabled=True,
|
|
102
|
+
api_token_ttl_days=1,
|
|
103
|
+
)
|
|
104
|
+
"""
|
|
105
|
+
_response = self._client_wrapper.httpx_client.request(
|
|
106
|
+
"api/jwt/settings",
|
|
107
|
+
method="POST",
|
|
108
|
+
json={
|
|
109
|
+
"api_tokens_enabled": api_tokens_enabled,
|
|
110
|
+
"legacy_api_tokens_enabled": legacy_api_tokens_enabled,
|
|
111
|
+
"api_token_ttl_days": api_token_ttl_days,
|
|
112
|
+
},
|
|
113
|
+
request_options=request_options,
|
|
114
|
+
omit=OMIT,
|
|
115
|
+
)
|
|
116
|
+
try:
|
|
117
|
+
if 200 <= _response.status_code < 300:
|
|
118
|
+
return typing.cast(
|
|
119
|
+
JwtSettingsResponse,
|
|
120
|
+
parse_obj_as(
|
|
121
|
+
type_=JwtSettingsResponse, # type: ignore
|
|
122
|
+
object_=_response.json(),
|
|
123
|
+
),
|
|
124
|
+
)
|
|
125
|
+
_response_json = _response.json()
|
|
126
|
+
except JSONDecodeError:
|
|
127
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
128
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class AsyncJwtSettingsClient:
|
|
132
|
+
def __init__(self, *, client_wrapper: AsyncClientWrapper):
|
|
133
|
+
self._client_wrapper = client_wrapper
|
|
134
|
+
|
|
135
|
+
async def get(self, *, request_options: typing.Optional[RequestOptions] = None) -> JwtSettingsResponse:
|
|
136
|
+
"""
|
|
137
|
+
Retrieve JWT settings for the currently-active organization.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
request_options : typing.Optional[RequestOptions]
|
|
142
|
+
Request-specific configuration.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
JwtSettingsResponse
|
|
147
|
+
JWT settings retrieved successfully
|
|
148
|
+
|
|
149
|
+
Examples
|
|
150
|
+
--------
|
|
151
|
+
import asyncio
|
|
152
|
+
|
|
153
|
+
from label_studio_sdk import AsyncLabelStudio
|
|
154
|
+
|
|
155
|
+
client = AsyncLabelStudio(
|
|
156
|
+
api_key="YOUR_API_KEY",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
async def main() -> None:
|
|
161
|
+
await client.jwt_settings.get()
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
asyncio.run(main())
|
|
165
|
+
"""
|
|
166
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
167
|
+
"api/jwt/settings",
|
|
168
|
+
method="GET",
|
|
169
|
+
request_options=request_options,
|
|
170
|
+
)
|
|
171
|
+
try:
|
|
172
|
+
if 200 <= _response.status_code < 300:
|
|
173
|
+
return typing.cast(
|
|
174
|
+
JwtSettingsResponse,
|
|
175
|
+
parse_obj_as(
|
|
176
|
+
type_=JwtSettingsResponse, # type: ignore
|
|
177
|
+
object_=_response.json(),
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
_response_json = _response.json()
|
|
181
|
+
except JSONDecodeError:
|
|
182
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
183
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
|
184
|
+
|
|
185
|
+
async def create(
|
|
186
|
+
self,
|
|
187
|
+
*,
|
|
188
|
+
api_tokens_enabled: bool,
|
|
189
|
+
legacy_api_tokens_enabled: bool,
|
|
190
|
+
api_token_ttl_days: int,
|
|
191
|
+
request_options: typing.Optional[RequestOptions] = None,
|
|
192
|
+
) -> JwtSettingsResponse:
|
|
193
|
+
"""
|
|
194
|
+
Update JWT settings for the currently active organization.
|
|
195
|
+
|
|
196
|
+
Parameters
|
|
197
|
+
----------
|
|
198
|
+
api_tokens_enabled : bool
|
|
199
|
+
Whether JWT API tokens are enabled
|
|
200
|
+
|
|
201
|
+
legacy_api_tokens_enabled : bool
|
|
202
|
+
Whether legacy API tokens are enabled
|
|
203
|
+
|
|
204
|
+
api_token_ttl_days : int
|
|
205
|
+
Number of days before API tokens expire
|
|
206
|
+
|
|
207
|
+
request_options : typing.Optional[RequestOptions]
|
|
208
|
+
Request-specific configuration.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
JwtSettingsResponse
|
|
213
|
+
JWT settings updated successfully
|
|
214
|
+
|
|
215
|
+
Examples
|
|
216
|
+
--------
|
|
217
|
+
import asyncio
|
|
218
|
+
|
|
219
|
+
from label_studio_sdk import AsyncLabelStudio
|
|
220
|
+
|
|
221
|
+
client = AsyncLabelStudio(
|
|
222
|
+
api_key="YOUR_API_KEY",
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
async def main() -> None:
|
|
227
|
+
await client.jwt_settings.create(
|
|
228
|
+
api_tokens_enabled=True,
|
|
229
|
+
legacy_api_tokens_enabled=True,
|
|
230
|
+
api_token_ttl_days=1,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
asyncio.run(main())
|
|
235
|
+
"""
|
|
236
|
+
_response = await self._client_wrapper.httpx_client.request(
|
|
237
|
+
"api/jwt/settings",
|
|
238
|
+
method="POST",
|
|
239
|
+
json={
|
|
240
|
+
"api_tokens_enabled": api_tokens_enabled,
|
|
241
|
+
"legacy_api_tokens_enabled": legacy_api_tokens_enabled,
|
|
242
|
+
"api_token_ttl_days": api_token_ttl_days,
|
|
243
|
+
},
|
|
244
|
+
request_options=request_options,
|
|
245
|
+
omit=OMIT,
|
|
246
|
+
)
|
|
247
|
+
try:
|
|
248
|
+
if 200 <= _response.status_code < 300:
|
|
249
|
+
return typing.cast(
|
|
250
|
+
JwtSettingsResponse,
|
|
251
|
+
parse_obj_as(
|
|
252
|
+
type_=JwtSettingsResponse, # type: ignore
|
|
253
|
+
object_=_response.json(),
|
|
254
|
+
),
|
|
255
|
+
)
|
|
256
|
+
_response_json = _response.json()
|
|
257
|
+
except JSONDecodeError:
|
|
258
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
|
259
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
|
@@ -92,6 +92,12 @@ class ControlTag(LabelStudioTag):
|
|
|
92
92
|
and tag.attrib.get("toName")
|
|
93
93
|
and tag.tag not in _NOT_CONTROL_TAGS
|
|
94
94
|
)
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def is_output_required(self):
|
|
98
|
+
# TextArea can be blank unless user specifies "required"="true" in the attribute
|
|
99
|
+
required_in_attr = str(self.attr.get("required", "false")).lower() == "true"
|
|
100
|
+
return required_in_attr or False
|
|
95
101
|
|
|
96
102
|
def to_json_schema(self):
|
|
97
103
|
"""
|
|
@@ -566,6 +572,7 @@ class LabelsTag(ControlTag):
|
|
|
566
572
|
"properties": {
|
|
567
573
|
"start": {
|
|
568
574
|
"type": "integer",
|
|
575
|
+
# TODO: this is incompatible with the OpenAI API using PredictedOutputs
|
|
569
576
|
"minimum": 0
|
|
570
577
|
},
|
|
571
578
|
"end": {
|
|
@@ -985,8 +992,14 @@ class TextAreaTag(ControlTag):
|
|
|
985
992
|
dict: A dictionary representing the JSON Schema compatible with OpenAPI 3.
|
|
986
993
|
"""
|
|
987
994
|
return {
|
|
988
|
-
"
|
|
989
|
-
|
|
995
|
+
"oneOf": [
|
|
996
|
+
{"type": "string"},
|
|
997
|
+
{
|
|
998
|
+
"type": "array",
|
|
999
|
+
"items": {"type": "string"}
|
|
1000
|
+
}
|
|
1001
|
+
],
|
|
1002
|
+
"description": f"Text or list of texts for {self.to_name[0]}"
|
|
990
1003
|
}
|
|
991
1004
|
|
|
992
1005
|
|
|
@@ -312,6 +312,15 @@ class LabelInterface:
|
|
|
312
312
|
"""
|
|
313
313
|
regions = []
|
|
314
314
|
for control_tag_name, payload in data.items():
|
|
315
|
+
|
|
316
|
+
if payload is None:
|
|
317
|
+
logger.warning(
|
|
318
|
+
f"Payload for control tag '{control_tag_name}' is None: "
|
|
319
|
+
"it can be ok if this payload is autogenerated by LLMs - "
|
|
320
|
+
"try to adjust the prompt to generate valid payloads. "
|
|
321
|
+
"Otherwise, it can signify an error")
|
|
322
|
+
continue
|
|
323
|
+
|
|
315
324
|
if control_tag_name not in self._controls:
|
|
316
325
|
logger.info(f"Control tag '{control_tag_name}' not found in the config")
|
|
317
326
|
continue
|
|
@@ -545,12 +554,16 @@ class LabelInterface:
|
|
|
545
554
|
Returns:
|
|
546
555
|
dict: A dictionary representing the JSON Schema.
|
|
547
556
|
"""
|
|
557
|
+
required_outputs = [
|
|
558
|
+
name for name, control in self._controls.items()
|
|
559
|
+
if control.is_output_required
|
|
560
|
+
]
|
|
548
561
|
return {
|
|
549
562
|
"type": "object",
|
|
550
563
|
"properties": {
|
|
551
564
|
name: control.to_json_schema() for name, control in self._controls.items()
|
|
552
565
|
},
|
|
553
|
-
"required":
|
|
566
|
+
"required": required_outputs
|
|
554
567
|
}
|
|
555
568
|
|
|
556
569
|
def parse(self, config_string: str) -> Tuple[Dict, Dict, Dict, etree._Element]:
|
|
@@ -902,6 +915,72 @@ class LabelInterface:
|
|
|
902
915
|
logger.debug(f'Sample annotation {annotation_dct} failed validation for label config {self.config}')
|
|
903
916
|
return None
|
|
904
917
|
|
|
918
|
+
def generate_complete_sample_task(self, raise_on_failure: bool = False) -> Optional[dict]:
|
|
919
|
+
"""Generate a complete sample task with annotations and predictions.
|
|
920
|
+
|
|
921
|
+
This method combines the generation of a sample task, sample prediction, and sample annotation
|
|
922
|
+
into a single method call, returning a complete task structure.
|
|
923
|
+
|
|
924
|
+
Args:
|
|
925
|
+
raise_on_failure: If True, will raise ValueError when any step
|
|
926
|
+
(including annotation/prediction generation) fails
|
|
927
|
+
|
|
928
|
+
Raises:
|
|
929
|
+
ValueError: If raise_on_failure is True and any generation step fails.
|
|
930
|
+
|
|
931
|
+
Example:
|
|
932
|
+
{
|
|
933
|
+
'data': {'text': 'Sample text for labeling'},
|
|
934
|
+
'annotations': [
|
|
935
|
+
{'was_cancelled': False,
|
|
936
|
+
'ground_truth': False,
|
|
937
|
+
'completed_by': -1,
|
|
938
|
+
'result': [
|
|
939
|
+
{'id': 'b05da11d-3ffc-4657-8b8d-f5bc37cd59ac',
|
|
940
|
+
'from_name': 'sentiment',
|
|
941
|
+
'to_name': 'text',
|
|
942
|
+
'type': 'choices',
|
|
943
|
+
'value': {'choices': ['Negative']}}
|
|
944
|
+
]
|
|
945
|
+
}
|
|
946
|
+
],
|
|
947
|
+
'predictions': [
|
|
948
|
+
{'model_version': 'sample model version',
|
|
949
|
+
'score': 0.95,
|
|
950
|
+
'result': [
|
|
951
|
+
{'id': 'e7bd76e6-4e88-4eb3-b433-55e03661bf5d',
|
|
952
|
+
'from_name': 'sentiment',
|
|
953
|
+
'to_name': 'text',
|
|
954
|
+
'type': 'choices',
|
|
955
|
+
'value': {'choices': ['Neutral']}}
|
|
956
|
+
]
|
|
957
|
+
}
|
|
958
|
+
]
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
NOTE: `id` field in result is not required when importing predictions; it will be generated automatically.
|
|
962
|
+
NOTE: for each control tag, depends on tag.to_json_schema() being implemented correctly
|
|
963
|
+
"""
|
|
964
|
+
sample_task = self.generate_sample_task()
|
|
965
|
+
if not sample_task:
|
|
966
|
+
if raise_on_failure:
|
|
967
|
+
raise ValueError("LabelInterface.generate_sample_task failed to generate a valid sample task")
|
|
968
|
+
return None
|
|
969
|
+
|
|
970
|
+
sample_prediction = self.generate_sample_prediction()
|
|
971
|
+
if not sample_prediction and raise_on_failure:
|
|
972
|
+
raise ValueError("LabelInterface.generate_sample_prediction failed to generate a valid prediction")
|
|
973
|
+
|
|
974
|
+
sample_annotation = self.generate_sample_annotation()
|
|
975
|
+
if not sample_annotation and raise_on_failure:
|
|
976
|
+
raise ValueError("LabelInterface.generate_sample_annotation failed to generate a valid annotation")
|
|
977
|
+
|
|
978
|
+
return {
|
|
979
|
+
"data": sample_task,
|
|
980
|
+
"annotations": [sample_annotation] if sample_annotation else [],
|
|
981
|
+
"predictions": [sample_prediction] if sample_prediction else []
|
|
982
|
+
}
|
|
983
|
+
|
|
905
984
|
#####
|
|
906
985
|
##### COMPATIBILITY LAYER
|
|
907
986
|
#####
|
|
@@ -119,7 +119,7 @@ class ObjectTag(LabelStudioTag):
|
|
|
119
119
|
tag=tag.tag,
|
|
120
120
|
attr=dict(tag.attrib),
|
|
121
121
|
name=tag.attrib.get("name"),
|
|
122
|
-
value=tag.attrib
|
|
122
|
+
value=tag.attrib.get('valueList', tag.attrib.get('value')),
|
|
123
123
|
)
|
|
124
124
|
|
|
125
125
|
@classmethod
|
|
@@ -127,7 +127,7 @@ class ObjectTag(LabelStudioTag):
|
|
|
127
127
|
"""
|
|
128
128
|
Check if tag is input
|
|
129
129
|
"""
|
|
130
|
-
return bool(tag.attrib.get("name") and tag.attrib.get("value"))
|
|
130
|
+
return bool(tag.attrib.get("name") and (tag.attrib.get("value") or tag.attrib.get("valueList")))
|
|
131
131
|
|
|
132
132
|
@property
|
|
133
133
|
def value_type(self):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# This file was auto-generated by Fern from our API Definition.
|
|
2
2
|
|
|
3
3
|
from .types import ProjectsCreateResponse, ProjectsImportTasksResponse, ProjectsListResponse, ProjectsUpdateResponse
|
|
4
|
-
from . import exports
|
|
4
|
+
from . import exports, pauses
|
|
5
5
|
from .exports import ExportsConvertResponse, ExportsListFormatsResponseItem
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
@@ -12,4 +12,5 @@ __all__ = [
|
|
|
12
12
|
"ProjectsListResponse",
|
|
13
13
|
"ProjectsUpdateResponse",
|
|
14
14
|
"exports",
|
|
15
|
+
"pauses",
|
|
15
16
|
]
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import typing
|
|
4
4
|
from ..core.client_wrapper import SyncClientWrapper
|
|
5
|
+
from .pauses.client import PausesClient
|
|
5
6
|
from .exports.client import ExportsClient
|
|
6
7
|
from ..core.request_options import RequestOptions
|
|
7
8
|
from ..core.pagination import SyncPager
|
|
@@ -17,6 +18,7 @@ from .types.projects_import_tasks_response import ProjectsImportTasksResponse
|
|
|
17
18
|
from ..errors.bad_request_error import BadRequestError
|
|
18
19
|
from ..types.project_label_config import ProjectLabelConfig
|
|
19
20
|
from ..core.client_wrapper import AsyncClientWrapper
|
|
21
|
+
from .pauses.client import AsyncPausesClient
|
|
20
22
|
from .exports.client import AsyncExportsClient
|
|
21
23
|
from ..core.pagination import AsyncPager
|
|
22
24
|
|
|
@@ -27,6 +29,7 @@ OMIT = typing.cast(typing.Any, ...)
|
|
|
27
29
|
class ProjectsClient:
|
|
28
30
|
def __init__(self, *, client_wrapper: SyncClientWrapper):
|
|
29
31
|
self._client_wrapper = client_wrapper
|
|
32
|
+
self.pauses = PausesClient(client_wrapper=self._client_wrapper)
|
|
30
33
|
self.exports = ExportsClient(client_wrapper=self._client_wrapper)
|
|
31
34
|
|
|
32
35
|
def list(
|
|
@@ -701,6 +704,7 @@ class ProjectsClient:
|
|
|
701
704
|
class AsyncProjectsClient:
|
|
702
705
|
def __init__(self, *, client_wrapper: AsyncClientWrapper):
|
|
703
706
|
self._client_wrapper = client_wrapper
|
|
707
|
+
self.pauses = AsyncPausesClient(client_wrapper=self._client_wrapper)
|
|
704
708
|
self.exports = AsyncExportsClient(client_wrapper=self._client_wrapper)
|
|
705
709
|
|
|
706
710
|
async def list(
|