retab 0.0.35__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 (111) hide show
  1. retab-0.0.35.dist-info/METADATA +417 -0
  2. retab-0.0.35.dist-info/RECORD +111 -0
  3. retab-0.0.35.dist-info/WHEEL +5 -0
  4. retab-0.0.35.dist-info/top_level.txt +1 -0
  5. uiform/__init__.py +4 -0
  6. uiform/_resource.py +28 -0
  7. uiform/_utils/__init__.py +0 -0
  8. uiform/_utils/ai_models.py +100 -0
  9. uiform/_utils/benchmarking copy.py +588 -0
  10. uiform/_utils/benchmarking.py +485 -0
  11. uiform/_utils/chat.py +332 -0
  12. uiform/_utils/display.py +443 -0
  13. uiform/_utils/json_schema.py +2161 -0
  14. uiform/_utils/mime.py +168 -0
  15. uiform/_utils/responses.py +163 -0
  16. uiform/_utils/stream_context_managers.py +52 -0
  17. uiform/_utils/usage/__init__.py +0 -0
  18. uiform/_utils/usage/usage.py +300 -0
  19. uiform/client.py +701 -0
  20. uiform/py.typed +0 -0
  21. uiform/resources/__init__.py +0 -0
  22. uiform/resources/consensus/__init__.py +3 -0
  23. uiform/resources/consensus/client.py +114 -0
  24. uiform/resources/consensus/completions.py +252 -0
  25. uiform/resources/consensus/completions_stream.py +278 -0
  26. uiform/resources/consensus/responses.py +325 -0
  27. uiform/resources/consensus/responses_stream.py +373 -0
  28. uiform/resources/deployments/__init__.py +9 -0
  29. uiform/resources/deployments/client.py +78 -0
  30. uiform/resources/deployments/endpoints.py +322 -0
  31. uiform/resources/deployments/links.py +452 -0
  32. uiform/resources/deployments/logs.py +211 -0
  33. uiform/resources/deployments/mailboxes.py +496 -0
  34. uiform/resources/deployments/outlook.py +531 -0
  35. uiform/resources/deployments/tests.py +158 -0
  36. uiform/resources/documents/__init__.py +3 -0
  37. uiform/resources/documents/client.py +255 -0
  38. uiform/resources/documents/extractions.py +441 -0
  39. uiform/resources/evals.py +812 -0
  40. uiform/resources/files.py +24 -0
  41. uiform/resources/finetuning.py +62 -0
  42. uiform/resources/jsonlUtils.py +1046 -0
  43. uiform/resources/models.py +45 -0
  44. uiform/resources/openai_example.py +22 -0
  45. uiform/resources/processors/__init__.py +3 -0
  46. uiform/resources/processors/automations/__init__.py +9 -0
  47. uiform/resources/processors/automations/client.py +78 -0
  48. uiform/resources/processors/automations/endpoints.py +317 -0
  49. uiform/resources/processors/automations/links.py +356 -0
  50. uiform/resources/processors/automations/logs.py +211 -0
  51. uiform/resources/processors/automations/mailboxes.py +435 -0
  52. uiform/resources/processors/automations/outlook.py +444 -0
  53. uiform/resources/processors/automations/tests.py +158 -0
  54. uiform/resources/processors/client.py +474 -0
  55. uiform/resources/prompt_optimization.py +76 -0
  56. uiform/resources/schemas.py +369 -0
  57. uiform/resources/secrets/__init__.py +9 -0
  58. uiform/resources/secrets/client.py +20 -0
  59. uiform/resources/secrets/external_api_keys.py +109 -0
  60. uiform/resources/secrets/webhook.py +62 -0
  61. uiform/resources/usage.py +271 -0
  62. uiform/types/__init__.py +0 -0
  63. uiform/types/ai_models.py +645 -0
  64. uiform/types/automations/__init__.py +0 -0
  65. uiform/types/automations/cron.py +58 -0
  66. uiform/types/automations/endpoints.py +21 -0
  67. uiform/types/automations/links.py +28 -0
  68. uiform/types/automations/mailboxes.py +60 -0
  69. uiform/types/automations/outlook.py +68 -0
  70. uiform/types/automations/webhooks.py +21 -0
  71. uiform/types/chat.py +8 -0
  72. uiform/types/completions.py +93 -0
  73. uiform/types/consensus.py +10 -0
  74. uiform/types/db/__init__.py +0 -0
  75. uiform/types/db/annotations.py +24 -0
  76. uiform/types/db/files.py +36 -0
  77. uiform/types/deployments/__init__.py +0 -0
  78. uiform/types/deployments/cron.py +59 -0
  79. uiform/types/deployments/endpoints.py +28 -0
  80. uiform/types/deployments/links.py +36 -0
  81. uiform/types/deployments/mailboxes.py +67 -0
  82. uiform/types/deployments/outlook.py +76 -0
  83. uiform/types/deployments/webhooks.py +21 -0
  84. uiform/types/documents/__init__.py +0 -0
  85. uiform/types/documents/correct_orientation.py +13 -0
  86. uiform/types/documents/create_messages.py +226 -0
  87. uiform/types/documents/extractions.py +297 -0
  88. uiform/types/evals.py +207 -0
  89. uiform/types/events.py +76 -0
  90. uiform/types/extractions.py +85 -0
  91. uiform/types/jobs/__init__.py +0 -0
  92. uiform/types/jobs/base.py +150 -0
  93. uiform/types/jobs/batch_annotation.py +22 -0
  94. uiform/types/jobs/evaluation.py +133 -0
  95. uiform/types/jobs/finetune.py +6 -0
  96. uiform/types/jobs/prompt_optimization.py +41 -0
  97. uiform/types/jobs/webcrawl.py +6 -0
  98. uiform/types/logs.py +231 -0
  99. uiform/types/mime.py +257 -0
  100. uiform/types/modalities.py +68 -0
  101. uiform/types/pagination.py +6 -0
  102. uiform/types/schemas/__init__.py +0 -0
  103. uiform/types/schemas/enhance.py +53 -0
  104. uiform/types/schemas/evaluate.py +55 -0
  105. uiform/types/schemas/generate.py +32 -0
  106. uiform/types/schemas/layout.py +58 -0
  107. uiform/types/schemas/object.py +631 -0
  108. uiform/types/schemas/templates.py +107 -0
  109. uiform/types/secrets/__init__.py +0 -0
  110. uiform/types/secrets/external_api_keys.py +22 -0
  111. uiform/types/standards.py +39 -0
@@ -0,0 +1,444 @@
1
+ import json
2
+ from io import IOBase
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Literal, Optional
5
+
6
+ from openai.types.chat.chat_completion_reasoning_effort import ChatCompletionReasoningEffort
7
+ from PIL.Image import Image
8
+ from pydantic import HttpUrl
9
+
10
+ from ...._resource import AsyncAPIResource, SyncAPIResource
11
+ from ...._utils.ai_models import assert_valid_model_extraction
12
+ from ....types.automations.outlook import FetchParams, ListOutlooks, MatchParams, Outlook, UpdateOutlookRequest
13
+ from ....types.logs import AutomationLog
14
+ from ....types.modalities import Modality
15
+ from ....types.standards import PreparedRequest
16
+
17
+
18
+ class OutlooksMixin:
19
+ def prepare_create(
20
+ self,
21
+ name: str,
22
+ json_schema: Dict[str, Any],
23
+ webhook_url: HttpUrl,
24
+ # email specific opitonals Fields
25
+ authorized_domains: List[str] = [],
26
+ authorized_emails: List[str] = [],
27
+ # HTTP Config Optional Fields
28
+ webhook_headers: Dict[str, str] = {},
29
+ # DocumentExtraction Config
30
+ image_resolution_dpi: Optional[int] = None,
31
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
32
+ modality: Modality = "native",
33
+ model: str = "gpt-4o-mini",
34
+ temperature: float = 0,
35
+ reasoning_effort: ChatCompletionReasoningEffort = "medium",
36
+ # Optional Fields for data integration
37
+ match_params: Optional[List[MatchParams]] = None,
38
+ fetch_params: Optional[List[FetchParams]] = None,
39
+ layout_schema: Optional[Dict[str, Any]] = None,
40
+ ) -> PreparedRequest:
41
+ assert_valid_model_extraction(model)
42
+
43
+ data = {
44
+ "name": name,
45
+ "webhook_url": webhook_url,
46
+ "webhook_headers": webhook_headers,
47
+ "json_schema": json_schema,
48
+ "authorized_domains": authorized_domains,
49
+ "authorized_emails": authorized_emails,
50
+ "image_resolution_dpi": image_resolution_dpi,
51
+ "browser_canvas": browser_canvas,
52
+ "modality": modality,
53
+ "model": model,
54
+ "temperature": temperature,
55
+ "reasoning_effort": reasoning_effort,
56
+ "layout_schema": layout_schema,
57
+ }
58
+
59
+ if match_params is not None:
60
+ data["match_params"] = match_params
61
+ if fetch_params is not None:
62
+ data["fetch_params"] = fetch_params
63
+
64
+ # Validate the data
65
+ outlook_data = Outlook.model_validate(data)
66
+ return PreparedRequest(method="POST", url="/v1/deployments/outlook", data=outlook_data.model_dump(mode="json"))
67
+
68
+ def prepare_list(
69
+ self,
70
+ before: str | None = None,
71
+ after: str | None = None,
72
+ limit: int = 10,
73
+ order: Literal["asc", "desc"] | None = "desc",
74
+ name: Optional[str] = None,
75
+ webhook_url: Optional[str] = None,
76
+ schema_id: Optional[str] = None,
77
+ schema_data_id: Optional[str] = None,
78
+ ) -> PreparedRequest:
79
+ params = {
80
+ "before": before,
81
+ "after": after,
82
+ "limit": limit,
83
+ "order": order,
84
+ "name": name,
85
+ "webhook_url": webhook_url,
86
+ "schema_id": schema_id,
87
+ "schema_data_id": schema_data_id,
88
+ }
89
+ # Remove None values
90
+ params = {k: v for k, v in params.items() if v is not None}
91
+
92
+ return PreparedRequest(method="GET", url="/v1/deployments/outlook", params=params)
93
+
94
+ def prepare_get(self, outlook_id: str) -> PreparedRequest:
95
+ return PreparedRequest(method="GET", url=f"/v1/processors/automations/outlook/{outlook_id}")
96
+
97
+ def prepare_update(
98
+ self,
99
+ outlook_id: str,
100
+ name: Optional[str] = None,
101
+ webhook_url: Optional[HttpUrl] = None,
102
+ webhook_headers: Optional[Dict[str, str]] = None,
103
+ authorized_domains: Optional[List[str]] = None,
104
+ authorized_emails: Optional[List[str]] = None,
105
+ image_resolution_dpi: Optional[int] = None,
106
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
107
+ modality: Optional[Modality] = None,
108
+ model: Optional[str] = None,
109
+ temperature: Optional[float] = None,
110
+ reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
111
+ json_schema: Optional[Dict[str, Any]] = None,
112
+ match_params: Optional[List[MatchParams]] = None,
113
+ fetch_params: Optional[List[FetchParams]] = None,
114
+ layout_schema: Optional[Dict[str, Any]] = None,
115
+ ) -> PreparedRequest:
116
+ data: dict[str, Any] = {}
117
+ if name is not None:
118
+ data["name"] = name
119
+ if webhook_url is not None:
120
+ data["webhook_url"] = webhook_url
121
+ if webhook_headers is not None:
122
+ data["webhook_headers"] = webhook_headers
123
+ if authorized_domains is not None:
124
+ data["authorized_domains"] = authorized_domains
125
+ if authorized_emails is not None:
126
+ data["authorized_emails"] = authorized_emails
127
+ if image_resolution_dpi is not None:
128
+ data["image_resolution_dpi"] = image_resolution_dpi
129
+ if browser_canvas is not None:
130
+ data["browser_canvas"] = browser_canvas
131
+ if modality is not None:
132
+ data["modality"] = modality
133
+ if model is not None:
134
+ assert_valid_model_extraction(model)
135
+ data["model"] = model
136
+ if temperature is not None:
137
+ data["temperature"] = temperature
138
+ if json_schema is not None:
139
+ data["json_schema"] = json_schema
140
+ if match_params is not None:
141
+ data["match_params"] = match_params
142
+ if fetch_params is not None:
143
+ data["fetch_params"] = fetch_params
144
+ if reasoning_effort is not None:
145
+ data["reasoning_effort"] = reasoning_effort
146
+ if layout_schema is not None:
147
+ data["layout_schema"] = layout_schema
148
+
149
+ update_outlook_request = UpdateOutlookRequest.model_validate(data)
150
+
151
+ return PreparedRequest(method="PUT", url=f"/v1/processors/automations/outlook/{outlook_id}", data=update_outlook_request.model_dump(mode="json"))
152
+
153
+ def prepare_delete(self, outlook_id: str) -> PreparedRequest:
154
+ return PreparedRequest(method="DELETE", url=f"/v1/processors/automations/outlook/{outlook_id}")
155
+
156
+ class Outlooks(SyncAPIResource, OutlooksMixin):
157
+ """Outlook API wrapper for managing outlook automation configurations"""
158
+
159
+ def __init__(self, client: Any) -> None:
160
+ super().__init__(client=client)
161
+
162
+ def create(
163
+ self,
164
+ name: str,
165
+ json_schema: Dict[str, Any],
166
+ webhook_url: HttpUrl,
167
+ authorized_domains: List[str] = [],
168
+ authorized_emails: List[str] = [],
169
+ webhook_headers: Dict[str, str] = {},
170
+ image_resolution_dpi: Optional[int] = None,
171
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
172
+ modality: Modality = "native",
173
+ model: str = "gpt-4o-mini",
174
+ temperature: float = 0,
175
+ reasoning_effort: ChatCompletionReasoningEffort = "medium",
176
+ match_params: Optional[List[MatchParams]] = None,
177
+ fetch_params: Optional[List[FetchParams]] = None,
178
+ ) -> Outlook:
179
+ """Create a new outlook automation configuration.
180
+
181
+ Args:
182
+ name: Name of the outlook plugin
183
+ json_schema: JSON schema to validate extracted data
184
+ webhook_url: Webhook URL to receive processed data
185
+ webhook_headers: Webhook headers to send with processed data
186
+ authorized_domains: List of authorized domains
187
+ authorized_emails: List of authorized emails
188
+ image_resolution_dpi: Optional image resolution DPI
189
+ browser_canvas: Optional browser canvas size
190
+ modality: Processing modality (currently only "native" supported)
191
+ model: AI model to use for processing
192
+ temperature: Model temperature setting
193
+ reasoning_effort: The effort level for the model to reason about the input data.
194
+ match_params: List of match parameters for the outlook automation
195
+ fetch_params: List of fetch parameters for the outlook automation
196
+ Returns:
197
+ Outlook: The created outlook plugin configuration
198
+ """
199
+
200
+ request = self.prepare_create(
201
+ name,
202
+ json_schema,
203
+ webhook_url,
204
+ authorized_domains,
205
+ authorized_emails,
206
+ webhook_headers,
207
+ image_resolution_dpi,
208
+ browser_canvas,
209
+ modality,
210
+ model,
211
+ temperature,
212
+ reasoning_effort,
213
+ match_params,
214
+ fetch_params,
215
+ )
216
+ response = self._client._prepared_request(request)
217
+
218
+ print(f"Outlook automation created. Outlook available at https://www.uiform.com/dashboard/processors/{response['id']}")
219
+
220
+ return Outlook.model_validate(response)
221
+
222
+ def list(
223
+ self,
224
+ before: str | None = None,
225
+ after: str | None = None,
226
+ limit: int = 10,
227
+ order: Literal["asc", "desc"] | None = "desc",
228
+ name: Optional[str] = None,
229
+ webhook_url: Optional[str] = None,
230
+ schema_id: Optional[str] = None,
231
+ schema_data_id: Optional[str] = None,
232
+ ) -> ListOutlooks:
233
+ """List all outlook automation configurations.
234
+
235
+ Args:
236
+ before: Optional cursor for pagination - get results before this log ID
237
+ after: Optional cursor for pagination - get results after this log ID
238
+ limit: Maximum number of logs to return (1-100, default 10)
239
+ order: Sort order by creation time - "asc" or "desc" (default "desc")
240
+ name: Optional name filter
241
+ webhook_url: Optional webhook URL filter
242
+ schema_id: Optional schema ID filter
243
+ schema_data_id: Optional schema data ID filter
244
+ match_params: Optional list of match parameters for the outlook automation
245
+ fetch_params: Optional list of fetch parameters for the outlook automation
246
+ Returns:
247
+ List[Outlook]: List of outlook plugin configurations
248
+ """
249
+ request = self.prepare_list(before, after, limit, order, name, webhook_url, schema_id, schema_data_id)
250
+ response = self._client._prepared_request(request)
251
+ return ListOutlooks.model_validate(response)
252
+
253
+ def get(self, id: str) -> Outlook:
254
+ """Get a specific outlook automation configuration.
255
+
256
+ Args:
257
+ id: ID of the outlook plugin
258
+
259
+ Returns:
260
+ Outlook: The outlook plugin configuration
261
+ """
262
+ request = self.prepare_get(id)
263
+ response = self._client._prepared_request(request)
264
+ return Outlook.model_validate(response)
265
+
266
+ def update(
267
+ self,
268
+ outlook_id: str,
269
+ name: Optional[str] = None,
270
+ webhook_url: Optional[HttpUrl] = None,
271
+ webhook_headers: Optional[Dict[str, str]] = None,
272
+ authorized_domains: Optional[List[str]] = None,
273
+ authorized_emails: Optional[List[str]] = None,
274
+ image_resolution_dpi: Optional[int] = None,
275
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
276
+ modality: Optional[Modality] = None,
277
+ model: Optional[str] = None,
278
+ temperature: Optional[float] = None,
279
+ reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
280
+ json_schema: Optional[Dict[str, Any]] = None,
281
+ match_params: Optional[List[MatchParams]] = None,
282
+ fetch_params: Optional[List[FetchParams]] = None,
283
+ layout_schema: Optional[Dict[str, Any]] = None,
284
+ ) -> Outlook:
285
+ """Update an outlook automation configuration.
286
+
287
+ Args:
288
+ outlook_id: ID of the outlook plugin to update
289
+ name: New name for the outlook plugin
290
+ webhook_url: New webhook URL
291
+ webhook_headers: New webhook headers
292
+ authorized_domains: New authorized domains
293
+ authorized_emails: New authorized emails
294
+ image_resolution_dpi: New image resolution DPI
295
+ browser_canvas: New browser canvas size
296
+ modality: New processing modality
297
+ model: New AI model
298
+ temperature: New temperature setting
299
+ reasoning_effort: New reasoning effort
300
+ json_schema: New JSON schema
301
+ match_params: New match parameters for the outlook automation
302
+ fetch_params: New fetch parameters for the outlook automation
303
+ layout_schema: New layout schema for the outlook automation
304
+
305
+ Returns:
306
+ Outlook: The updated outlook plugin configuration
307
+ """
308
+ request = self.prepare_update(
309
+ outlook_id,
310
+ name,
311
+ webhook_url,
312
+ webhook_headers,
313
+ authorized_domains,
314
+ authorized_emails,
315
+ image_resolution_dpi,
316
+ browser_canvas,
317
+ modality,
318
+ model,
319
+ temperature,
320
+ reasoning_effort,
321
+ json_schema,
322
+ match_params,
323
+ fetch_params,
324
+ layout_schema,
325
+ )
326
+ response = self._client._prepared_request(request)
327
+ return Outlook.model_validate(response)
328
+
329
+ def delete(self, outlook_id: str) -> None:
330
+ """Delete an outlook automation configuration.
331
+
332
+ Args:
333
+ outlook_id: ID of the outlook plugin to delete
334
+ """
335
+ request = self.prepare_delete(outlook_id)
336
+ response = self._client._prepared_request(request)
337
+ return None
338
+
339
+
340
+ class AsyncOutlooks(AsyncAPIResource, OutlooksMixin):
341
+ def __init__(self, client: Any) -> None:
342
+ super().__init__(client=client)
343
+
344
+ async def create(
345
+ self,
346
+ name: str,
347
+ json_schema: Dict[str, Any],
348
+ webhook_url: HttpUrl,
349
+ authorized_domains: List[str] = [],
350
+ authorized_emails: List[str] = [],
351
+ webhook_headers: Dict[str, str] = {},
352
+ image_resolution_dpi: Optional[int] = None,
353
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
354
+ modality: Modality = "native",
355
+ model: str = "gpt-4o-mini",
356
+ temperature: float = 0,
357
+ reasoning_effort: ChatCompletionReasoningEffort = "medium",
358
+ match_params: List[MatchParams] = [],
359
+ fetch_params: List[FetchParams] = [],
360
+ ) -> Outlook:
361
+ request = self.prepare_create(
362
+ name,
363
+ json_schema,
364
+ webhook_url,
365
+ authorized_domains,
366
+ authorized_emails,
367
+ webhook_headers,
368
+ image_resolution_dpi,
369
+ browser_canvas,
370
+ modality,
371
+ model,
372
+ temperature,
373
+ reasoning_effort,
374
+ match_params,
375
+ fetch_params,
376
+ )
377
+ response = await self._client._prepared_request(request)
378
+ print(f"Outlook automation created. Outlook available at https://www.uiform.com/dashboard/processors/{response['id']}")
379
+ return Outlook.model_validate(response)
380
+
381
+ async def list(
382
+ self,
383
+ before: str | None = None,
384
+ after: str | None = None,
385
+ limit: int = 10,
386
+ order: Literal["asc", "desc"] | None = "desc",
387
+ name: Optional[str] = None,
388
+ webhook_url: Optional[str] = None,
389
+ schema_id: Optional[str] = None,
390
+ schema_data_id: Optional[str] = None,
391
+ ) -> ListOutlooks:
392
+ request = self.prepare_list(before, after, limit, order, name, webhook_url, schema_id, schema_data_id)
393
+ response = await self._client._prepared_request(request)
394
+ return ListOutlooks.model_validate(response)
395
+
396
+ async def get(self, outlook_id: str) -> Outlook:
397
+ request = self.prepare_get(outlook_id)
398
+ response = await self._client._prepared_request(request)
399
+ return Outlook.model_validate(response)
400
+
401
+ async def update(
402
+ self,
403
+ outlook_id: str,
404
+ name: Optional[str] = None,
405
+ webhook_url: Optional[HttpUrl] = None,
406
+ webhook_headers: Optional[Dict[str, str]] = None,
407
+ authorized_domains: Optional[List[str]] = None,
408
+ authorized_emails: Optional[List[str]] = None,
409
+ image_resolution_dpi: Optional[int] = None,
410
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
411
+ modality: Optional[Modality] = None,
412
+ model: Optional[str] = None,
413
+ temperature: Optional[float] = None,
414
+ reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
415
+ json_schema: Optional[Dict[str, Any]] = None,
416
+ match_params: Optional[List[MatchParams]] = None,
417
+ fetch_params: Optional[List[FetchParams]] = None,
418
+ layout_schema: Optional[Dict[str, Any]] = None,
419
+ ) -> Outlook:
420
+ request = self.prepare_update(
421
+ outlook_id,
422
+ name,
423
+ webhook_url,
424
+ webhook_headers,
425
+ authorized_domains,
426
+ authorized_emails,
427
+ image_resolution_dpi,
428
+ browser_canvas,
429
+ modality,
430
+ model,
431
+ temperature,
432
+ reasoning_effort,
433
+ json_schema,
434
+ match_params,
435
+ fetch_params,
436
+ layout_schema,
437
+ )
438
+ response = await self._client._prepared_request(request)
439
+ return Outlook.model_validate(response)
440
+
441
+ async def delete(self, outlook_id: str) -> None:
442
+ request = self.prepare_delete(outlook_id)
443
+ await self._client._prepared_request(request)
444
+ return None
@@ -0,0 +1,158 @@
1
+ import datetime
2
+ import json
3
+ from io import IOBase
4
+ from pathlib import Path
5
+ from typing import Any, Dict, Literal, Optional
6
+
7
+ import httpx
8
+ from pydantic import HttpUrl
9
+ from PIL.Image import Image
10
+
11
+ from ...._resource import AsyncAPIResource, SyncAPIResource
12
+ from ...._utils.mime import prepare_mime_document
13
+ from ....types.mime import BaseMIMEData, MIMEData
14
+ from ....types.logs import AutomationLog
15
+ from ....types.standards import PreparedRequest
16
+
17
+
18
+ class TestsMixin:
19
+ def prepare_upload(self, automation_id: str, document: Path | str | IOBase | HttpUrl | Image | MIMEData) -> PreparedRequest:
20
+ mime_document = prepare_mime_document(document)
21
+ return PreparedRequest(method="POST", url=f"/v1/processors/automations/tests/upload/{automation_id}", data={"document": mime_document.model_dump(mode='json')})
22
+
23
+ def prepare_webhook(self, automation_id: str) -> PreparedRequest:
24
+ return PreparedRequest(method="POST", url=f"/v1/processors/automations/tests/webhook/{automation_id}", data=None)
25
+
26
+ def print_upload_verbose(self, log: AutomationLog) -> None:
27
+ if log.external_request_log:
28
+ print(f"\nTEST FILE UPLOAD RESULTS:")
29
+ print(f"\n#########################")
30
+ print(f"Status Code: {log.external_request_log.status_code}")
31
+ print(f"Duration: {log.external_request_log.duration_ms:.2f}ms")
32
+
33
+ if log.external_request_log.error:
34
+ print(f"\nERROR: {log.external_request_log.error}")
35
+
36
+ if log.external_request_log.response_body:
37
+ print("\n--------------")
38
+ print("RESPONSE BODY:")
39
+ print("--------------")
40
+ print(json.dumps(log.external_request_log.response_body, indent=2))
41
+
42
+ if log.external_request_log.response_headers:
43
+ print("\n--------------")
44
+ print("RESPONSE HEADERS:")
45
+ print("--------------")
46
+ print(json.dumps(log.external_request_log.response_headers, indent=2))
47
+
48
+ def print_webhook_verbose(self, log: AutomationLog) -> None:
49
+ if log.external_request_log:
50
+ print(f"\nTEST WEBHOOK RESULTS:")
51
+ print(f"\n#########################")
52
+ print(f"Status Code: {log.external_request_log.status_code}")
53
+ print(f"Duration: {log.external_request_log.duration_ms:.2f}ms")
54
+
55
+ if log.external_request_log.error:
56
+ print(f"\nERROR: {log.external_request_log.error}")
57
+
58
+ if log.external_request_log.response_body:
59
+ print("\n--------------")
60
+ print("RESPONSE BODY:")
61
+ print("--------------")
62
+ print(json.dumps(log.external_request_log.response_body, indent=2))
63
+
64
+ if log.external_request_log.response_headers:
65
+ print("\n--------------")
66
+ print("RESPONSE HEADERS:")
67
+ print("--------------")
68
+ print(json.dumps(log.external_request_log.response_headers, indent=2))
69
+
70
+
71
+ class Tests(SyncAPIResource, TestsMixin):
72
+ """Test API wrapper for testing automation configurations"""
73
+
74
+ def upload(self, automation_id: str, document: Path | str | IOBase | HttpUrl | Image | MIMEData, verbose: bool = True) -> AutomationLog:
75
+ """Test endpoint that simulates the complete extraction process with the provided document.
76
+
77
+ Args:
78
+ automation_id: ID of the automation to test
79
+ document: Document to process
80
+ verbose: Whether to print verbose output
81
+
82
+ Returns:
83
+ AutomationLog: The automation log with extraction results
84
+ """
85
+ request = self.prepare_upload(automation_id, document)
86
+ response = self._client._prepared_request(request)
87
+
88
+ log = AutomationLog.model_validate(response)
89
+
90
+ if verbose:
91
+ self.print_upload_verbose(log)
92
+
93
+ return log
94
+
95
+ def webhook(self, automation_id: str, verbose: bool = True) -> AutomationLog:
96
+ """Test endpoint that simulates the complete webhook process with sample data.
97
+
98
+ Args:
99
+ automation_id: ID of the automation to test
100
+ verbose: Whether to print verbose output
101
+
102
+ Returns:
103
+ AutomationLog: The automation log with webhook results
104
+ """
105
+ request = self.prepare_webhook(automation_id)
106
+ response = self._client._prepared_request(request)
107
+
108
+ log = AutomationLog.model_validate(response)
109
+
110
+ if verbose:
111
+ self.print_webhook_verbose(log)
112
+
113
+ return log
114
+
115
+
116
+ class AsyncTests(AsyncAPIResource, TestsMixin):
117
+ """Async Test API wrapper for testing deployment configurations"""
118
+
119
+ async def upload(self, automation_id: str, document: Path | str | IOBase | HttpUrl | Image | MIMEData, verbose: bool = True) -> AutomationLog:
120
+ """Test endpoint that simulates the complete extraction process with the provided document.
121
+
122
+ Args:
123
+ automation_id: ID of the automation to test
124
+ document: Document to process
125
+ verbose: Whether to print verbose output
126
+
127
+ Returns:
128
+ AutomationLog: The automation log with extraction results
129
+ """
130
+ request = self.prepare_upload(automation_id, document)
131
+ response = await self._client._prepared_request(request)
132
+
133
+ log = AutomationLog.model_validate(response)
134
+
135
+ if verbose:
136
+ self.print_upload_verbose(log)
137
+
138
+ return log
139
+
140
+ async def webhook(self, automation_id: str, verbose: bool = True) -> AutomationLog:
141
+ """Test endpoint that simulates the complete webhook process with sample data.
142
+
143
+ Args:
144
+ automation_id: ID of the automation to test
145
+ verbose: Whether to print verbose output
146
+
147
+ Returns:
148
+ AutomationLog: The automation log with webhook results
149
+ """
150
+ request = self.prepare_webhook(automation_id)
151
+ response = await self._client._prepared_request(request)
152
+
153
+ log = AutomationLog.model_validate(response)
154
+
155
+ if verbose:
156
+ self.print_webhook_verbose(log)
157
+
158
+ return log