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,496 @@
1
+ import datetime
2
+ import json
3
+ from io import IOBase
4
+ from pathlib import Path
5
+ from typing import Any, Dict, List, Literal, Optional
6
+
7
+ import httpx
8
+ from openai.types.chat.chat_completion_reasoning_effort import ChatCompletionReasoningEffort
9
+ from PIL.Image import Image
10
+ from pydantic import HttpUrl
11
+
12
+ from ..._resource import AsyncAPIResource, SyncAPIResource
13
+ from ..._utils.ai_models import assert_valid_model_extraction
14
+ from ..._utils.mime import prepare_mime_document
15
+ from ...types.automations.mailboxes import ListMailboxes, Mailbox, UpdateMailboxRequest
16
+ from ...types.documents.extractions import UiParsedChatCompletion
17
+ from ...types.logs import AutomationLog, ExternalRequestLog
18
+ from ...types.mime import BaseMIMEData, EmailData, MIMEData
19
+ from ...types.modalities import Modality
20
+ from ...types.standards import PreparedRequest
21
+
22
+
23
+ class MailBoxesMixin:
24
+ def prepare_create(
25
+ self,
26
+ email: str,
27
+ json_schema: Dict[str, Any],
28
+ webhook_url: HttpUrl,
29
+ # email specific opitonals Fields
30
+ authorized_domains: List[str] = [],
31
+ authorized_emails: List[str] = [],
32
+ # HTTP Config Optional Fields
33
+ webhook_headers: Dict[str, str] = {},
34
+ # DocumentExtraction Config
35
+ image_resolution_dpi: int = 96,
36
+ browser_canvas: Literal['A3', 'A4', 'A5'] = 'A4',
37
+ modality: Modality = "native",
38
+ model: str = "gpt-4o-mini",
39
+ temperature: float = 0,
40
+ reasoning_effort: ChatCompletionReasoningEffort = "medium",
41
+ ) -> PreparedRequest:
42
+ assert_valid_model_extraction(model)
43
+
44
+ data = {
45
+ "email": email,
46
+ "webhook_url": webhook_url,
47
+ "webhook_headers": webhook_headers,
48
+ "json_schema": json_schema,
49
+ "authorized_domains": authorized_domains,
50
+ "authorized_emails": authorized_emails,
51
+ "image_resolution_dpi": image_resolution_dpi,
52
+ "browser_canvas": browser_canvas,
53
+ "modality": modality,
54
+ "model": model,
55
+ "temperature": temperature,
56
+ "reasoning_effort": reasoning_effort,
57
+ }
58
+
59
+ # Validate the data
60
+ mailbox_data = Mailbox.model_validate(data)
61
+ return PreparedRequest(method="POST", url="/v1/deployments/mailboxes", data=mailbox_data.model_dump(mode="json"))
62
+
63
+ def prepare_list(
64
+ self,
65
+ before: str | None = None,
66
+ after: str | None = None,
67
+ limit: int = 10,
68
+ order: Literal["asc", "desc"] | None = "desc",
69
+ email: Optional[str] = None,
70
+ webhook_url: Optional[str] = None,
71
+ schema_id: Optional[str] = None,
72
+ schema_data_id: Optional[str] = None,
73
+ ) -> PreparedRequest:
74
+ params = {
75
+ "before": before,
76
+ "after": after,
77
+ "limit": limit,
78
+ "order": order,
79
+ "email": email,
80
+ "webhook_url": webhook_url,
81
+ "schema_id": schema_id,
82
+ "schema_data_id": schema_data_id,
83
+ }
84
+ # Remove None values
85
+ params = {k: v for k, v in params.items() if v is not None}
86
+
87
+ return PreparedRequest(method="GET", url="/v1/deployments/mailboxes", params=params)
88
+
89
+ def prepare_get(self, email: str) -> PreparedRequest:
90
+ return PreparedRequest(method="GET", url=f"/v1/deployments/mailboxes/{email}")
91
+
92
+ def prepare_update(
93
+ self,
94
+ email: str,
95
+ webhook_url: Optional[HttpUrl] = None,
96
+ webhook_headers: Optional[Dict[str, str]] = None,
97
+ authorized_domains: Optional[List[str]] = None,
98
+ authorized_emails: Optional[List[str]] = None,
99
+ image_resolution_dpi: Optional[int] = None,
100
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
101
+ modality: Optional[Modality] = None,
102
+ model: Optional[str] = None,
103
+ temperature: Optional[float] = None,
104
+ reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
105
+ json_schema: Optional[Dict[str, Any]] = None,
106
+ ) -> PreparedRequest:
107
+ data: dict[str, Any] = {}
108
+ if webhook_url is not None:
109
+ data["webhook_url"] = webhook_url
110
+ if webhook_headers is not None:
111
+ data["webhook_headers"] = webhook_headers
112
+ if authorized_domains is not None:
113
+ data["authorized_domains"] = authorized_domains
114
+ if authorized_emails is not None:
115
+ data["authorized_emails"] = authorized_emails
116
+ if image_resolution_dpi is not None:
117
+ data["image_resolution_dpi"] = image_resolution_dpi
118
+ if browser_canvas is not None:
119
+ data["browser_canvas"] = browser_canvas
120
+ if modality is not None:
121
+ data["modality"] = modality
122
+ if model is not None:
123
+ assert_valid_model_extraction(model)
124
+ data["model"] = model
125
+ if temperature is not None:
126
+ data["temperature"] = temperature
127
+ if reasoning_effort is not None:
128
+ data["reasoning_effort"] = reasoning_effort
129
+ if json_schema is not None:
130
+ data["json_schema"] = json_schema
131
+
132
+ update_mailbox_request = UpdateMailboxRequest.model_validate(data)
133
+
134
+ return PreparedRequest(method="PUT", url=f"/v1/deployments/mailboxes/{email}", data=update_mailbox_request.model_dump(mode="json"))
135
+
136
+ def prepare_delete(self, email: str) -> PreparedRequest:
137
+ return PreparedRequest(method="DELETE", url=f"/v1/deployments/mailboxes/{email}", raise_for_status=True)
138
+
139
+ def prepare_logs(
140
+ self,
141
+ before: str | None = None,
142
+ after: str | None = None,
143
+ limit: int = 10,
144
+ order: Literal["asc", "desc"] | None = "desc",
145
+ email: Optional[str] = None,
146
+ webhook_url: Optional[str] = None,
147
+ schema_id: Optional[str] = None,
148
+ schema_data_id: Optional[str] = None,
149
+ ) -> PreparedRequest:
150
+ params = {
151
+ "email": email,
152
+ "webhook_url": webhook_url,
153
+ "schema_id": schema_id,
154
+ "schema_data_id": schema_data_id,
155
+ "before": before,
156
+ "after": after,
157
+ "limit": limit,
158
+ "order": order,
159
+ }
160
+ return PreparedRequest(method="GET", url=f"/v1/deployments/mailboxes/{email}/logs", params=params)
161
+
162
+
163
+ class Mailboxes(SyncAPIResource, MailBoxesMixin):
164
+ """Emails API wrapper for managing email automation configurations"""
165
+
166
+ def __init__(self, client: Any) -> None:
167
+ super().__init__(client=client)
168
+ self.tests = TestMailboxes(client=client)
169
+
170
+ def create(
171
+ self,
172
+ email: str,
173
+ json_schema: Dict[str, Any],
174
+ webhook_url: HttpUrl,
175
+ # email specific opitonals Fields
176
+ authorized_domains: List[str] = [],
177
+ authorized_emails: List[str] = [],
178
+ # HTTP Config Optional Fields
179
+ webhook_headers: Dict[str, str] = {},
180
+ # DocumentExtraction Config
181
+ image_resolution_dpi: int = 96,
182
+ browser_canvas: Literal['A3', 'A4', 'A5'] = 'A4',
183
+ modality: Modality = "native",
184
+ model: str = "gpt-4o-mini",
185
+ temperature: float = 0,
186
+ reasoning_effort: ChatCompletionReasoningEffort = "medium",
187
+ ) -> Mailbox:
188
+ """Create a new email automation configuration.
189
+
190
+ Args:
191
+ email: Email address for the mailbox
192
+ json_schema: JSON schema to validate extracted email data
193
+ webhook_url: Webhook URL to receive processed emails
194
+ webhook_headers: Webhook headers to send with processed emails
195
+ authorized_domains: List of authorized domains for the mailbox
196
+ authorized_emails: List of authorized emails for the mailbox
197
+ image_resolution_dpi: Image resolution DPI
198
+ browser_canvas: Browser canvas size
199
+ modality: Processing modality (currently only "native" supported)
200
+ model: AI model to use for processing
201
+ temperature: Model temperature setting
202
+ reasoning_effort: The effort level for the model to reason about the input data.
203
+
204
+ Returns:
205
+ Mailbox: The created mailbox configuration
206
+ """
207
+
208
+ request = self.prepare_create(
209
+ email, json_schema, webhook_url, authorized_domains, authorized_emails, webhook_headers, image_resolution_dpi, browser_canvas, modality, model, temperature, reasoning_effort
210
+ )
211
+ response = self._client._prepared_request(request)
212
+
213
+ print(f"Email automation created. Mailbox available at https://www.uiform.com/dashboard/processors/{response['id']}")
214
+
215
+ return Mailbox.model_validate(response)
216
+
217
+ def list(
218
+ self,
219
+ before: str | None = None,
220
+ after: str | None = None,
221
+ limit: int = 10,
222
+ order: Literal["asc", "desc"] | None = "desc",
223
+ email: Optional[str] = None,
224
+ webhook_url: Optional[str] = None,
225
+ schema_id: Optional[str] = None,
226
+ schema_data_id: Optional[str] = None,
227
+ ) -> ListMailboxes:
228
+ """List all email automation configurations.
229
+
230
+ Args:
231
+ before: Optional cursor for pagination - get results before this log ID
232
+ after: Optional cursor for pagination - get results after this log ID
233
+ limit: Maximum number of logs to return (1-100, default 10)
234
+ order: Sort order by creation time - "asc" or "desc" (default "desc")
235
+ email: Optional email address filter
236
+ webhook_url: Optional webhook URL filter
237
+ schema_id: Optional schema ID filter
238
+ schema_data_id: Optional schema data ID filter
239
+
240
+ Returns:
241
+ ListMailboxes: List of mailbox configurations
242
+ """
243
+ request = self.prepare_list(before, after, limit, order, email, webhook_url, schema_id, schema_data_id)
244
+ response = self._client._prepared_request(request)
245
+ return ListMailboxes.model_validate(response)
246
+
247
+ def get(self, email: str) -> Mailbox:
248
+ """Get a specific email automation configuration.
249
+
250
+ Args:
251
+ email: Email address of the mailbox
252
+
253
+ Returns:
254
+ Mailbox: The mailbox configuration
255
+ """
256
+ request = self.prepare_get(email)
257
+ response = self._client._prepared_request(request)
258
+ return Mailbox.model_validate(response)
259
+
260
+ def update(
261
+ self,
262
+ email: str,
263
+ webhook_url: Optional[HttpUrl] = None,
264
+ webhook_headers: Optional[Dict[str, str]] = None,
265
+ authorized_domains: Optional[List[str]] = None,
266
+ authorized_emails: Optional[List[str]] = None,
267
+ image_resolution_dpi: Optional[int] = None,
268
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
269
+ modality: Optional[Modality] = None,
270
+ model: Optional[str] = None,
271
+ temperature: Optional[float] = None,
272
+ reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
273
+ json_schema: Optional[Dict[str, Any]] = None,
274
+ ) -> Mailbox:
275
+ """Update an email automation configuration.
276
+
277
+ Args:
278
+ email: Email address of the mailbox to update
279
+ webhook_url: New webhook configuration
280
+ webhook_headers: New webhook configuration
281
+ max_file_size: New webhook configuration
282
+ file_payload: New webhook configuration
283
+ follow_up: New webhook configuration
284
+ authorized_domains: New webhook configuration
285
+ authorized_emails: New webhook configuration
286
+ image_resolution_dpi: New image resolution DPI
287
+ browser_canvas: New browser canvas size
288
+ modality: New processing modality
289
+ model: New AI model
290
+ temperature: New temperature setting
291
+ reasoning_effort: New reasoning effort
292
+ json_schema: New JSON schema
293
+
294
+ Returns:
295
+ Mailbox: The updated mailbox configuration
296
+ """
297
+ request = self.prepare_update(
298
+ email, webhook_url, webhook_headers, authorized_domains, authorized_emails, image_resolution_dpi, browser_canvas, modality, model, temperature, reasoning_effort, json_schema
299
+ )
300
+ response = self._client._prepared_request(request)
301
+ return Mailbox.model_validate(response)
302
+
303
+ def delete(self, email: str) -> None:
304
+ """Delete an email automation configuration.
305
+
306
+ Args:
307
+ email: Email address of the mailbox to delete
308
+ """
309
+ request = self.prepare_delete(email)
310
+ response = self._client._prepared_request(request)
311
+ return None
312
+
313
+ def logs(
314
+ self,
315
+ before: str | None = None,
316
+ after: str | None = None,
317
+ limit: int = 10,
318
+ order: Literal["asc", "desc"] | None = "desc",
319
+ email: Optional[str] = None,
320
+ webhook_url: Optional[str] = None,
321
+ schema_id: Optional[str] = None,
322
+ schema_data_id: Optional[str] = None,
323
+ ) -> List[AutomationLog]:
324
+ """Get logs for a specific email automation.
325
+
326
+ Args:
327
+ before: Optional cursor for pagination - get results before this log ID
328
+ after: Optional cursor for pagination - get results after this log ID
329
+ limit: Maximum number of logs to return (1-100, default 10)
330
+ order: Sort order by creation time - "asc" or "desc" (default "desc")
331
+ email: Optional email address filter
332
+ webhook_url: Optional webhook URL filter
333
+ schema_id: Optional schema ID filter
334
+ schema_data_id: Optional schema data ID filter
335
+
336
+ Returns:
337
+ List[Dict[str, Any]]: List of log entries
338
+ """
339
+ request = self.prepare_logs(before, after, limit, order, email, webhook_url, schema_id, schema_data_id)
340
+ response = self._client._prepared_request(request)
341
+ return [AutomationLog.model_validate(log) for log in response]
342
+
343
+
344
+ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
345
+ def __init__(self, client: Any) -> None:
346
+ super().__init__(client=client)
347
+ self.tests = AsyncTestMailboxes(client=client)
348
+
349
+ async def create(
350
+ self,
351
+ email: str,
352
+ json_schema: Dict[str, Any],
353
+ webhook_url: HttpUrl,
354
+ authorized_domains: List[str] = [],
355
+ authorized_emails: List[str] = [],
356
+ webhook_headers: Dict[str, str] = {},
357
+ image_resolution_dpi: int = 96,
358
+ browser_canvas: Literal['A3', 'A4', 'A5'] = 'A4',
359
+ modality: Modality = "native",
360
+ model: str = "gpt-4o-mini",
361
+ temperature: float = 0,
362
+ reasoning_effort: ChatCompletionReasoningEffort = "medium",
363
+ ) -> Mailbox:
364
+ request = self.prepare_create(
365
+ email, json_schema, webhook_url, authorized_domains, authorized_emails, webhook_headers, image_resolution_dpi, browser_canvas, modality, model, temperature, reasoning_effort
366
+ )
367
+ response = await self._client._prepared_request(request)
368
+
369
+ print(f"Email automation created. Mailbox available at https://www.uiform.com/dashboard/processors/{response['id']}")
370
+
371
+ return Mailbox.model_validate(response)
372
+
373
+ async def list(
374
+ self,
375
+ before: str | None = None,
376
+ after: str | None = None,
377
+ limit: int = 10,
378
+ order: Literal["asc", "desc"] | None = "desc",
379
+ email: Optional[str] = None,
380
+ webhook_url: Optional[str] = None,
381
+ schema_id: Optional[str] = None,
382
+ schema_data_id: Optional[str] = None,
383
+ ) -> ListMailboxes:
384
+ request = self.prepare_list(before, after, limit, order, email, webhook_url, schema_id, schema_data_id)
385
+ response = await self._client._prepared_request(request)
386
+ return ListMailboxes.model_validate(response)
387
+
388
+ async def get(self, email: str) -> Mailbox:
389
+ request = self.prepare_get(email)
390
+ response = await self._client._prepared_request(request)
391
+ return Mailbox.model_validate(response)
392
+
393
+ async def update(
394
+ self,
395
+ email: str,
396
+ webhook_url: Optional[HttpUrl] = None,
397
+ webhook_headers: Optional[Dict[str, str]] = None,
398
+ authorized_domains: Optional[List[str]] = None,
399
+ authorized_emails: Optional[List[str]] = None,
400
+ image_resolution_dpi: Optional[int] = None,
401
+ browser_canvas: Optional[Literal['A3', 'A4', 'A5']] = None,
402
+ modality: Optional[Modality] = None,
403
+ model: Optional[str] = None,
404
+ temperature: Optional[float] = None,
405
+ reasoning_effort: Optional[ChatCompletionReasoningEffort] = None,
406
+ json_schema: Optional[Dict[str, Any]] = None,
407
+ ) -> Mailbox:
408
+ request = self.prepare_update(
409
+ email, webhook_url, webhook_headers, authorized_domains, authorized_emails, image_resolution_dpi, browser_canvas, modality, model, temperature, reasoning_effort, json_schema
410
+ )
411
+ response = await self._client._prepared_request(request)
412
+ return Mailbox.model_validate(response)
413
+
414
+ async def delete(self, email: str) -> None:
415
+ request = self.prepare_delete(email)
416
+ await self._client._prepared_request(request)
417
+ return None
418
+
419
+ async def logs(
420
+ self,
421
+ before: str | None = None,
422
+ after: str | None = None,
423
+ limit: int = 10,
424
+ order: Literal["asc", "desc"] | None = "desc",
425
+ email: Optional[str] = None,
426
+ webhook_url: Optional[str] = None,
427
+ schema_id: Optional[str] = None,
428
+ schema_data_id: Optional[str] = None,
429
+ ) -> List[AutomationLog]:
430
+ request = self.prepare_logs(before, after, limit, order, email, webhook_url, schema_id, schema_data_id)
431
+ response = await self._client._prepared_request(request)
432
+ return [AutomationLog.model_validate(log) for log in response]
433
+
434
+
435
+ class TestMailboxesMixin:
436
+ def prepare_forward(
437
+ self,
438
+ email: str,
439
+ document: Path | str | IOBase | HttpUrl | MIMEData,
440
+ verbose: bool = True,
441
+ ) -> PreparedRequest:
442
+ mime_document = prepare_mime_document(document)
443
+ return PreparedRequest(method="POST", url=f"/v1/deployments/mailboxes/tests/forward/{email}", data={"document": mime_document.model_dump()})
444
+
445
+ def print_forward_verbose(self, email_data: EmailData) -> None:
446
+ print(f"\nTEST EMAIL FORWARDING RESULTS:")
447
+ print(f"\n#########################")
448
+ print(f"Email ID: {email_data.id}")
449
+ print(f"Subject: {email_data.subject}")
450
+ print(f"From: {email_data.sender}")
451
+ print(f"To: {', '.join(str(r) for r in email_data.recipients_to)}")
452
+ if email_data.recipients_cc:
453
+ print(f"CC: {', '.join(str(r) for r in email_data.recipients_cc)}")
454
+ print(f"Sent at: {email_data.sent_at}")
455
+ print(f"Attachments: {len(email_data.attachments)}")
456
+ if email_data.body_plain:
457
+ print("\nBody Preview:")
458
+ print(email_data.body_plain[:500] + "..." if len(email_data.body_plain) > 500 else email_data.body_plain)
459
+
460
+ class TestMailboxes(SyncAPIResource, TestMailboxesMixin):
461
+ def forward(
462
+ self,
463
+ email: str,
464
+ document: Path | str | IOBase | HttpUrl | MIMEData,
465
+ verbose: bool = True,
466
+ ) -> EmailData:
467
+ """Mock endpoint that simulates the complete email forwarding process with sample data.
468
+
469
+ Args:
470
+ email: Email address of the mailbox to mock
471
+
472
+ Returns:
473
+ DocumentExtractResponse: The simulated extraction response
474
+ """
475
+ request = self.prepare_forward(email, document, verbose)
476
+ response = self._client._prepared_request(request)
477
+
478
+ email_data = EmailData.model_validate(response)
479
+
480
+ if verbose:
481
+ self.print_forward_verbose(email_data)
482
+ return email_data
483
+
484
+ class AsyncTestMailboxes(AsyncAPIResource, TestMailboxesMixin):
485
+ async def forward(
486
+ self,
487
+ email: str,
488
+ document: Path | str | IOBase | HttpUrl | MIMEData,
489
+ verbose: bool = True,
490
+ ) -> EmailData:
491
+ request = self.prepare_forward(email, document, verbose)
492
+ response = await self._client._prepared_request(request)
493
+ email_data = EmailData.model_validate(response)
494
+ if verbose:
495
+ self.print_forward_verbose(email_data)
496
+ return email_data