scrapely-client-python 3.1.3__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 scrapely-client-python might be problematic. Click here for more details.

Files changed (65) hide show
  1. scrapely_client/__init__.py +30 -0
  2. scrapely_client/_charging.py +186 -0
  3. scrapely_client/_client_registry.py +136 -0
  4. scrapely_client/_consts.py +96 -0
  5. scrapely_client/_docs.py +37 -0
  6. scrapely_client/_literals.py +539 -0
  7. scrapely_client/_logging.py +180 -0
  8. scrapely_client/_models.py +4172 -0
  9. scrapely_client/_pagination.py +220 -0
  10. scrapely_client/_resource_clients/__init__.py +84 -0
  11. scrapely_client/_resource_clients/_resource_client.py +567 -0
  12. scrapely_client/_resource_clients/actor.py +1042 -0
  13. scrapely_client/_resource_clients/actor_collection.py +377 -0
  14. scrapely_client/_resource_clients/actor_env_var.py +154 -0
  15. scrapely_client/_resource_clients/actor_env_var_collection.py +165 -0
  16. scrapely_client/_resource_clients/actor_version.py +254 -0
  17. scrapely_client/_resource_clients/actor_version_collection.py +232 -0
  18. scrapely_client/_resource_clients/build.py +244 -0
  19. scrapely_client/_resource_clients/build_collection.py +164 -0
  20. scrapely_client/_resource_clients/dataset.py +1151 -0
  21. scrapely_client/_resource_clients/dataset_collection.py +244 -0
  22. scrapely_client/_resource_clients/key_value_store.py +906 -0
  23. scrapely_client/_resource_clients/key_value_store_collection.py +243 -0
  24. scrapely_client/_resource_clients/log.py +225 -0
  25. scrapely_client/_resource_clients/request_queue.py +1167 -0
  26. scrapely_client/_resource_clients/request_queue_collection.py +240 -0
  27. scrapely_client/_resource_clients/run.py +875 -0
  28. scrapely_client/_resource_clients/run_collection.py +226 -0
  29. scrapely_client/_resource_clients/schedule.py +243 -0
  30. scrapely_client/_resource_clients/schedule_collection.py +260 -0
  31. scrapely_client/_resource_clients/store_collection.py +242 -0
  32. scrapely_client/_resource_clients/task.py +793 -0
  33. scrapely_client/_resource_clients/task_collection.py +322 -0
  34. scrapely_client/_resource_clients/user.py +262 -0
  35. scrapely_client/_resource_clients/webhook.py +292 -0
  36. scrapely_client/_resource_clients/webhook_collection.py +281 -0
  37. scrapely_client/_resource_clients/webhook_dispatch.py +84 -0
  38. scrapely_client/_resource_clients/webhook_dispatch_collection.py +158 -0
  39. scrapely_client/_scrapely_client.py +837 -0
  40. scrapely_client/_statistics.py +29 -0
  41. scrapely_client/_status_message_watcher.py +197 -0
  42. scrapely_client/_streamed_log.py +250 -0
  43. scrapely_client/_typeddicts.py +408 -0
  44. scrapely_client/_utils/__init__.py +0 -0
  45. scrapely_client/_utils/crypto.py +87 -0
  46. scrapely_client/_utils/encoding.py +133 -0
  47. scrapely_client/_utils/errors.py +33 -0
  48. scrapely_client/_utils/http.py +137 -0
  49. scrapely_client/_utils/time.py +32 -0
  50. scrapely_client/_utils/try_import.py +61 -0
  51. scrapely_client/errors.py +190 -0
  52. scrapely_client/http_clients/__init__.py +10 -0
  53. scrapely_client/http_clients/_base.py +430 -0
  54. scrapely_client/http_clients/_impit.py +598 -0
  55. scrapely_client/http_compressors/__init__.py +18 -0
  56. scrapely_client/http_compressors/_base.py +25 -0
  57. scrapely_client/http_compressors/_brotli.py +38 -0
  58. scrapely_client/http_compressors/_gzip.py +38 -0
  59. scrapely_client/http_compressors/_resolve.py +38 -0
  60. scrapely_client/py.typed +0 -0
  61. scrapely_client/types.py +52 -0
  62. scrapely_client_python-3.1.3.dist-info/METADATA +269 -0
  63. scrapely_client_python-3.1.3.dist-info/RECORD +65 -0
  64. scrapely_client_python-3.1.3.dist-info/WHEEL +4 -0
  65. scrapely_client_python-3.1.3.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,322 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ from scrapely_client._docs import docs_group
6
+ from scrapely_client._models import (
7
+ ActorStandby,
8
+ CreateTaskRequest,
9
+ ListOfTasks,
10
+ ListOfTasksResponse,
11
+ Task,
12
+ TaskInput,
13
+ TaskOptions,
14
+ TaskResponse,
15
+ )
16
+ from scrapely_client._pagination import get_items_iterator, get_items_iterator_async
17
+ from scrapely_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
18
+ from scrapely_client._utils.time import to_seconds
19
+
20
+ if TYPE_CHECKING:
21
+ from collections.abc import AsyncIterator, Iterator
22
+ from datetime import timedelta
23
+
24
+ from scrapely_client._models import TaskShort
25
+ from scrapely_client._typeddicts import TaskInputDict
26
+ from scrapely_client.types import Timeout
27
+
28
+
29
+ @docs_group('Resource clients')
30
+ class TaskCollectionClient(ResourceClient):
31
+ """Sub-client for the task collection.
32
+
33
+ Provides methods to manage the task collection, e.g. list or create tasks. Obtain an instance via an appropriate
34
+ method on the `ApifyClient` class.
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ *,
40
+ resource_path: str = 'actor-tasks',
41
+ **kwargs: Any,
42
+ ) -> None:
43
+ super().__init__(
44
+ resource_path=resource_path,
45
+ **kwargs,
46
+ )
47
+
48
+ def list(
49
+ self,
50
+ *,
51
+ limit: int | None = None,
52
+ offset: int | None = None,
53
+ desc: bool | None = None,
54
+ timeout: Timeout = 'medium',
55
+ ) -> ListOfTasks:
56
+ """List the available tasks.
57
+
58
+
59
+ Args:
60
+ limit: How many tasks to list.
61
+ offset: What task to include as first when retrieving the list.
62
+ desc: Whether to sort the tasks in descending order based on their creation date.
63
+ timeout: Timeout for the API HTTP request.
64
+
65
+ Returns:
66
+ The list of available tasks matching the specified filters.
67
+ """
68
+ result = self._list(timeout=timeout, limit=limit, offset=offset, desc=desc)
69
+ return ListOfTasksResponse.model_validate(result).data
70
+
71
+ def iterate(
72
+ self,
73
+ *,
74
+ limit: int | None = None,
75
+ offset: int | None = None,
76
+ desc: bool | None = None,
77
+ timeout: Timeout = 'medium',
78
+ ) -> Iterator[TaskShort]:
79
+ """Iterate over the available tasks.
80
+
81
+ Simple `list` does only one API call, possibly not listing all items matching the criteria. This method
82
+ returns an iterator that is capable of making multiple API calls to retrieve all items matching the criteria.
83
+
84
+
85
+ Args:
86
+ limit: How many tasks to list.
87
+ offset: What task to include as first when retrieving the list.
88
+ desc: Whether to sort the tasks in descending order based on their creation date.
89
+ timeout: Timeout for the API HTTP request.
90
+
91
+ Yields:
92
+ The available tasks matching the specified filters.
93
+ """
94
+
95
+ def _callback(*, limit: int | None = None, offset: int | None = None) -> ListOfTasks:
96
+ return self.list(limit=limit, offset=offset, desc=desc, timeout=timeout)
97
+
98
+ return get_items_iterator(_callback, limit=limit, offset=offset)
99
+
100
+ def create(
101
+ self,
102
+ *,
103
+ actor_id: str,
104
+ name: str,
105
+ build: str | None = None,
106
+ run_timeout: timedelta | None = None,
107
+ memory_mbytes: int | None = None,
108
+ max_items: int | None = None,
109
+ restart_on_error: bool | None = None,
110
+ task_input: TaskInputDict | TaskInput | None = None,
111
+ title: str | None = None,
112
+ actor_standby_desired_requests_per_actor_run: int | None = None,
113
+ actor_standby_max_requests_per_actor_run: int | None = None,
114
+ actor_standby_idle_timeout: timedelta | None = None,
115
+ actor_standby_build: str | None = None,
116
+ actor_standby_memory_mbytes: int | None = None,
117
+ timeout: Timeout = 'medium',
118
+ ) -> Task:
119
+ """Create a new task.
120
+
121
+
122
+ Args:
123
+ actor_id: Id of the Actor that should be run.
124
+ name: Name of the task.
125
+ build: Actor build to run. It can be either a build tag or build number. By default, the run uses
126
+ the build specified in the task settings (typically latest).
127
+ memory_mbytes: Memory limit for the run, in megabytes. By default, the run uses a memory limit specified
128
+ in the task settings.
129
+ max_items: Maximum number of results that will be returned by runs of this task. If the Actor of this task
130
+ is charged per result, you will not be charged for more results than the given limit.
131
+ run_timeout: Optional timeout for the run. By default, the run uses timeout specified
132
+ in the task settings.
133
+ restart_on_error: If true, the Task run process will be restarted whenever it exits with
134
+ a non-zero status code.
135
+ task_input: Task input object.
136
+ title: A human-friendly equivalent of the name.
137
+ actor_standby_desired_requests_per_actor_run: The desired number of concurrent HTTP requests for
138
+ a single Actor Standby run.
139
+ actor_standby_max_requests_per_actor_run: The maximum number of concurrent HTTP requests for
140
+ a single Actor Standby run.
141
+ actor_standby_idle_timeout: If the Actor run does not receive any requests for this time,
142
+ it will be shut down.
143
+ actor_standby_build: The build tag or number to run when the Actor is in Standby mode.
144
+ actor_standby_memory_mbytes: The memory in megabytes to use when the Actor is in Standby mode.
145
+ timeout: Timeout for the API HTTP request.
146
+
147
+ Returns:
148
+ The created task.
149
+ """
150
+ if task_input is not None and not isinstance(task_input, TaskInput):
151
+ task_input = TaskInput.model_validate(task_input)
152
+
153
+ task_fields = CreateTaskRequest(
154
+ act_id=actor_id,
155
+ name=name,
156
+ title=title,
157
+ input=task_input,
158
+ options=TaskOptions(
159
+ build=build,
160
+ max_items=max_items,
161
+ memory_mbytes=memory_mbytes,
162
+ timeout_secs=to_seconds(run_timeout, as_int=True),
163
+ restart_on_error=restart_on_error,
164
+ ),
165
+ actor_standby=ActorStandby(
166
+ desired_requests_per_actor_run=actor_standby_desired_requests_per_actor_run,
167
+ max_requests_per_actor_run=actor_standby_max_requests_per_actor_run,
168
+ idle_timeout_secs=to_seconds(actor_standby_idle_timeout, as_int=True),
169
+ build=actor_standby_build,
170
+ memory_mbytes=actor_standby_memory_mbytes,
171
+ ),
172
+ )
173
+ result = self._create(timeout=timeout, **task_fields.model_dump(by_alias=True, exclude_none=True))
174
+ return TaskResponse.model_validate(result).data
175
+
176
+
177
+ @docs_group('Resource clients')
178
+ class TaskCollectionClientAsync(ResourceClientAsync):
179
+ """Sub-client for the task collection.
180
+
181
+ Provides methods to manage the task collection, e.g. list or create tasks. Obtain an instance via an appropriate
182
+ method on the `ApifyClientAsync` class.
183
+ """
184
+
185
+ def __init__(
186
+ self,
187
+ *,
188
+ resource_path: str = 'actor-tasks',
189
+ **kwargs: Any,
190
+ ) -> None:
191
+ super().__init__(
192
+ resource_path=resource_path,
193
+ **kwargs,
194
+ )
195
+
196
+ async def list(
197
+ self,
198
+ *,
199
+ limit: int | None = None,
200
+ offset: int | None = None,
201
+ desc: bool | None = None,
202
+ timeout: Timeout = 'medium',
203
+ ) -> ListOfTasks:
204
+ """List the available tasks.
205
+
206
+
207
+ Args:
208
+ limit: How many tasks to list.
209
+ offset: What task to include as first when retrieving the list.
210
+ desc: Whether to sort the tasks in descending order based on their creation date.
211
+ timeout: Timeout for the API HTTP request.
212
+
213
+ Returns:
214
+ The list of available tasks matching the specified filters.
215
+ """
216
+ result = await self._list(timeout=timeout, limit=limit, offset=offset, desc=desc)
217
+ return ListOfTasksResponse.model_validate(result).data
218
+
219
+ def iterate(
220
+ self,
221
+ *,
222
+ limit: int | None = None,
223
+ offset: int | None = None,
224
+ desc: bool | None = None,
225
+ timeout: Timeout = 'medium',
226
+ ) -> AsyncIterator[TaskShort]:
227
+ """Iterate over the available tasks.
228
+
229
+ Simple `list` does only one API call, possibly not listing all items matching the criteria. This method
230
+ returns an iterator that is capable of making multiple API calls to retrieve all items matching the criteria.
231
+
232
+
233
+ Args:
234
+ limit: How many tasks to list.
235
+ offset: What task to include as first when retrieving the list.
236
+ desc: Whether to sort the tasks in descending order based on their creation date.
237
+ timeout: Timeout for the API HTTP request.
238
+
239
+ Yields:
240
+ The available tasks matching the specified filters.
241
+ """
242
+
243
+ async def _callback(*, limit: int | None = None, offset: int | None = None) -> ListOfTasks:
244
+ return await self.list(limit=limit, offset=offset, desc=desc, timeout=timeout)
245
+
246
+ return get_items_iterator_async(_callback, limit=limit, offset=offset)
247
+
248
+ async def create(
249
+ self,
250
+ *,
251
+ actor_id: str,
252
+ name: str,
253
+ build: str | None = None,
254
+ run_timeout: timedelta | None = None,
255
+ memory_mbytes: int | None = None,
256
+ max_items: int | None = None,
257
+ restart_on_error: bool | None = None,
258
+ task_input: TaskInputDict | TaskInput | None = None,
259
+ title: str | None = None,
260
+ actor_standby_desired_requests_per_actor_run: int | None = None,
261
+ actor_standby_max_requests_per_actor_run: int | None = None,
262
+ actor_standby_idle_timeout: timedelta | None = None,
263
+ actor_standby_build: str | None = None,
264
+ actor_standby_memory_mbytes: int | None = None,
265
+ timeout: Timeout = 'medium',
266
+ ) -> Task:
267
+ """Create a new task.
268
+
269
+
270
+ Args:
271
+ actor_id: Id of the Actor that should be run.
272
+ name: Name of the task.
273
+ build: Actor build to run. It can be either a build tag or build number. By default, the run uses
274
+ the build specified in the task settings (typically latest).
275
+ memory_mbytes: Memory limit for the run, in megabytes. By default, the run uses a memory limit specified
276
+ in the task settings.
277
+ max_items: Maximum number of results that will be returned by runs of this task. If the Actor of this task
278
+ is charged per result, you will not be charged for more results than the given limit.
279
+ run_timeout: Optional timeout for the run. By default, the run uses timeout specified
280
+ in the task settings.
281
+ restart_on_error: If true, the Task run process will be restarted whenever it exits with
282
+ a non-zero status code.
283
+ task_input: Task input object.
284
+ title: A human-friendly equivalent of the name.
285
+ actor_standby_desired_requests_per_actor_run: The desired number of concurrent HTTP requests for
286
+ a single Actor Standby run.
287
+ actor_standby_max_requests_per_actor_run: The maximum number of concurrent HTTP requests for
288
+ a single Actor Standby run.
289
+ actor_standby_idle_timeout: If the Actor run does not receive any requests for this time,
290
+ it will be shut down.
291
+ actor_standby_build: The build tag or number to run when the Actor is in Standby mode.
292
+ actor_standby_memory_mbytes: The memory in megabytes to use when the Actor is in Standby mode.
293
+ timeout: Timeout for the API HTTP request.
294
+
295
+ Returns:
296
+ The created task.
297
+ """
298
+ if task_input is not None and not isinstance(task_input, TaskInput):
299
+ task_input = TaskInput.model_validate(task_input)
300
+
301
+ task_fields = CreateTaskRequest(
302
+ act_id=actor_id,
303
+ name=name,
304
+ title=title,
305
+ input=task_input,
306
+ options=TaskOptions(
307
+ build=build,
308
+ max_items=max_items,
309
+ memory_mbytes=memory_mbytes,
310
+ timeout_secs=to_seconds(run_timeout, as_int=True),
311
+ restart_on_error=restart_on_error,
312
+ ),
313
+ actor_standby=ActorStandby(
314
+ desired_requests_per_actor_run=actor_standby_desired_requests_per_actor_run,
315
+ max_requests_per_actor_run=actor_standby_max_requests_per_actor_run,
316
+ idle_timeout_secs=to_seconds(actor_standby_idle_timeout, as_int=True),
317
+ build=actor_standby_build,
318
+ memory_mbytes=actor_standby_memory_mbytes,
319
+ ),
320
+ )
321
+ result = await self._create(timeout=timeout, **task_fields.model_dump(by_alias=True, exclude_none=True))
322
+ return TaskResponse.model_validate(result).data
@@ -0,0 +1,262 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ from pydantic import ValidationError
6
+
7
+ from scrapely_client._docs import docs_group
8
+ from scrapely_client._models import (
9
+ AccountLimits,
10
+ LimitsResponse,
11
+ MonthlyUsage,
12
+ MonthlyUsageResponse,
13
+ PrivateUserDataResponse,
14
+ PublicUserDataResponse,
15
+ UserPrivateInfo,
16
+ UserPublicInfo,
17
+ )
18
+ from scrapely_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
19
+ from scrapely_client._utils.http import response_to_dict
20
+
21
+ if TYPE_CHECKING:
22
+ from scrapely_client.types import Timeout
23
+
24
+
25
+ @docs_group('Resource clients')
26
+ class UserClient(ResourceClient):
27
+ """Sub-client for managing user account information.
28
+
29
+ Provides methods to manage user account information, e.g. get user data or monthly usage. Obtain an instance via
30
+ an appropriate method on the `ApifyClient` class.
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ *,
36
+ resource_id: str | None = None,
37
+ resource_path: str = 'users',
38
+ **kwargs: Any,
39
+ ) -> None:
40
+ super().__init__(
41
+ resource_id=resource_id or 'me',
42
+ resource_path=resource_path,
43
+ **kwargs,
44
+ )
45
+
46
+ def get(self, *, timeout: Timeout = 'short') -> UserPublicInfo | UserPrivateInfo | None:
47
+ """Return information about user account.
48
+
49
+ You receive all or only public info based on your token permissions.
50
+
51
+
52
+ Args:
53
+ timeout: Timeout for the API HTTP request.
54
+
55
+ Returns:
56
+ The retrieved user data, or None if the user does not exist.
57
+ """
58
+ result = self._get(timeout=timeout)
59
+ if result is None:
60
+ return None
61
+ try:
62
+ return PrivateUserDataResponse.model_validate(result).data
63
+ except ValidationError:
64
+ return PublicUserDataResponse.model_validate(result).data
65
+
66
+ def monthly_usage(self, *, timeout: Timeout = 'short') -> MonthlyUsage:
67
+ """Return monthly usage of the user account.
68
+
69
+ This includes a complete usage summary for the current usage cycle, an overall sum, as well as a daily breakdown
70
+ of usage. It is the same information which is available on the account's Billing page. The information includes
71
+ use of storage, data transfer, and request queue usage.
72
+
73
+
74
+ Args:
75
+ timeout: Timeout for the API HTTP request.
76
+
77
+ Returns:
78
+ The retrieved monthly usage.
79
+
80
+ Raises:
81
+ NotFoundError: If the user does not exist.
82
+ """
83
+ response = self._http_client.call(
84
+ url=self._build_url('usage/monthly'),
85
+ method='GET',
86
+ params=self._build_params(),
87
+ timeout=timeout,
88
+ )
89
+ result = response_to_dict(response)
90
+ return MonthlyUsageResponse.model_validate(result).data
91
+
92
+ def limits(self, *, timeout: Timeout = 'short') -> AccountLimits:
93
+ """Return a complete summary of the user account's limits.
94
+
95
+ It is the same information which is available on the account's Limits page. The returned data includes
96
+ the current usage cycle, a summary of the account's limits, and the current usage.
97
+
98
+
99
+ Args:
100
+ timeout: Timeout for the API HTTP request.
101
+
102
+ Returns:
103
+ The account limits.
104
+
105
+ Raises:
106
+ NotFoundError: If the user does not exist.
107
+ """
108
+ response = self._http_client.call(
109
+ url=self._build_url('limits'),
110
+ method='GET',
111
+ params=self._build_params(),
112
+ timeout=timeout,
113
+ )
114
+ result = response_to_dict(response)
115
+ return LimitsResponse.model_validate(result).data
116
+
117
+ def update_limits(
118
+ self,
119
+ *,
120
+ max_monthly_usage_usd: int | None = None,
121
+ data_retention_days: int | None = None,
122
+ timeout: Timeout = 'short',
123
+ ) -> None:
124
+ """Update the account's limits manageable on your account's Limits page.
125
+
126
+ Args:
127
+ max_monthly_usage_usd: Maximum monthly usage in USD.
128
+ data_retention_days: Data retention period in days.
129
+ timeout: Timeout for the API HTTP request.
130
+ """
131
+ self._http_client.call(
132
+ url=self._build_url('limits'),
133
+ method='PUT',
134
+ params=self._build_params(),
135
+ json=self._clean_json_payload(
136
+ {
137
+ 'maxMonthlyUsageUsd': max_monthly_usage_usd,
138
+ 'dataRetentionDays': data_retention_days,
139
+ }
140
+ ),
141
+ timeout=timeout,
142
+ )
143
+
144
+
145
+ @docs_group('Resource clients')
146
+ class UserClientAsync(ResourceClientAsync):
147
+ """Sub-client for managing user account information.
148
+
149
+ Provides methods to manage user account information, e.g. get user data or monthly usage. Obtain an instance via
150
+ an appropriate method on the `ApifyClientAsync` class.
151
+ """
152
+
153
+ def __init__(
154
+ self,
155
+ *,
156
+ resource_id: str | None = None,
157
+ resource_path: str = 'users',
158
+ **kwargs: Any,
159
+ ) -> None:
160
+ super().__init__(
161
+ resource_id=resource_id or 'me',
162
+ resource_path=resource_path,
163
+ **kwargs,
164
+ )
165
+
166
+ async def get(self, *, timeout: Timeout = 'short') -> UserPublicInfo | UserPrivateInfo | None:
167
+ """Return information about user account.
168
+
169
+ You receive all or only public info based on your token permissions.
170
+
171
+
172
+ Args:
173
+ timeout: Timeout for the API HTTP request.
174
+
175
+ Returns:
176
+ The retrieved user data, or None if the user does not exist.
177
+ """
178
+ result = await self._get(timeout=timeout)
179
+ if result is None:
180
+ return None
181
+ try:
182
+ return PrivateUserDataResponse.model_validate(result).data
183
+ except ValidationError:
184
+ return PublicUserDataResponse.model_validate(result).data
185
+
186
+ async def monthly_usage(self, *, timeout: Timeout = 'short') -> MonthlyUsage:
187
+ """Return monthly usage of the user account.
188
+
189
+ This includes a complete usage summary for the current usage cycle, an overall sum, as well as a daily breakdown
190
+ of usage. It is the same information which is available on the account's Billing page. The information includes
191
+ use of storage, data transfer, and request queue usage.
192
+
193
+
194
+ Args:
195
+ timeout: Timeout for the API HTTP request.
196
+
197
+ Returns:
198
+ The retrieved monthly usage.
199
+
200
+ Raises:
201
+ NotFoundError: If the user does not exist.
202
+ """
203
+ response = await self._http_client.call(
204
+ url=self._build_url('usage/monthly'),
205
+ method='GET',
206
+ params=self._build_params(),
207
+ timeout=timeout,
208
+ )
209
+ result = response_to_dict(response)
210
+ return MonthlyUsageResponse.model_validate(result).data
211
+
212
+ async def limits(self, *, timeout: Timeout = 'short') -> AccountLimits:
213
+ """Return a complete summary of the user account's limits.
214
+
215
+ It is the same information which is available on the account's Limits page. The returned data includes
216
+ the current usage cycle, a summary of the account's limits, and the current usage.
217
+
218
+
219
+ Args:
220
+ timeout: Timeout for the API HTTP request.
221
+
222
+ Returns:
223
+ The account limits.
224
+
225
+ Raises:
226
+ NotFoundError: If the user does not exist.
227
+ """
228
+ response = await self._http_client.call(
229
+ url=self._build_url('limits'),
230
+ method='GET',
231
+ params=self._build_params(),
232
+ timeout=timeout,
233
+ )
234
+ result = response_to_dict(response)
235
+ return LimitsResponse.model_validate(result).data
236
+
237
+ async def update_limits(
238
+ self,
239
+ *,
240
+ max_monthly_usage_usd: int | None = None,
241
+ data_retention_days: int | None = None,
242
+ timeout: Timeout = 'short',
243
+ ) -> None:
244
+ """Update the account's limits manageable on your account's Limits page.
245
+
246
+ Args:
247
+ max_monthly_usage_usd: Maximum monthly usage in USD.
248
+ data_retention_days: Data retention period in days.
249
+ timeout: Timeout for the API HTTP request.
250
+ """
251
+ await self._http_client.call(
252
+ url=self._build_url('limits'),
253
+ method='PUT',
254
+ params=self._build_params(),
255
+ json=self._clean_json_payload(
256
+ {
257
+ 'maxMonthlyUsageUsd': max_monthly_usage_usd,
258
+ 'dataRetentionDays': data_retention_days,
259
+ }
260
+ ),
261
+ timeout=timeout,
262
+ )