pulse-python-sdk 0.0.52__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.
Files changed (72) hide show
  1. pulse/__init__.py +42 -0
  2. pulse/client.py +666 -0
  3. pulse/core/__init__.py +34 -0
  4. pulse/core/api_error.py +23 -0
  5. pulse/core/client_wrapper.py +89 -0
  6. pulse/core/datetime_utils.py +28 -0
  7. pulse/core/file.py +67 -0
  8. pulse/core/force_multipart.py +18 -0
  9. pulse/core/http_client.py +663 -0
  10. pulse/core/http_response.py +55 -0
  11. pulse/core/http_sse/__init__.py +42 -0
  12. pulse/core/http_sse/_api.py +112 -0
  13. pulse/core/http_sse/_decoders.py +61 -0
  14. pulse/core/http_sse/_exceptions.py +7 -0
  15. pulse/core/http_sse/_models.py +17 -0
  16. pulse/core/jsonable_encoder.py +100 -0
  17. pulse/core/pydantic_utilities.py +260 -0
  18. pulse/core/query_encoder.py +58 -0
  19. pulse/core/remove_none_from_dict.py +11 -0
  20. pulse/core/request_options.py +35 -0
  21. pulse/core/serialization.py +276 -0
  22. pulse/core/unchecked_base_model.py +396 -0
  23. pulse/environment.py +7 -0
  24. pulse/errors/__init__.py +4 -0
  25. pulse/errors/bad_request_error.py +10 -0
  26. pulse/errors/forbidden_error.py +10 -0
  27. pulse/errors/internal_server_error.py +10 -0
  28. pulse/errors/not_found_error.py +10 -0
  29. pulse/errors/too_many_requests_error.py +10 -0
  30. pulse/errors/unauthorized_error.py +10 -0
  31. pulse/jobs/__init__.py +4 -0
  32. pulse/jobs/client.py +191 -0
  33. pulse/jobs/raw_client.py +408 -0
  34. pulse/py.typed +0 -0
  35. pulse/raw_client.py +661 -0
  36. pulse/types/__init__.py +4 -0
  37. pulse/types/extract_async_input.py +5 -0
  38. pulse/types/extract_async_response.py +43 -0
  39. pulse/types/extract_async_submission_response_status.py +7 -0
  40. pulse/types/extract_input.py +5 -0
  41. pulse/types/extract_json_input.py +116 -0
  42. pulse/types/extract_json_input_experimental_schema.py +5 -0
  43. pulse/types/extract_json_input_schema.py +5 -0
  44. pulse/types/extract_json_input_storage.py +36 -0
  45. pulse/types/extract_json_input_structured_output.py +38 -0
  46. pulse/types/extract_multipart_input.py +111 -0
  47. pulse/types/extract_multipart_input_experimental_schema.py +5 -0
  48. pulse/types/extract_multipart_input_schema.py +5 -0
  49. pulse/types/extract_multipart_input_storage.py +36 -0
  50. pulse/types/extract_multipart_input_structured_output.py +38 -0
  51. pulse/types/extract_options.py +111 -0
  52. pulse/types/extract_options_experimental_schema.py +5 -0
  53. pulse/types/extract_options_schema.py +5 -0
  54. pulse/types/extract_options_storage.py +36 -0
  55. pulse/types/extract_options_structured_output.py +38 -0
  56. pulse/types/extract_response.py +47 -0
  57. pulse/types/extract_source_multipart_one.py +27 -0
  58. pulse/types/extract_source_multipart_zero.py +27 -0
  59. pulse/types/job_cancellation_response.py +32 -0
  60. pulse/types/job_status.py +5 -0
  61. pulse/types/job_status_response.py +50 -0
  62. pulse/types/json_source.py +29 -0
  63. pulse/types/multipart_source.py +8 -0
  64. pulse/version.py +3 -0
  65. pulse/webhooks/__init__.py +4 -0
  66. pulse/webhooks/client.py +104 -0
  67. pulse/webhooks/raw_client.py +139 -0
  68. pulse/webhooks/types/__init__.py +4 -0
  69. pulse/webhooks/types/create_webhook_link_response.py +23 -0
  70. pulse_python_sdk-0.0.52.dist-info/METADATA +197 -0
  71. pulse_python_sdk-0.0.52.dist-info/RECORD +72 -0
  72. pulse_python_sdk-0.0.52.dist-info/WHEEL +4 -0
@@ -0,0 +1,408 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import typing
4
+ from json.decoder import JSONDecodeError
5
+
6
+ from ..core.api_error import ApiError
7
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
8
+ from ..core.http_response import AsyncHttpResponse, HttpResponse
9
+ from ..core.jsonable_encoder import jsonable_encoder
10
+ from ..core.request_options import RequestOptions
11
+ from ..core.unchecked_base_model import construct_type
12
+ from ..errors.forbidden_error import ForbiddenError
13
+ from ..errors.internal_server_error import InternalServerError
14
+ from ..errors.not_found_error import NotFoundError
15
+ from ..errors.too_many_requests_error import TooManyRequestsError
16
+ from ..errors.unauthorized_error import UnauthorizedError
17
+ from ..types.job_cancellation_response import JobCancellationResponse
18
+ from ..types.job_status_response import JobStatusResponse
19
+
20
+
21
+ class RawJobsClient:
22
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
23
+ self._client_wrapper = client_wrapper
24
+
25
+ def get_job(
26
+ self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
27
+ ) -> HttpResponse[JobStatusResponse]:
28
+ """
29
+ Check the status and retrieve results of an asynchronous job
30
+ (e.g., submitted via `/extract_async`).
31
+
32
+ Parameters
33
+ ----------
34
+ job_id : str
35
+ Identifier returned from an async job submission (e.g., `/extract_async`).
36
+
37
+ request_options : typing.Optional[RequestOptions]
38
+ Request-specific configuration.
39
+
40
+ Returns
41
+ -------
42
+ HttpResponse[JobStatusResponse]
43
+ Current job status payload
44
+ """
45
+ _response = self._client_wrapper.httpx_client.request(
46
+ f"job/{jsonable_encoder(job_id)}",
47
+ method="GET",
48
+ request_options=request_options,
49
+ )
50
+ try:
51
+ if 200 <= _response.status_code < 300:
52
+ _data = typing.cast(
53
+ JobStatusResponse,
54
+ construct_type(
55
+ type_=JobStatusResponse, # type: ignore
56
+ object_=_response.json(),
57
+ ),
58
+ )
59
+ return HttpResponse(response=_response, data=_data)
60
+ if _response.status_code == 401:
61
+ raise UnauthorizedError(
62
+ headers=dict(_response.headers),
63
+ body=typing.cast(
64
+ typing.Any,
65
+ construct_type(
66
+ type_=typing.Any, # type: ignore
67
+ object_=_response.json(),
68
+ ),
69
+ ),
70
+ )
71
+ if _response.status_code == 403:
72
+ raise ForbiddenError(
73
+ headers=dict(_response.headers),
74
+ body=typing.cast(
75
+ typing.Any,
76
+ construct_type(
77
+ type_=typing.Any, # type: ignore
78
+ object_=_response.json(),
79
+ ),
80
+ ),
81
+ )
82
+ if _response.status_code == 404:
83
+ raise NotFoundError(
84
+ headers=dict(_response.headers),
85
+ body=typing.cast(
86
+ typing.Any,
87
+ construct_type(
88
+ type_=typing.Any, # type: ignore
89
+ object_=_response.json(),
90
+ ),
91
+ ),
92
+ )
93
+ if _response.status_code == 429:
94
+ raise TooManyRequestsError(
95
+ headers=dict(_response.headers),
96
+ body=typing.cast(
97
+ typing.Any,
98
+ construct_type(
99
+ type_=typing.Any, # type: ignore
100
+ object_=_response.json(),
101
+ ),
102
+ ),
103
+ )
104
+ if _response.status_code == 500:
105
+ raise InternalServerError(
106
+ headers=dict(_response.headers),
107
+ body=typing.cast(
108
+ typing.Any,
109
+ construct_type(
110
+ type_=typing.Any, # type: ignore
111
+ object_=_response.json(),
112
+ ),
113
+ ),
114
+ )
115
+ _response_json = _response.json()
116
+ except JSONDecodeError:
117
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
118
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
119
+
120
+ def cancel_job(
121
+ self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
122
+ ) -> HttpResponse[JobCancellationResponse]:
123
+ """
124
+ Attempts to cancel an asynchronous job that is currently pending
125
+ or processing. Jobs that have already completed will remain unchanged.
126
+
127
+ Parameters
128
+ ----------
129
+ job_id : str
130
+ Identifier returned from an async job submission (e.g., `/extract_async`).
131
+
132
+ request_options : typing.Optional[RequestOptions]
133
+ Request-specific configuration.
134
+
135
+ Returns
136
+ -------
137
+ HttpResponse[JobCancellationResponse]
138
+ Job cancellation accepted
139
+ """
140
+ _response = self._client_wrapper.httpx_client.request(
141
+ f"job/{jsonable_encoder(job_id)}",
142
+ method="DELETE",
143
+ request_options=request_options,
144
+ )
145
+ try:
146
+ if 200 <= _response.status_code < 300:
147
+ _data = typing.cast(
148
+ JobCancellationResponse,
149
+ construct_type(
150
+ type_=JobCancellationResponse, # type: ignore
151
+ object_=_response.json(),
152
+ ),
153
+ )
154
+ return HttpResponse(response=_response, data=_data)
155
+ if _response.status_code == 401:
156
+ raise UnauthorizedError(
157
+ headers=dict(_response.headers),
158
+ body=typing.cast(
159
+ typing.Any,
160
+ construct_type(
161
+ type_=typing.Any, # type: ignore
162
+ object_=_response.json(),
163
+ ),
164
+ ),
165
+ )
166
+ if _response.status_code == 403:
167
+ raise ForbiddenError(
168
+ headers=dict(_response.headers),
169
+ body=typing.cast(
170
+ typing.Any,
171
+ construct_type(
172
+ type_=typing.Any, # type: ignore
173
+ object_=_response.json(),
174
+ ),
175
+ ),
176
+ )
177
+ if _response.status_code == 404:
178
+ raise NotFoundError(
179
+ headers=dict(_response.headers),
180
+ body=typing.cast(
181
+ typing.Any,
182
+ construct_type(
183
+ type_=typing.Any, # type: ignore
184
+ object_=_response.json(),
185
+ ),
186
+ ),
187
+ )
188
+ if _response.status_code == 429:
189
+ raise TooManyRequestsError(
190
+ headers=dict(_response.headers),
191
+ body=typing.cast(
192
+ typing.Any,
193
+ construct_type(
194
+ type_=typing.Any, # type: ignore
195
+ object_=_response.json(),
196
+ ),
197
+ ),
198
+ )
199
+ if _response.status_code == 500:
200
+ raise InternalServerError(
201
+ headers=dict(_response.headers),
202
+ body=typing.cast(
203
+ typing.Any,
204
+ construct_type(
205
+ type_=typing.Any, # type: ignore
206
+ object_=_response.json(),
207
+ ),
208
+ ),
209
+ )
210
+ _response_json = _response.json()
211
+ except JSONDecodeError:
212
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
213
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
214
+
215
+
216
+ class AsyncRawJobsClient:
217
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
218
+ self._client_wrapper = client_wrapper
219
+
220
+ async def get_job(
221
+ self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
222
+ ) -> AsyncHttpResponse[JobStatusResponse]:
223
+ """
224
+ Check the status and retrieve results of an asynchronous job
225
+ (e.g., submitted via `/extract_async`).
226
+
227
+ Parameters
228
+ ----------
229
+ job_id : str
230
+ Identifier returned from an async job submission (e.g., `/extract_async`).
231
+
232
+ request_options : typing.Optional[RequestOptions]
233
+ Request-specific configuration.
234
+
235
+ Returns
236
+ -------
237
+ AsyncHttpResponse[JobStatusResponse]
238
+ Current job status payload
239
+ """
240
+ _response = await self._client_wrapper.httpx_client.request(
241
+ f"job/{jsonable_encoder(job_id)}",
242
+ method="GET",
243
+ request_options=request_options,
244
+ )
245
+ try:
246
+ if 200 <= _response.status_code < 300:
247
+ _data = typing.cast(
248
+ JobStatusResponse,
249
+ construct_type(
250
+ type_=JobStatusResponse, # type: ignore
251
+ object_=_response.json(),
252
+ ),
253
+ )
254
+ return AsyncHttpResponse(response=_response, data=_data)
255
+ if _response.status_code == 401:
256
+ raise UnauthorizedError(
257
+ headers=dict(_response.headers),
258
+ body=typing.cast(
259
+ typing.Any,
260
+ construct_type(
261
+ type_=typing.Any, # type: ignore
262
+ object_=_response.json(),
263
+ ),
264
+ ),
265
+ )
266
+ if _response.status_code == 403:
267
+ raise ForbiddenError(
268
+ headers=dict(_response.headers),
269
+ body=typing.cast(
270
+ typing.Any,
271
+ construct_type(
272
+ type_=typing.Any, # type: ignore
273
+ object_=_response.json(),
274
+ ),
275
+ ),
276
+ )
277
+ if _response.status_code == 404:
278
+ raise NotFoundError(
279
+ headers=dict(_response.headers),
280
+ body=typing.cast(
281
+ typing.Any,
282
+ construct_type(
283
+ type_=typing.Any, # type: ignore
284
+ object_=_response.json(),
285
+ ),
286
+ ),
287
+ )
288
+ if _response.status_code == 429:
289
+ raise TooManyRequestsError(
290
+ headers=dict(_response.headers),
291
+ body=typing.cast(
292
+ typing.Any,
293
+ construct_type(
294
+ type_=typing.Any, # type: ignore
295
+ object_=_response.json(),
296
+ ),
297
+ ),
298
+ )
299
+ if _response.status_code == 500:
300
+ raise InternalServerError(
301
+ headers=dict(_response.headers),
302
+ body=typing.cast(
303
+ typing.Any,
304
+ construct_type(
305
+ type_=typing.Any, # type: ignore
306
+ object_=_response.json(),
307
+ ),
308
+ ),
309
+ )
310
+ _response_json = _response.json()
311
+ except JSONDecodeError:
312
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
313
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
314
+
315
+ async def cancel_job(
316
+ self, job_id: str, *, request_options: typing.Optional[RequestOptions] = None
317
+ ) -> AsyncHttpResponse[JobCancellationResponse]:
318
+ """
319
+ Attempts to cancel an asynchronous job that is currently pending
320
+ or processing. Jobs that have already completed will remain unchanged.
321
+
322
+ Parameters
323
+ ----------
324
+ job_id : str
325
+ Identifier returned from an async job submission (e.g., `/extract_async`).
326
+
327
+ request_options : typing.Optional[RequestOptions]
328
+ Request-specific configuration.
329
+
330
+ Returns
331
+ -------
332
+ AsyncHttpResponse[JobCancellationResponse]
333
+ Job cancellation accepted
334
+ """
335
+ _response = await self._client_wrapper.httpx_client.request(
336
+ f"job/{jsonable_encoder(job_id)}",
337
+ method="DELETE",
338
+ request_options=request_options,
339
+ )
340
+ try:
341
+ if 200 <= _response.status_code < 300:
342
+ _data = typing.cast(
343
+ JobCancellationResponse,
344
+ construct_type(
345
+ type_=JobCancellationResponse, # type: ignore
346
+ object_=_response.json(),
347
+ ),
348
+ )
349
+ return AsyncHttpResponse(response=_response, data=_data)
350
+ if _response.status_code == 401:
351
+ raise UnauthorizedError(
352
+ headers=dict(_response.headers),
353
+ body=typing.cast(
354
+ typing.Any,
355
+ construct_type(
356
+ type_=typing.Any, # type: ignore
357
+ object_=_response.json(),
358
+ ),
359
+ ),
360
+ )
361
+ if _response.status_code == 403:
362
+ raise ForbiddenError(
363
+ headers=dict(_response.headers),
364
+ body=typing.cast(
365
+ typing.Any,
366
+ construct_type(
367
+ type_=typing.Any, # type: ignore
368
+ object_=_response.json(),
369
+ ),
370
+ ),
371
+ )
372
+ if _response.status_code == 404:
373
+ raise NotFoundError(
374
+ headers=dict(_response.headers),
375
+ body=typing.cast(
376
+ typing.Any,
377
+ construct_type(
378
+ type_=typing.Any, # type: ignore
379
+ object_=_response.json(),
380
+ ),
381
+ ),
382
+ )
383
+ if _response.status_code == 429:
384
+ raise TooManyRequestsError(
385
+ headers=dict(_response.headers),
386
+ body=typing.cast(
387
+ typing.Any,
388
+ construct_type(
389
+ type_=typing.Any, # type: ignore
390
+ object_=_response.json(),
391
+ ),
392
+ ),
393
+ )
394
+ if _response.status_code == 500:
395
+ raise InternalServerError(
396
+ headers=dict(_response.headers),
397
+ body=typing.cast(
398
+ typing.Any,
399
+ construct_type(
400
+ type_=typing.Any, # type: ignore
401
+ object_=_response.json(),
402
+ ),
403
+ ),
404
+ )
405
+ _response_json = _response.json()
406
+ except JSONDecodeError:
407
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
408
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
pulse/py.typed ADDED
File without changes