retab 0.0.36__py3-none-any.whl → 0.0.38__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 (123) hide show
  1. retab/__init__.py +4 -0
  2. {uiform → retab}/_resource.py +5 -5
  3. {uiform → retab}/_utils/ai_models.py +2 -2
  4. {uiform → retab}/_utils/benchmarking.py +15 -16
  5. {uiform → retab}/_utils/chat.py +29 -34
  6. {uiform → retab}/_utils/display.py +0 -3
  7. {uiform → retab}/_utils/json_schema.py +9 -14
  8. {uiform → retab}/_utils/mime.py +11 -14
  9. {uiform → retab}/_utils/responses.py +16 -10
  10. {uiform → retab}/_utils/stream_context_managers.py +1 -1
  11. {uiform → retab}/_utils/usage/usage.py +31 -31
  12. {uiform → retab}/client.py +54 -53
  13. {uiform → retab}/resources/consensus/client.py +19 -38
  14. {uiform → retab}/resources/consensus/completions.py +36 -59
  15. {uiform → retab}/resources/consensus/completions_stream.py +35 -47
  16. {uiform → retab}/resources/consensus/responses.py +37 -86
  17. {uiform → retab}/resources/consensus/responses_stream.py +41 -89
  18. retab/resources/documents/client.py +455 -0
  19. {uiform → retab}/resources/documents/extractions.py +192 -101
  20. {uiform → retab}/resources/evals.py +56 -43
  21. retab/resources/evaluations/__init__.py +3 -0
  22. retab/resources/evaluations/client.py +301 -0
  23. retab/resources/evaluations/documents.py +233 -0
  24. retab/resources/evaluations/iterations.py +452 -0
  25. {uiform → retab}/resources/files.py +2 -2
  26. {uiform → retab}/resources/jsonlUtils.py +225 -221
  27. retab/resources/models.py +73 -0
  28. retab/resources/processors/automations/client.py +244 -0
  29. {uiform → retab}/resources/processors/automations/endpoints.py +79 -120
  30. retab/resources/processors/automations/links.py +294 -0
  31. {uiform → retab}/resources/processors/automations/logs.py +30 -19
  32. retab/resources/processors/automations/mailboxes.py +397 -0
  33. retab/resources/processors/automations/outlook.py +337 -0
  34. {uiform → retab}/resources/processors/automations/tests.py +22 -25
  35. {uiform → retab}/resources/processors/client.py +181 -166
  36. {uiform → retab}/resources/schemas.py +78 -66
  37. {uiform → retab}/resources/secrets/external_api_keys.py +1 -5
  38. retab/resources/secrets/webhook.py +64 -0
  39. {uiform → retab}/resources/usage.py +41 -4
  40. {uiform → retab}/types/ai_models.py +17 -17
  41. {uiform → retab}/types/automations/cron.py +19 -12
  42. {uiform → retab}/types/automations/endpoints.py +7 -4
  43. {uiform → retab}/types/automations/links.py +7 -3
  44. {uiform → retab}/types/automations/mailboxes.py +10 -10
  45. {uiform → retab}/types/automations/outlook.py +15 -11
  46. {uiform → retab}/types/automations/webhooks.py +1 -1
  47. retab/types/browser_canvas.py +3 -0
  48. retab/types/chat.py +8 -0
  49. {uiform → retab}/types/completions.py +12 -15
  50. retab/types/consensus.py +19 -0
  51. {uiform → retab}/types/db/annotations.py +3 -3
  52. {uiform → retab}/types/db/files.py +8 -6
  53. {uiform → retab}/types/documents/create_messages.py +20 -22
  54. {uiform → retab}/types/documents/extractions.py +71 -26
  55. {uiform → retab}/types/evals.py +5 -5
  56. retab/types/evaluations/__init__.py +31 -0
  57. retab/types/evaluations/documents.py +30 -0
  58. retab/types/evaluations/iterations.py +112 -0
  59. retab/types/evaluations/model.py +73 -0
  60. retab/types/events.py +79 -0
  61. {uiform → retab}/types/extractions.py +36 -13
  62. retab/types/inference_settings.py +15 -0
  63. retab/types/jobs/base.py +54 -0
  64. retab/types/jobs/batch_annotation.py +12 -0
  65. {uiform → retab}/types/jobs/evaluation.py +1 -2
  66. {uiform → retab}/types/logs.py +37 -34
  67. retab/types/metrics.py +32 -0
  68. {uiform → retab}/types/mime.py +22 -20
  69. {uiform → retab}/types/modalities.py +10 -10
  70. retab/types/predictions.py +19 -0
  71. {uiform → retab}/types/schemas/enhance.py +4 -2
  72. {uiform → retab}/types/schemas/evaluate.py +7 -4
  73. {uiform → retab}/types/schemas/generate.py +6 -3
  74. {uiform → retab}/types/schemas/layout.py +1 -1
  75. {uiform → retab}/types/schemas/object.py +16 -17
  76. {uiform → retab}/types/schemas/templates.py +1 -3
  77. {uiform → retab}/types/secrets/external_api_keys.py +0 -1
  78. {uiform → retab}/types/standards.py +18 -1
  79. {retab-0.0.36.dist-info → retab-0.0.38.dist-info}/METADATA +78 -77
  80. retab-0.0.38.dist-info/RECORD +107 -0
  81. retab-0.0.38.dist-info/top_level.txt +1 -0
  82. retab-0.0.36.dist-info/RECORD +0 -96
  83. retab-0.0.36.dist-info/top_level.txt +0 -1
  84. uiform/__init__.py +0 -4
  85. uiform/_utils/benchmarking copy.py +0 -588
  86. uiform/resources/documents/client.py +0 -255
  87. uiform/resources/models.py +0 -45
  88. uiform/resources/processors/automations/client.py +0 -78
  89. uiform/resources/processors/automations/links.py +0 -356
  90. uiform/resources/processors/automations/mailboxes.py +0 -435
  91. uiform/resources/processors/automations/outlook.py +0 -444
  92. uiform/resources/secrets/webhook.py +0 -62
  93. uiform/types/chat.py +0 -8
  94. uiform/types/consensus.py +0 -10
  95. uiform/types/events.py +0 -76
  96. uiform/types/jobs/base.py +0 -150
  97. uiform/types/jobs/batch_annotation.py +0 -22
  98. {uiform → retab}/_utils/__init__.py +0 -0
  99. {uiform → retab}/_utils/usage/__init__.py +0 -0
  100. {uiform → retab}/py.typed +0 -0
  101. {uiform → retab}/resources/__init__.py +0 -0
  102. {uiform → retab}/resources/consensus/__init__.py +0 -0
  103. {uiform → retab}/resources/documents/__init__.py +0 -0
  104. {uiform → retab}/resources/finetuning.py +0 -0
  105. {uiform → retab}/resources/openai_example.py +0 -0
  106. {uiform → retab}/resources/processors/__init__.py +0 -0
  107. {uiform → retab}/resources/processors/automations/__init__.py +0 -0
  108. {uiform → retab}/resources/prompt_optimization.py +0 -0
  109. {uiform → retab}/resources/secrets/__init__.py +0 -0
  110. {uiform → retab}/resources/secrets/client.py +0 -0
  111. {uiform → retab}/types/__init__.py +0 -0
  112. {uiform → retab}/types/automations/__init__.py +0 -0
  113. {uiform → retab}/types/db/__init__.py +0 -0
  114. {uiform → retab}/types/documents/__init__.py +0 -0
  115. {uiform → retab}/types/documents/correct_orientation.py +0 -0
  116. {uiform → retab}/types/jobs/__init__.py +0 -0
  117. {uiform → retab}/types/jobs/finetune.py +0 -0
  118. {uiform → retab}/types/jobs/prompt_optimization.py +0 -0
  119. {uiform → retab}/types/jobs/webcrawl.py +0 -0
  120. {uiform → retab}/types/pagination.py +0 -0
  121. {uiform → retab}/types/schemas/__init__.py +0 -0
  122. {uiform → retab}/types/secrets/__init__.py +0 -0
  123. {retab-0.0.36.dist-info → retab-0.0.38.dist-info}/WHEEL +0 -0
@@ -0,0 +1,397 @@
1
+ from io import IOBase
2
+ from pathlib import Path
3
+ from typing import Any, List, Literal, Optional
4
+
5
+ from pydantic import EmailStr, HttpUrl
6
+ from pydantic_core import PydanticUndefined
7
+
8
+ from ...._resource import AsyncAPIResource, SyncAPIResource
9
+ from ...._utils.mime import prepare_mime_document
10
+ from ....types.automations.mailboxes import ListMailboxes, Mailbox, UpdateMailboxRequest
11
+ from ....types.mime import EmailData, MIMEData
12
+ from ....types.standards import PreparedRequest
13
+
14
+
15
+ class MailBoxesMixin:
16
+ mailboxes_base_url: str = "/v1/processors/automations/mailboxes"
17
+
18
+ def prepare_create(
19
+ self,
20
+ email: str,
21
+ name: str,
22
+ processor_id: str,
23
+ webhook_url: str,
24
+ authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
25
+ authorized_emails: list[EmailStr] = PydanticUndefined, # type: ignore[assignment]
26
+ webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
27
+ default_language: str = PydanticUndefined, # type: ignore[assignment]
28
+ need_validation: bool = PydanticUndefined, # type: ignore[assignment]
29
+ ) -> PreparedRequest:
30
+ """Create a new email automation configuration."""
31
+ mailbox = Mailbox(
32
+ name=name,
33
+ processor_id=processor_id,
34
+ default_language=default_language,
35
+ webhook_url=webhook_url,
36
+ webhook_headers=webhook_headers,
37
+ need_validation=need_validation,
38
+ email=email,
39
+ authorized_domains=authorized_domains,
40
+ authorized_emails=authorized_emails,
41
+ )
42
+ return PreparedRequest(method="POST", url=self.mailboxes_base_url, data=mailbox.model_dump(mode="json"))
43
+
44
+ def prepare_list(
45
+ self,
46
+ before: str | None = None,
47
+ after: str | None = None,
48
+ limit: int = 10,
49
+ order: Literal["asc", "desc"] | None = "desc",
50
+ email: Optional[str] = None,
51
+ name: Optional[str] = None,
52
+ webhook_url: Optional[str] = None,
53
+ ) -> PreparedRequest:
54
+ params = {
55
+ "before": before,
56
+ "after": after,
57
+ "limit": limit,
58
+ "order": order,
59
+ "email": email,
60
+ "name": name,
61
+ "webhook_url": webhook_url,
62
+ }
63
+ # Remove None values
64
+ params = {k: v for k, v in params.items() if v is not None}
65
+
66
+ return PreparedRequest(method="GET", url=self.mailboxes_base_url, params=params)
67
+
68
+ def prepare_get(self, email: str) -> PreparedRequest:
69
+ return PreparedRequest(method="GET", url=f"{self.mailboxes_base_url}/{email}")
70
+
71
+ def prepare_get_from_id(self, mailbox_id: str) -> PreparedRequest:
72
+ return PreparedRequest(method="GET", url=f"{self.mailboxes_base_url}/from_id/{mailbox_id}")
73
+
74
+ def prepare_update(
75
+ self,
76
+ email: str,
77
+ name: str = PydanticUndefined, # type: ignore[assignment]
78
+ default_language: str = PydanticUndefined, # type: ignore[assignment]
79
+ webhook_url: str = PydanticUndefined, # type: ignore[assignment]
80
+ webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
81
+ need_validation: bool = PydanticUndefined, # type: ignore[assignment]
82
+ authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
83
+ authorized_emails: list[str] = PydanticUndefined, # type: ignore[assignment]
84
+ ) -> PreparedRequest:
85
+ update_mailbox_request = UpdateMailboxRequest(
86
+ name=name,
87
+ default_language=default_language,
88
+ webhook_url=webhook_url,
89
+ webhook_headers=webhook_headers,
90
+ need_validation=need_validation,
91
+ authorized_domains=authorized_domains,
92
+ authorized_emails=authorized_emails,
93
+ )
94
+ return PreparedRequest(method="PUT", url=f"/v1/processors/automations/mailboxes/{email}", data=update_mailbox_request.model_dump(mode="json"))
95
+
96
+ def prepare_delete(self, email: str) -> PreparedRequest:
97
+ return PreparedRequest(method="DELETE", url=f"/v1/processors/automations/mailboxes/{email}", raise_for_status=True)
98
+
99
+
100
+ class Mailboxes(SyncAPIResource, MailBoxesMixin):
101
+ """Emails API wrapper for managing email automation configurations"""
102
+
103
+ def __init__(self, client: Any) -> None:
104
+ super().__init__(client=client)
105
+ self.tests = TestMailboxes(client=client)
106
+
107
+ def create(
108
+ self,
109
+ email: str,
110
+ name: str,
111
+ webhook_url: str,
112
+ processor_id: str,
113
+ authorized_domains: list[str] = PydanticUndefined, # type: ignore[assignment]
114
+ authorized_emails: list[EmailStr] = PydanticUndefined, # type: ignore[assignment]
115
+ webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
116
+ default_language: str = PydanticUndefined, # type: ignore[assignment]
117
+ need_validation: bool = PydanticUndefined, # type: ignore[assignment]
118
+ ) -> Mailbox:
119
+ """Create a new email automation configuration.
120
+
121
+ Args:
122
+ email: Email address for the mailbox
123
+ name: Name of the mailbox
124
+ webhook_url: Webhook URL to receive processed emails
125
+ processor_id: ID of the processor to use for the mailbox
126
+ authorized_domains: List of authorized domains for the mailbox
127
+ authorized_emails: List of authorized emails for the mailbox
128
+ webhook_headers: Webhook headers to send with processed emails
129
+
130
+ Returns:
131
+ Mailbox: The created mailbox configuration
132
+ """
133
+
134
+ request = self.prepare_create(
135
+ email=email,
136
+ name=name,
137
+ processor_id=processor_id,
138
+ webhook_url=webhook_url,
139
+ authorized_domains=authorized_domains,
140
+ authorized_emails=authorized_emails,
141
+ webhook_headers=webhook_headers,
142
+ default_language=default_language,
143
+ need_validation=need_validation,
144
+ )
145
+ response = self._client._prepared_request(request)
146
+
147
+ print(f"Email automation created. Mailbox available at https://www.retab.dev/dashboard/processors/{response['id']}")
148
+
149
+ return Mailbox.model_validate(response)
150
+
151
+ def list(
152
+ self,
153
+ before: str | None = None,
154
+ after: str | None = None,
155
+ limit: int = 10,
156
+ order: Literal["asc", "desc"] | None = "desc",
157
+ name: Optional[str] = None,
158
+ email: Optional[str] = None,
159
+ webhook_url: Optional[str] = None,
160
+ ) -> ListMailboxes:
161
+ """List all email automation configurations.
162
+
163
+ Args:
164
+ before: Optional cursor for pagination - get results before this log ID
165
+ after: Optional cursor for pagination - get results after this log ID
166
+ limit: Maximum number of logs to return (1-100, default 10)
167
+ order: Sort order by creation time - "asc" or "desc" (default "desc")
168
+ email: Optional email address filter
169
+ webhook_url: Optional webhook URL filter
170
+ schema_id: Optional schema ID filter
171
+ schema_data_id: Optional schema data ID filter
172
+
173
+ Returns:
174
+ ListMailboxes: List of mailbox configurations
175
+ """
176
+ request = self.prepare_list(
177
+ before=before,
178
+ after=after,
179
+ limit=limit,
180
+ order=order,
181
+ email=email,
182
+ name=name,
183
+ webhook_url=webhook_url,
184
+ )
185
+ response = self._client._prepared_request(request)
186
+ return ListMailboxes.model_validate(response)
187
+
188
+ def get(self, email: str) -> Mailbox:
189
+ """Get a specific email automation configuration.
190
+
191
+ Args:
192
+ email: Email address of the mailbox
193
+
194
+ Returns:
195
+ Mailbox: The mailbox configuration
196
+ """
197
+ request = self.prepare_get(email)
198
+ response = self._client._prepared_request(request)
199
+ return Mailbox.model_validate(response)
200
+
201
+ def update(
202
+ self,
203
+ email: str,
204
+ name: str = PydanticUndefined, # type: ignore[assignment]
205
+ default_language: str = PydanticUndefined, # type: ignore[assignment]
206
+ webhook_url: str = PydanticUndefined, # type: ignore[assignment]
207
+ webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
208
+ need_validation: bool = PydanticUndefined, # type: ignore[assignment]
209
+ authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
210
+ authorized_emails: List[str] = PydanticUndefined, # type: ignore[assignment]
211
+ ) -> Mailbox:
212
+ """Update an email automation configuration.
213
+
214
+ Args:
215
+ email: Email address of the mailbox to update
216
+ name: New name
217
+ default_language: New default language
218
+ webhook_url: New webhook configuration
219
+ webhook_headers: New webhook configuration
220
+ need_validation: New webhook configuration
221
+ authorized_domains: New webhook configuration
222
+ authorized_emails: New webhook configuration
223
+
224
+ Returns:
225
+ Mailbox: The updated mailbox configuration
226
+ """
227
+ request = self.prepare_update(
228
+ email=email,
229
+ name=name,
230
+ default_language=default_language,
231
+ webhook_url=webhook_url,
232
+ webhook_headers=webhook_headers,
233
+ need_validation=need_validation,
234
+ authorized_domains=authorized_domains,
235
+ authorized_emails=authorized_emails,
236
+ )
237
+ response = self._client._prepared_request(request)
238
+ return Mailbox.model_validate(response)
239
+
240
+ def delete(self, email: str) -> None:
241
+ """Delete an email automation configuration.
242
+
243
+ Args:
244
+ email: Email address of the mailbox to delete
245
+ """
246
+ request = self.prepare_delete(email)
247
+ self._client._prepared_request(request)
248
+ return None
249
+
250
+
251
+ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
252
+ def __init__(self, client: Any) -> None:
253
+ super().__init__(client=client)
254
+ self.tests = AsyncTestMailboxes(client=client)
255
+
256
+ async def create(
257
+ self,
258
+ email: str,
259
+ name: str,
260
+ webhook_url: str,
261
+ processor_id: str,
262
+ authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
263
+ authorized_emails: List[EmailStr] = PydanticUndefined, # type: ignore[assignment]
264
+ webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
265
+ default_language: str = PydanticUndefined, # type: ignore[assignment]
266
+ need_validation: bool = PydanticUndefined, # type: ignore[assignment]
267
+ ) -> Mailbox:
268
+ request = self.prepare_create(
269
+ email=email,
270
+ name=name,
271
+ processor_id=processor_id,
272
+ webhook_url=webhook_url,
273
+ authorized_domains=authorized_domains,
274
+ authorized_emails=authorized_emails,
275
+ webhook_headers=webhook_headers,
276
+ default_language=default_language,
277
+ need_validation=need_validation,
278
+ )
279
+ response = await self._client._prepared_request(request)
280
+
281
+ print(f"Email automation created. Mailbox available at https://www.retab.dev/dashboard/processors/{response['id']}")
282
+
283
+ return Mailbox.model_validate(response)
284
+
285
+ async def list(
286
+ self,
287
+ before: str | None = None,
288
+ after: str | None = None,
289
+ limit: int = 10,
290
+ order: Literal["asc", "desc"] | None = "desc",
291
+ email: str | None = None,
292
+ name: str | None = None,
293
+ webhook_url: str | None = None,
294
+ ) -> ListMailboxes:
295
+ request = self.prepare_list(before=before, after=after, limit=limit, order=order, email=email, name=name, webhook_url=webhook_url)
296
+ response = await self._client._prepared_request(request)
297
+ return ListMailboxes.model_validate(response)
298
+
299
+ async def get(self, email: str) -> Mailbox:
300
+ request = self.prepare_get(email)
301
+ response = await self._client._prepared_request(request)
302
+ return Mailbox.model_validate(response)
303
+
304
+ async def update(
305
+ self,
306
+ email: str,
307
+ name: str = PydanticUndefined, # type: ignore[assignment]
308
+ default_language: str = PydanticUndefined, # type: ignore[assignment]
309
+ webhook_url: str = PydanticUndefined, # type: ignore[assignment]
310
+ webhook_headers: dict[str, str] = PydanticUndefined, # type: ignore[assignment]
311
+ need_validation: bool = PydanticUndefined, # type: ignore[assignment]
312
+ authorized_domains: List[str] = PydanticUndefined, # type: ignore[assignment]
313
+ authorized_emails: List[str] = PydanticUndefined, # type: ignore[assignment]
314
+ ) -> Mailbox:
315
+ request = self.prepare_update(
316
+ email=email,
317
+ name=name,
318
+ default_language=default_language,
319
+ webhook_url=webhook_url,
320
+ webhook_headers=webhook_headers,
321
+ need_validation=need_validation,
322
+ authorized_domains=authorized_domains,
323
+ authorized_emails=authorized_emails,
324
+ )
325
+ response = await self._client._prepared_request(request)
326
+ return Mailbox.model_validate(response)
327
+
328
+ async def delete(self, email: str) -> None:
329
+ request = self.prepare_delete(email)
330
+ await self._client._prepared_request(request)
331
+ return None
332
+
333
+
334
+ class TestMailboxesMixin:
335
+ def prepare_forward(
336
+ self,
337
+ email: str,
338
+ document: Path | str | IOBase | HttpUrl | MIMEData,
339
+ verbose: bool = True,
340
+ ) -> PreparedRequest:
341
+ mime_document = prepare_mime_document(document)
342
+ return PreparedRequest(method="POST", url=f"/v1/processors/automations/mailboxes/tests/forward/{email}", data={"document": mime_document.model_dump()})
343
+
344
+ def print_forward_verbose(self, email_data: EmailData) -> None:
345
+ print("\nTEST EMAIL FORWARDING RESULTS:")
346
+ print("\n#########################")
347
+ print(f"Email ID: {email_data.id}")
348
+ print(f"Subject: {email_data.subject}")
349
+ print(f"From: {email_data.sender}")
350
+ print(f"To: {', '.join(str(r) for r in email_data.recipients_to)}")
351
+ if email_data.recipients_cc:
352
+ print(f"CC: {', '.join(str(r) for r in email_data.recipients_cc)}")
353
+ print(f"Sent at: {email_data.sent_at}")
354
+ print(f"Attachments: {len(email_data.attachments)}")
355
+ if email_data.body_plain:
356
+ print("\nBody Preview:")
357
+ print(email_data.body_plain[:500] + "..." if len(email_data.body_plain) > 500 else email_data.body_plain)
358
+
359
+
360
+ class TestMailboxes(SyncAPIResource, TestMailboxesMixin):
361
+ def forward(
362
+ self,
363
+ email: str,
364
+ document: Path | str | IOBase | HttpUrl | MIMEData,
365
+ verbose: bool = True,
366
+ ) -> EmailData:
367
+ """Mock endpoint that simulates the complete email forwarding process with sample data.
368
+
369
+ Args:
370
+ email: Email address of the mailbox to mock
371
+
372
+ Returns:
373
+ DocumentExtractResponse: The simulated extraction response
374
+ """
375
+ request = self.prepare_forward(email, document, verbose)
376
+ response = self._client._prepared_request(request)
377
+
378
+ email_data = EmailData.model_validate(response)
379
+
380
+ if verbose:
381
+ self.print_forward_verbose(email_data)
382
+ return email_data
383
+
384
+
385
+ class AsyncTestMailboxes(AsyncAPIResource, TestMailboxesMixin):
386
+ async def forward(
387
+ self,
388
+ email: str,
389
+ document: Path | str | IOBase | HttpUrl | MIMEData,
390
+ verbose: bool = True,
391
+ ) -> EmailData:
392
+ request = self.prepare_forward(email, document, verbose)
393
+ response = await self._client._prepared_request(request)
394
+ email_data = EmailData.model_validate(response)
395
+ if verbose:
396
+ self.print_forward_verbose(email_data)
397
+ return email_data