retab 0.0.41__py3-none-any.whl → 0.0.42__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.
- retab/client.py +5 -5
- retab/resources/consensus/completions_stream.py +2 -2
- retab/resources/documents/client.py +9 -8
- retab/resources/processors/automations/endpoints.py +8 -4
- retab/resources/processors/automations/links.py +2 -2
- retab/resources/processors/automations/logs.py +2 -2
- retab/resources/processors/automations/mailboxes.py +42 -31
- retab/resources/processors/automations/outlook.py +25 -7
- retab/resources/processors/automations/tests.py +7 -1
- retab/resources/processors/client.py +2 -2
- retab/types/automations/mailboxes.py +1 -1
- retab/types/documents/extractions.py +2 -2
- retab/types/documents/parse.py +3 -1
- retab/types/extractions.py +34 -9
- retab-0.0.42.dist-info/METADATA +119 -0
- {retab-0.0.41.dist-info → retab-0.0.42.dist-info}/RECORD +18 -18
- retab-0.0.41.dist-info/METADATA +0 -418
- {retab-0.0.41.dist-info → retab-0.0.42.dist-info}/WHEEL +0 -0
- {retab-0.0.41.dist-info → retab-0.0.42.dist-info}/top_level.txt +0 -0
retab/client.py
CHANGED
@@ -34,7 +34,7 @@ class BaseRetab:
|
|
34
34
|
|
35
35
|
Args:
|
36
36
|
api_key (str, optional): Retab API key. If not provided, will look for RETAB_API_KEY env variable.
|
37
|
-
base_url (str, optional): Base URL for API requests. Defaults to https://api.retab.
|
37
|
+
base_url (str, optional): Base URL for API requests. Defaults to https://api.retab.com
|
38
38
|
timeout (float): Request timeout in seconds. Defaults to 240.0
|
39
39
|
max_retries (int): Maximum number of retries for failed requests. Defaults to 3
|
40
40
|
openai_api_key (str, optional): OpenAI API key. Will look for OPENAI_API_KEY env variable if not provided
|
@@ -63,12 +63,12 @@ class BaseRetab:
|
|
63
63
|
|
64
64
|
if api_key is None:
|
65
65
|
raise ValueError(
|
66
|
-
"No API key provided. You can create an API key at https://retab.
|
66
|
+
"No API key provided. You can create an API key at https://retab.com\n"
|
67
67
|
"Then either pass it to the client (api_key='your-key') or set the RETAB_API_KEY environment variable"
|
68
68
|
)
|
69
69
|
|
70
70
|
if base_url is None:
|
71
|
-
base_url = os.environ.get("RETAB_API_BASE_URL", "https://api.retab.
|
71
|
+
base_url = os.environ.get("RETAB_API_BASE_URL", "https://api.retab.com")
|
72
72
|
|
73
73
|
truststore.inject_into_ssl()
|
74
74
|
self.api_key = api_key
|
@@ -154,7 +154,7 @@ class Retab(BaseRetab):
|
|
154
154
|
|
155
155
|
Args:
|
156
156
|
api_key (str, optional): Retab API key. If not provided, will look for RETAB_API_KEY env variable.
|
157
|
-
base_url (str, optional): Base URL for API requests. Defaults to https://api.retab.
|
157
|
+
base_url (str, optional): Base URL for API requests. Defaults to https://api.retab.com
|
158
158
|
timeout (float): Request timeout in seconds. Defaults to 240.0
|
159
159
|
max_retries (int): Maximum number of retries for failed requests. Defaults to 3
|
160
160
|
openai_api_key (str, optional): OpenAI API key. Will look for OPENAI_API_KEY env variable if not provided
|
@@ -422,7 +422,7 @@ class AsyncRetab(BaseRetab):
|
|
422
422
|
|
423
423
|
Args:
|
424
424
|
api_key (str, optional): Retab API key. If not provided, will look for RETAB_API_KEY env variable.
|
425
|
-
base_url (str, optional): Base URL for API requests. Defaults to https://api.retab.
|
425
|
+
base_url (str, optional): Base URL for API requests. Defaults to https://api.retab.com
|
426
426
|
timeout (float): Request timeout in seconds. Defaults to 240.0
|
427
427
|
max_retries (int): Maximum number of retries for failed requests. Defaults to 3
|
428
428
|
openai_api_key (str, optional): OpenAI API key. Will look for OPENAI_API_KEY env variable if not provided
|
@@ -123,7 +123,7 @@ class Completions(SyncAPIResource, BaseCompletionsMixin):
|
|
123
123
|
|
124
124
|
Usage:
|
125
125
|
```python
|
126
|
-
with retab.
|
126
|
+
with retab.completions.stream(json_schema, messages, model, temperature, reasoning_effort) as stream:
|
127
127
|
for response in stream:
|
128
128
|
print(response)
|
129
129
|
```
|
@@ -210,7 +210,7 @@ class AsyncCompletions(AsyncAPIResource, BaseCompletionsMixin):
|
|
210
210
|
|
211
211
|
Usage:
|
212
212
|
```python
|
213
|
-
async with retab.
|
213
|
+
async with retab.completions.stream(json_schema, messages, model, temperature, reasoning_effort, n_consensus) as stream:
|
214
214
|
async for response in stream:
|
215
215
|
print(response)
|
216
216
|
```
|
@@ -17,6 +17,7 @@ from ...types.documents.parse import ParseRequest, ParseResult, TableParsingForm
|
|
17
17
|
from ...types.browser_canvas import BrowserCanvas
|
18
18
|
from ...types.mime import MIMEData
|
19
19
|
from ...types.modalities import Modality
|
20
|
+
from ...types.ai_models import LLMModel
|
20
21
|
from ...types.schemas.object import Schema
|
21
22
|
from ...types.standards import PreparedRequest
|
22
23
|
from .extractions import AsyncExtractions, Extractions
|
@@ -89,7 +90,7 @@ class BaseDocumentsMixin:
|
|
89
90
|
def _prepare_parse(
|
90
91
|
self,
|
91
92
|
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
92
|
-
|
93
|
+
model: LLMModel,
|
93
94
|
table_parsing_format: TableParsingFormat = "html",
|
94
95
|
image_resolution_dpi: int = 72,
|
95
96
|
browser_canvas: BrowserCanvas = "A4",
|
@@ -99,7 +100,7 @@ class BaseDocumentsMixin:
|
|
99
100
|
|
100
101
|
parse_request = ParseRequest(
|
101
102
|
document=mime_document,
|
102
|
-
|
103
|
+
model=model,
|
103
104
|
table_parsing_format=table_parsing_format,
|
104
105
|
image_resolution_dpi=image_resolution_dpi,
|
105
106
|
browser_canvas=browser_canvas,
|
@@ -290,7 +291,7 @@ class Documents(SyncAPIResource, BaseDocumentsMixin):
|
|
290
291
|
def parse(
|
291
292
|
self,
|
292
293
|
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
293
|
-
|
294
|
+
model: LLMModel,
|
294
295
|
table_parsing_format: TableParsingFormat = "html",
|
295
296
|
image_resolution_dpi: int = 72,
|
296
297
|
browser_canvas: BrowserCanvas = "A4",
|
@@ -304,7 +305,7 @@ class Documents(SyncAPIResource, BaseDocumentsMixin):
|
|
304
305
|
|
305
306
|
Args:
|
306
307
|
document: The document to parse. Can be a file path (Path or str), file-like object, MIMEData, PIL Image, or URL.
|
307
|
-
|
308
|
+
model: The AI model to use for document parsing.
|
308
309
|
table_parsing_format: Format for parsing tables. Options: "html", "json", "yaml", "markdown". Defaults to "html".
|
309
310
|
image_resolution_dpi: DPI for image processing. Defaults to 72.
|
310
311
|
browser_canvas: Canvas size for document rendering. Defaults to "A4".
|
@@ -318,7 +319,7 @@ class Documents(SyncAPIResource, BaseDocumentsMixin):
|
|
318
319
|
"""
|
319
320
|
request = self._prepare_parse(
|
320
321
|
document=document,
|
321
|
-
|
322
|
+
model=model,
|
322
323
|
table_parsing_format=table_parsing_format,
|
323
324
|
image_resolution_dpi=image_resolution_dpi,
|
324
325
|
browser_canvas=browser_canvas,
|
@@ -512,7 +513,7 @@ class AsyncDocuments(AsyncAPIResource, BaseDocumentsMixin):
|
|
512
513
|
async def parse(
|
513
514
|
self,
|
514
515
|
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
515
|
-
|
516
|
+
model: LLMModel,
|
516
517
|
table_parsing_format: TableParsingFormat = "html",
|
517
518
|
image_resolution_dpi: int = 72,
|
518
519
|
browser_canvas: BrowserCanvas = "A4",
|
@@ -526,7 +527,7 @@ class AsyncDocuments(AsyncAPIResource, BaseDocumentsMixin):
|
|
526
527
|
|
527
528
|
Args:
|
528
529
|
document: The document to parse. Can be a file path (Path or str), file-like object, MIMEData, PIL Image, or URL.
|
529
|
-
|
530
|
+
model: The AI model to use for document parsing.
|
530
531
|
table_parsing_format: Format for parsing tables. Options: "html", "json", "yaml", "markdown". Defaults to "html".
|
531
532
|
image_resolution_dpi: DPI for image processing. Defaults to 72.
|
532
533
|
browser_canvas: Canvas size for document rendering. Defaults to "A4".
|
@@ -540,7 +541,7 @@ class AsyncDocuments(AsyncAPIResource, BaseDocumentsMixin):
|
|
540
541
|
"""
|
541
542
|
request = self._prepare_parse(
|
542
543
|
document=document,
|
543
|
-
|
544
|
+
model=model,
|
544
545
|
table_parsing_format=table_parsing_format,
|
545
546
|
image_resolution_dpi=image_resolution_dpi,
|
546
547
|
browser_canvas=browser_canvas,
|
@@ -31,6 +31,7 @@ class EndpointsMixin:
|
|
31
31
|
|
32
32
|
def prepare_list(
|
33
33
|
self,
|
34
|
+
processor_id: str,
|
34
35
|
before: Optional[str] = None,
|
35
36
|
after: Optional[str] = None,
|
36
37
|
limit: Optional[int] = 10,
|
@@ -40,6 +41,7 @@ class EndpointsMixin:
|
|
40
41
|
webhook_url: Optional[str] = None,
|
41
42
|
) -> PreparedRequest:
|
42
43
|
params = {
|
44
|
+
"processor_id": processor_id,
|
43
45
|
"before": before,
|
44
46
|
"after": after,
|
45
47
|
"limit": limit,
|
@@ -120,11 +122,12 @@ class Endpoints(SyncAPIResource, EndpointsMixin):
|
|
120
122
|
need_validation=need_validation,
|
121
123
|
)
|
122
124
|
response = self._client._prepared_request(request)
|
123
|
-
print(f"Endpoint Created. Url: https://www.retab.
|
125
|
+
print(f"Endpoint Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
124
126
|
return Endpoint.model_validate(response)
|
125
127
|
|
126
128
|
def list(
|
127
129
|
self,
|
130
|
+
processor_id: str,
|
128
131
|
before: Optional[str] = None,
|
129
132
|
after: Optional[str] = None,
|
130
133
|
limit: Optional[int] = 10,
|
@@ -145,7 +148,7 @@ class Endpoints(SyncAPIResource, EndpointsMixin):
|
|
145
148
|
Returns:
|
146
149
|
ListEndpoints: Paginated list of endpoint configurations with metadata
|
147
150
|
"""
|
148
|
-
request = self.prepare_list(before, after, limit, order, name, webhook_url)
|
151
|
+
request = self.prepare_list(processor_id, before, after, limit, order, name, webhook_url)
|
149
152
|
response = self._client._prepared_request(request)
|
150
153
|
return ListEndpoints.model_validate(response)
|
151
154
|
|
@@ -229,12 +232,13 @@ class AsyncEndpoints(AsyncAPIResource, EndpointsMixin):
|
|
229
232
|
need_validation=need_validation,
|
230
233
|
)
|
231
234
|
response = await self._client._prepared_request(request)
|
232
|
-
print(f"Endpoint Created. Url: https://www.retab.
|
235
|
+
print(f"Endpoint Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
233
236
|
|
234
237
|
return Endpoint.model_validate(response)
|
235
238
|
|
236
239
|
async def list(
|
237
240
|
self,
|
241
|
+
processor_id: str,
|
238
242
|
before: Optional[str] = None,
|
239
243
|
after: Optional[str] = None,
|
240
244
|
limit: Optional[int] = 10,
|
@@ -242,7 +246,7 @@ class AsyncEndpoints(AsyncAPIResource, EndpointsMixin):
|
|
242
246
|
name: Optional[str] = None,
|
243
247
|
webhook_url: Optional[str] = None,
|
244
248
|
) -> ListEndpoints:
|
245
|
-
request = self.prepare_list(before, after, limit, order, name, webhook_url)
|
249
|
+
request = self.prepare_list(processor_id, before, after, limit, order, name, webhook_url)
|
246
250
|
response = await self._client._prepared_request(request)
|
247
251
|
return ListEndpoints.model_validate(response)
|
248
252
|
|
@@ -128,7 +128,7 @@ class Links(SyncAPIResource, LinksMixin):
|
|
128
128
|
)
|
129
129
|
response = self._client._prepared_request(request)
|
130
130
|
|
131
|
-
print(f"Link Created. Url: https://www.retab.
|
131
|
+
print(f"Link Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
132
132
|
return Link.model_validate(response)
|
133
133
|
|
134
134
|
def list(
|
@@ -248,7 +248,7 @@ class AsyncLinks(AsyncAPIResource, LinksMixin):
|
|
248
248
|
password=password,
|
249
249
|
)
|
250
250
|
response = await self._client._prepared_request(request)
|
251
|
-
print(f"Link Created. Url: https://www.retab.
|
251
|
+
print(f"Link Created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
252
252
|
return Link.model_validate(response)
|
253
253
|
|
254
254
|
async def list(
|
@@ -147,7 +147,7 @@ class Logs(SyncAPIResource, LogsMixin):
|
|
147
147
|
request = self.prepare_rerun(processor_id, log_id)
|
148
148
|
response = self._client._prepared_request(request)
|
149
149
|
|
150
|
-
print(f"Webhook call run successfully. Log available at https://www.retab.
|
150
|
+
print(f"Webhook call run successfully. Log available at https://www.retab.com/dashboard/processors/{processor_id}/logs/{log_id}")
|
151
151
|
|
152
152
|
return ExternalRequestLog.model_validate(response)
|
153
153
|
|
@@ -217,6 +217,6 @@ class AsyncLogs(AsyncAPIResource, LogsMixin):
|
|
217
217
|
request = self.prepare_rerun(processor_id, log_id)
|
218
218
|
response = await self._client._prepared_request(request)
|
219
219
|
|
220
|
-
print(f"Webhook call run successfully. Log available at https://www.retab.
|
220
|
+
print(f"Webhook call run successfully. Log available at https://www.retab.com/dashboard/processors/{processor_id}/logs/{log_id}")
|
221
221
|
|
222
222
|
return ExternalRequestLog.model_validate(response)
|
@@ -43,6 +43,7 @@ class MailBoxesMixin:
|
|
43
43
|
|
44
44
|
def prepare_list(
|
45
45
|
self,
|
46
|
+
processor_id: str,
|
46
47
|
before: str | None = None,
|
47
48
|
after: str | None = None,
|
48
49
|
limit: int = 10,
|
@@ -52,6 +53,7 @@ class MailBoxesMixin:
|
|
52
53
|
webhook_url: Optional[str] = None,
|
53
54
|
) -> PreparedRequest:
|
54
55
|
params = {
|
56
|
+
"processor_id": processor_id,
|
55
57
|
"before": before,
|
56
58
|
"after": after,
|
57
59
|
"limit": limit,
|
@@ -65,15 +67,12 @@ class MailBoxesMixin:
|
|
65
67
|
|
66
68
|
return PreparedRequest(method="GET", url=self.mailboxes_base_url, params=params)
|
67
69
|
|
68
|
-
def prepare_get(self,
|
69
|
-
return PreparedRequest(method="GET", url=f"{self.mailboxes_base_url}/{
|
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}")
|
70
|
+
def prepare_get(self, mailbox_id: str) -> PreparedRequest:
|
71
|
+
return PreparedRequest(method="GET", url=f"{self.mailboxes_base_url}/{mailbox_id}")
|
73
72
|
|
74
73
|
def prepare_update(
|
75
74
|
self,
|
76
|
-
|
75
|
+
mailbox_id: str,
|
77
76
|
name: str = PydanticUndefined, # type: ignore[assignment]
|
78
77
|
default_language: str = PydanticUndefined, # type: ignore[assignment]
|
79
78
|
webhook_url: str = PydanticUndefined, # type: ignore[assignment]
|
@@ -91,10 +90,10 @@ class MailBoxesMixin:
|
|
91
90
|
authorized_domains=authorized_domains,
|
92
91
|
authorized_emails=authorized_emails,
|
93
92
|
)
|
94
|
-
return PreparedRequest(method="PUT", url=f"/v1/processors/automations/mailboxes/{
|
93
|
+
return PreparedRequest(method="PUT", url=f"/v1/processors/automations/mailboxes/{mailbox_id}", data=update_mailbox_request.model_dump(mode="json"))
|
95
94
|
|
96
|
-
def prepare_delete(self,
|
97
|
-
return PreparedRequest(method="DELETE", url=f"/v1/processors/automations/mailboxes/{
|
95
|
+
def prepare_delete(self, mailbox_id: str) -> PreparedRequest:
|
96
|
+
return PreparedRequest(method="DELETE", url=f"/v1/processors/automations/mailboxes/{mailbox_id}", raise_for_status=True)
|
98
97
|
|
99
98
|
|
100
99
|
class Mailboxes(SyncAPIResource, MailBoxesMixin):
|
@@ -144,12 +143,13 @@ class Mailboxes(SyncAPIResource, MailBoxesMixin):
|
|
144
143
|
)
|
145
144
|
response = self._client._prepared_request(request)
|
146
145
|
|
147
|
-
print(f"Mailbox {response['email']} created. Url: https://www.retab.
|
146
|
+
print(f"Mailbox {response['email']} created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
148
147
|
|
149
148
|
return Mailbox.model_validate(response)
|
150
149
|
|
151
150
|
def list(
|
152
151
|
self,
|
152
|
+
processor_id: str,
|
153
153
|
before: str | None = None,
|
154
154
|
after: str | None = None,
|
155
155
|
limit: int = 10,
|
@@ -174,6 +174,7 @@ class Mailboxes(SyncAPIResource, MailBoxesMixin):
|
|
174
174
|
ListMailboxes: List of mailbox configurations
|
175
175
|
"""
|
176
176
|
request = self.prepare_list(
|
177
|
+
processor_id=processor_id,
|
177
178
|
before=before,
|
178
179
|
after=after,
|
179
180
|
limit=limit,
|
@@ -185,22 +186,22 @@ class Mailboxes(SyncAPIResource, MailBoxesMixin):
|
|
185
186
|
response = self._client._prepared_request(request)
|
186
187
|
return ListMailboxes.model_validate(response)
|
187
188
|
|
188
|
-
def get(self,
|
189
|
+
def get(self, mailbox_id: str) -> Mailbox:
|
189
190
|
"""Get a specific email automation configuration.
|
190
191
|
|
191
192
|
Args:
|
192
|
-
|
193
|
+
mailbox_id: ID of the mailbox
|
193
194
|
|
194
195
|
Returns:
|
195
196
|
Mailbox: The mailbox configuration
|
196
197
|
"""
|
197
|
-
request = self.prepare_get(
|
198
|
+
request = self.prepare_get(mailbox_id)
|
198
199
|
response = self._client._prepared_request(request)
|
199
200
|
return Mailbox.model_validate(response)
|
200
201
|
|
201
202
|
def update(
|
202
203
|
self,
|
203
|
-
|
204
|
+
mailbox_id: str,
|
204
205
|
name: str = PydanticUndefined, # type: ignore[assignment]
|
205
206
|
default_language: str = PydanticUndefined, # type: ignore[assignment]
|
206
207
|
webhook_url: str = PydanticUndefined, # type: ignore[assignment]
|
@@ -225,7 +226,7 @@ class Mailboxes(SyncAPIResource, MailBoxesMixin):
|
|
225
226
|
Mailbox: The updated mailbox configuration
|
226
227
|
"""
|
227
228
|
request = self.prepare_update(
|
228
|
-
|
229
|
+
mailbox_id=mailbox_id,
|
229
230
|
name=name,
|
230
231
|
default_language=default_language,
|
231
232
|
webhook_url=webhook_url,
|
@@ -237,13 +238,13 @@ class Mailboxes(SyncAPIResource, MailBoxesMixin):
|
|
237
238
|
response = self._client._prepared_request(request)
|
238
239
|
return Mailbox.model_validate(response)
|
239
240
|
|
240
|
-
def delete(self,
|
241
|
+
def delete(self, mailbox_id: str) -> None:
|
241
242
|
"""Delete an email automation configuration.
|
242
243
|
|
243
244
|
Args:
|
244
245
|
email: Email address of the mailbox to delete
|
245
246
|
"""
|
246
|
-
request = self.prepare_delete(
|
247
|
+
request = self.prepare_delete(mailbox_id)
|
247
248
|
self._client._prepared_request(request)
|
248
249
|
return None
|
249
250
|
|
@@ -278,12 +279,13 @@ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
|
|
278
279
|
)
|
279
280
|
response = await self._client._prepared_request(request)
|
280
281
|
|
281
|
-
print(f"Mailbox {response['email']} created. Url: https://www.retab.
|
282
|
+
print(f"Mailbox {response['email']} created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
282
283
|
|
283
284
|
return Mailbox.model_validate(response)
|
284
285
|
|
285
286
|
async def list(
|
286
287
|
self,
|
288
|
+
processor_id: str,
|
287
289
|
before: str | None = None,
|
288
290
|
after: str | None = None,
|
289
291
|
limit: int = 10,
|
@@ -292,18 +294,27 @@ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
|
|
292
294
|
name: str | None = None,
|
293
295
|
webhook_url: str | None = None,
|
294
296
|
) -> ListMailboxes:
|
295
|
-
request = self.prepare_list(
|
297
|
+
request = self.prepare_list(
|
298
|
+
processor_id=processor_id,
|
299
|
+
before=before,
|
300
|
+
after=after,
|
301
|
+
limit=limit,
|
302
|
+
order=order,
|
303
|
+
email=email,
|
304
|
+
name=name,
|
305
|
+
webhook_url=webhook_url,
|
306
|
+
)
|
296
307
|
response = await self._client._prepared_request(request)
|
297
308
|
return ListMailboxes.model_validate(response)
|
298
309
|
|
299
|
-
async def get(self,
|
300
|
-
request = self.prepare_get(
|
310
|
+
async def get(self, mailbox_id: str) -> Mailbox:
|
311
|
+
request = self.prepare_get(mailbox_id)
|
301
312
|
response = await self._client._prepared_request(request)
|
302
313
|
return Mailbox.model_validate(response)
|
303
314
|
|
304
315
|
async def update(
|
305
316
|
self,
|
306
|
-
|
317
|
+
mailbox_id: str,
|
307
318
|
name: str = PydanticUndefined, # type: ignore[assignment]
|
308
319
|
default_language: str = PydanticUndefined, # type: ignore[assignment]
|
309
320
|
webhook_url: str = PydanticUndefined, # type: ignore[assignment]
|
@@ -313,7 +324,7 @@ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
|
|
313
324
|
authorized_emails: List[str] = PydanticUndefined, # type: ignore[assignment]
|
314
325
|
) -> Mailbox:
|
315
326
|
request = self.prepare_update(
|
316
|
-
|
327
|
+
mailbox_id=mailbox_id,
|
317
328
|
name=name,
|
318
329
|
default_language=default_language,
|
319
330
|
webhook_url=webhook_url,
|
@@ -325,8 +336,8 @@ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
|
|
325
336
|
response = await self._client._prepared_request(request)
|
326
337
|
return Mailbox.model_validate(response)
|
327
338
|
|
328
|
-
async def delete(self,
|
329
|
-
request = self.prepare_delete(
|
339
|
+
async def delete(self, mailbox_id: str) -> None:
|
340
|
+
request = self.prepare_delete(mailbox_id)
|
330
341
|
await self._client._prepared_request(request)
|
331
342
|
return None
|
332
343
|
|
@@ -334,12 +345,12 @@ class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
|
|
334
345
|
class TestMailboxesMixin:
|
335
346
|
def prepare_forward(
|
336
347
|
self,
|
337
|
-
|
348
|
+
mailbox_id: str,
|
338
349
|
document: Path | str | IOBase | HttpUrl | MIMEData,
|
339
350
|
verbose: bool = True,
|
340
351
|
) -> PreparedRequest:
|
341
352
|
mime_document = prepare_mime_document(document)
|
342
|
-
return PreparedRequest(method="POST", url=f"/v1/processors/automations/mailboxes/tests/forward/{
|
353
|
+
return PreparedRequest(method="POST", url=f"/v1/processors/automations/mailboxes/tests/forward/{mailbox_id}", data={"document": mime_document.model_dump()})
|
343
354
|
|
344
355
|
def print_forward_verbose(self, email_data: EmailData) -> None:
|
345
356
|
print("\nTEST EMAIL FORWARDING RESULTS:")
|
@@ -360,7 +371,7 @@ class TestMailboxesMixin:
|
|
360
371
|
class TestMailboxes(SyncAPIResource, TestMailboxesMixin):
|
361
372
|
def forward(
|
362
373
|
self,
|
363
|
-
|
374
|
+
mailbox_id: str,
|
364
375
|
document: Path | str | IOBase | HttpUrl | MIMEData,
|
365
376
|
verbose: bool = True,
|
366
377
|
) -> EmailData:
|
@@ -372,7 +383,7 @@ class TestMailboxes(SyncAPIResource, TestMailboxesMixin):
|
|
372
383
|
Returns:
|
373
384
|
DocumentExtractResponse: The simulated extraction response
|
374
385
|
"""
|
375
|
-
request = self.prepare_forward(
|
386
|
+
request = self.prepare_forward(mailbox_id, document, verbose)
|
376
387
|
response = self._client._prepared_request(request)
|
377
388
|
|
378
389
|
email_data = EmailData.model_validate(response)
|
@@ -385,11 +396,11 @@ class TestMailboxes(SyncAPIResource, TestMailboxesMixin):
|
|
385
396
|
class AsyncTestMailboxes(AsyncAPIResource, TestMailboxesMixin):
|
386
397
|
async def forward(
|
387
398
|
self,
|
388
|
-
|
399
|
+
mailbox_id: str,
|
389
400
|
document: Path | str | IOBase | HttpUrl | MIMEData,
|
390
401
|
verbose: bool = True,
|
391
402
|
) -> EmailData:
|
392
|
-
request = self.prepare_forward(
|
403
|
+
request = self.prepare_forward(mailbox_id, document, verbose)
|
393
404
|
response = await self._client._prepared_request(request)
|
394
405
|
email_data = EmailData.model_validate(response)
|
395
406
|
if verbose:
|
@@ -3,7 +3,13 @@ from typing import Any, Literal, List
|
|
3
3
|
from pydantic_core import PydanticUndefined
|
4
4
|
|
5
5
|
from ...._resource import AsyncAPIResource, SyncAPIResource
|
6
|
-
from ....types.automations.outlook import
|
6
|
+
from ....types.automations.outlook import (
|
7
|
+
FetchParams,
|
8
|
+
ListOutlooks,
|
9
|
+
MatchParams,
|
10
|
+
Outlook,
|
11
|
+
UpdateOutlookRequest,
|
12
|
+
)
|
7
13
|
from ....types.standards import PreparedRequest
|
8
14
|
|
9
15
|
|
@@ -38,10 +44,15 @@ class OutlooksMixin:
|
|
38
44
|
match_params=match_params,
|
39
45
|
fetch_params=fetch_params,
|
40
46
|
)
|
41
|
-
return PreparedRequest(
|
47
|
+
return PreparedRequest(
|
48
|
+
method="POST",
|
49
|
+
url=self.outlooks_base_url,
|
50
|
+
data=outlook_data.model_dump(mode="json"),
|
51
|
+
)
|
42
52
|
|
43
53
|
def prepare_list(
|
44
54
|
self,
|
55
|
+
processor_id: str,
|
45
56
|
before: str | None = None,
|
46
57
|
after: str | None = None,
|
47
58
|
limit: int = 10,
|
@@ -50,6 +61,7 @@ class OutlooksMixin:
|
|
50
61
|
webhook_url: str | None = None,
|
51
62
|
) -> PreparedRequest:
|
52
63
|
params = {
|
64
|
+
"processor_id": processor_id,
|
53
65
|
"before": before,
|
54
66
|
"after": after,
|
55
67
|
"limit": limit,
|
@@ -92,7 +104,11 @@ class OutlooksMixin:
|
|
92
104
|
fetch_params=fetch_params,
|
93
105
|
)
|
94
106
|
|
95
|
-
return PreparedRequest(
|
107
|
+
return PreparedRequest(
|
108
|
+
method="PUT",
|
109
|
+
url=f"{self.outlooks_base_url}/{outlook_id}",
|
110
|
+
data=update_outlook_request.model_dump(mode="json"),
|
111
|
+
)
|
96
112
|
|
97
113
|
def prepare_delete(self, outlook_id: str) -> PreparedRequest:
|
98
114
|
return PreparedRequest(method="DELETE", url=f"{self.outlooks_base_url}/{outlook_id}")
|
@@ -149,12 +165,13 @@ class Outlooks(SyncAPIResource, OutlooksMixin):
|
|
149
165
|
)
|
150
166
|
response = self._client._prepared_request(request)
|
151
167
|
|
152
|
-
print(f"Outlook plugin created. Url: https://www.retab.
|
168
|
+
print(f"Outlook plugin created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
153
169
|
|
154
170
|
return Outlook.model_validate(response)
|
155
171
|
|
156
172
|
def list(
|
157
173
|
self,
|
174
|
+
processor_id: str,
|
158
175
|
before: str | None = None,
|
159
176
|
after: str | None = None,
|
160
177
|
limit: int = 10,
|
@@ -174,7 +191,7 @@ class Outlooks(SyncAPIResource, OutlooksMixin):
|
|
174
191
|
Returns:
|
175
192
|
List[Outlook]: List of outlook plugin configurations
|
176
193
|
"""
|
177
|
-
request = self.prepare_list(before, after, limit, order, name, webhook_url)
|
194
|
+
request = self.prepare_list(processor_id, before, after, limit, order, name, webhook_url)
|
178
195
|
response = self._client._prepared_request(request)
|
179
196
|
return ListOutlooks.model_validate(response)
|
180
197
|
|
@@ -280,11 +297,12 @@ class AsyncOutlooks(AsyncAPIResource, OutlooksMixin):
|
|
280
297
|
fetch_params=fetch_params,
|
281
298
|
)
|
282
299
|
response = await self._client._prepared_request(request)
|
283
|
-
print(f"Outlook plugin created. Url: https://www.retab.
|
300
|
+
print(f"Outlook plugin created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
284
301
|
return Outlook.model_validate(response)
|
285
302
|
|
286
303
|
async def list(
|
287
304
|
self,
|
305
|
+
processor_id: str,
|
288
306
|
before: str | None = None,
|
289
307
|
after: str | None = None,
|
290
308
|
limit: int = 10,
|
@@ -292,7 +310,7 @@ class AsyncOutlooks(AsyncAPIResource, OutlooksMixin):
|
|
292
310
|
name: str | None = None,
|
293
311
|
webhook_url: str | None = None,
|
294
312
|
) -> ListOutlooks:
|
295
|
-
request = self.prepare_list(before, after, limit, order, name, webhook_url)
|
313
|
+
request = self.prepare_list(processor_id, before, after, limit, order, name, webhook_url)
|
296
314
|
response = await self._client._prepared_request(request)
|
297
315
|
return ListOutlooks.model_validate(response)
|
298
316
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import json
|
2
|
+
import base64
|
2
3
|
from io import IOBase
|
3
4
|
from pathlib import Path
|
4
5
|
|
@@ -15,7 +16,12 @@ from ....types.standards import PreparedRequest
|
|
15
16
|
class TestsMixin:
|
16
17
|
def prepare_upload(self, automation_id: str, document: Path | str | IOBase | HttpUrl | Image | MIMEData) -> PreparedRequest:
|
17
18
|
mime_document = prepare_mime_document(document)
|
18
|
-
|
19
|
+
|
20
|
+
# Convert MIME document to file upload format (similar to processors client)
|
21
|
+
files = {"file": (mime_document.filename, base64.b64decode(mime_document.content), mime_document.mime_type)}
|
22
|
+
|
23
|
+
# Send as multipart form data with file upload
|
24
|
+
return PreparedRequest(method="POST", url=f"/v1/processors/automations/tests/upload/{automation_id}", files=files)
|
19
25
|
|
20
26
|
def prepare_webhook(self, automation_id: str) -> PreparedRequest:
|
21
27
|
return PreparedRequest(method="POST", url=f"/v1/processors/automations/tests/webhook/{automation_id}", data=None)
|
@@ -248,7 +248,7 @@ class Processors(SyncAPIResource, ProcessorsMixin):
|
|
248
248
|
n_consensus=n_consensus,
|
249
249
|
)
|
250
250
|
response = self._client._prepared_request(request)
|
251
|
-
print(f"Processor ID: {response['id']}. Processor available at https://www.retab.
|
251
|
+
print(f"Processor ID: {response['id']}. Processor available at https://www.retab.com/dashboard/processors/{response['id']}")
|
252
252
|
return ProcessorConfig.model_validate(response)
|
253
253
|
|
254
254
|
def list(
|
@@ -408,7 +408,7 @@ class AsyncProcessors(AsyncAPIResource, ProcessorsMixin):
|
|
408
408
|
n_consensus=n_consensus,
|
409
409
|
)
|
410
410
|
response = await self._client._prepared_request(request)
|
411
|
-
print(f"Processor ID: {response['id']}. Processor available at https://www.retab.
|
411
|
+
print(f"Processor ID: {response['id']}. Processor available at https://www.retab.com/dashboard/processors/{response['id']}")
|
412
412
|
|
413
413
|
return ProcessorConfig.model_validate(response)
|
414
414
|
|
@@ -17,7 +17,7 @@ class Mailbox(AutomationConfig):
|
|
17
17
|
def object(self) -> str:
|
18
18
|
return "automation.mailbox"
|
19
19
|
|
20
|
-
EMAIL_PATTERN: ClassVar[str] = f".*@{os.getenv('EMAIL_DOMAIN', 'mailbox.retab.
|
20
|
+
EMAIL_PATTERN: ClassVar[str] = f".*@{os.getenv('EMAIL_DOMAIN', 'mailbox.retab.com')}$"
|
21
21
|
id: str = Field(default_factory=lambda: "mb_" + nanoid.generate(), description="Unique identifier for the mailbox")
|
22
22
|
|
23
23
|
# Email Specific config
|
@@ -91,7 +91,7 @@ class FieldLocation(BaseModel):
|
|
91
91
|
quote: str = Field(..., description="The quote of the field (verbatim from the document)")
|
92
92
|
file_id: str | None = Field(default=None, description="The ID of the file")
|
93
93
|
page: int | None = Field(default=None, description="The page number of the field (1-indexed)")
|
94
|
-
|
94
|
+
bbox_normalized: tuple[float, float, float, float] | None = Field(default=None, description="The normalized bounding box of the field")
|
95
95
|
score: float | None = Field(default=None, description="The score of the field")
|
96
96
|
match_level: Literal["token", "line", "block"] | None = Field(default=None, description="The level of the match (token, line, block)")
|
97
97
|
|
@@ -99,7 +99,7 @@ class FieldLocation(BaseModel):
|
|
99
99
|
class RetabParsedChoice(ParsedChoice):
|
100
100
|
# Adaptable ParsedChoice that allows None for the finish_reason
|
101
101
|
finish_reason: Literal["stop", "length", "tool_calls", "content_filter", "function_call"] | None = None # type: ignore
|
102
|
-
field_locations: dict[str,
|
102
|
+
field_locations: dict[str, FieldLocation] | None = Field(default=None, description="The locations of the fields in the document, if available")
|
103
103
|
key_mapping: dict[str, Optional[str]] | None = Field(default=None, description="Mapping of consensus keys to original model keys")
|
104
104
|
|
105
105
|
|