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.
- retab/__init__.py +4 -0
- {uiform → retab}/_resource.py +5 -5
- {uiform → retab}/_utils/ai_models.py +2 -2
- {uiform → retab}/_utils/benchmarking.py +15 -16
- {uiform → retab}/_utils/chat.py +29 -34
- {uiform → retab}/_utils/display.py +0 -3
- {uiform → retab}/_utils/json_schema.py +9 -14
- {uiform → retab}/_utils/mime.py +11 -14
- {uiform → retab}/_utils/responses.py +16 -10
- {uiform → retab}/_utils/stream_context_managers.py +1 -1
- {uiform → retab}/_utils/usage/usage.py +31 -31
- {uiform → retab}/client.py +54 -53
- {uiform → retab}/resources/consensus/client.py +19 -38
- {uiform → retab}/resources/consensus/completions.py +36 -59
- {uiform → retab}/resources/consensus/completions_stream.py +35 -47
- {uiform → retab}/resources/consensus/responses.py +37 -86
- {uiform → retab}/resources/consensus/responses_stream.py +41 -89
- retab/resources/documents/client.py +455 -0
- {uiform → retab}/resources/documents/extractions.py +192 -101
- {uiform → retab}/resources/evals.py +56 -43
- retab/resources/evaluations/__init__.py +3 -0
- retab/resources/evaluations/client.py +301 -0
- retab/resources/evaluations/documents.py +233 -0
- retab/resources/evaluations/iterations.py +452 -0
- {uiform → retab}/resources/files.py +2 -2
- {uiform → retab}/resources/jsonlUtils.py +225 -221
- retab/resources/models.py +73 -0
- retab/resources/processors/automations/client.py +244 -0
- {uiform → retab}/resources/processors/automations/endpoints.py +79 -120
- retab/resources/processors/automations/links.py +294 -0
- {uiform → retab}/resources/processors/automations/logs.py +30 -19
- retab/resources/processors/automations/mailboxes.py +397 -0
- retab/resources/processors/automations/outlook.py +337 -0
- {uiform → retab}/resources/processors/automations/tests.py +22 -25
- {uiform → retab}/resources/processors/client.py +181 -166
- {uiform → retab}/resources/schemas.py +78 -66
- {uiform → retab}/resources/secrets/external_api_keys.py +1 -5
- retab/resources/secrets/webhook.py +64 -0
- {uiform → retab}/resources/usage.py +41 -4
- {uiform → retab}/types/ai_models.py +17 -17
- {uiform → retab}/types/automations/cron.py +19 -12
- {uiform → retab}/types/automations/endpoints.py +7 -4
- {uiform → retab}/types/automations/links.py +7 -3
- {uiform → retab}/types/automations/mailboxes.py +10 -10
- {uiform → retab}/types/automations/outlook.py +15 -11
- {uiform → retab}/types/automations/webhooks.py +1 -1
- retab/types/browser_canvas.py +3 -0
- retab/types/chat.py +8 -0
- {uiform → retab}/types/completions.py +12 -15
- retab/types/consensus.py +19 -0
- {uiform → retab}/types/db/annotations.py +3 -3
- {uiform → retab}/types/db/files.py +8 -6
- {uiform → retab}/types/documents/create_messages.py +20 -22
- {uiform → retab}/types/documents/extractions.py +71 -26
- {uiform → retab}/types/evals.py +5 -5
- retab/types/evaluations/__init__.py +31 -0
- retab/types/evaluations/documents.py +30 -0
- retab/types/evaluations/iterations.py +112 -0
- retab/types/evaluations/model.py +73 -0
- retab/types/events.py +79 -0
- {uiform → retab}/types/extractions.py +36 -13
- retab/types/inference_settings.py +15 -0
- retab/types/jobs/base.py +54 -0
- retab/types/jobs/batch_annotation.py +12 -0
- {uiform → retab}/types/jobs/evaluation.py +1 -2
- {uiform → retab}/types/logs.py +37 -34
- retab/types/metrics.py +32 -0
- {uiform → retab}/types/mime.py +22 -20
- {uiform → retab}/types/modalities.py +10 -10
- retab/types/predictions.py +19 -0
- {uiform → retab}/types/schemas/enhance.py +4 -2
- {uiform → retab}/types/schemas/evaluate.py +7 -4
- {uiform → retab}/types/schemas/generate.py +6 -3
- {uiform → retab}/types/schemas/layout.py +1 -1
- {uiform → retab}/types/schemas/object.py +16 -17
- {uiform → retab}/types/schemas/templates.py +1 -3
- {uiform → retab}/types/secrets/external_api_keys.py +0 -1
- {uiform → retab}/types/standards.py +18 -1
- {retab-0.0.36.dist-info → retab-0.0.38.dist-info}/METADATA +78 -77
- retab-0.0.38.dist-info/RECORD +107 -0
- retab-0.0.38.dist-info/top_level.txt +1 -0
- retab-0.0.36.dist-info/RECORD +0 -96
- retab-0.0.36.dist-info/top_level.txt +0 -1
- uiform/__init__.py +0 -4
- uiform/_utils/benchmarking copy.py +0 -588
- uiform/resources/documents/client.py +0 -255
- uiform/resources/models.py +0 -45
- uiform/resources/processors/automations/client.py +0 -78
- uiform/resources/processors/automations/links.py +0 -356
- uiform/resources/processors/automations/mailboxes.py +0 -435
- uiform/resources/processors/automations/outlook.py +0 -444
- uiform/resources/secrets/webhook.py +0 -62
- uiform/types/chat.py +0 -8
- uiform/types/consensus.py +0 -10
- uiform/types/events.py +0 -76
- uiform/types/jobs/base.py +0 -150
- uiform/types/jobs/batch_annotation.py +0 -22
- {uiform → retab}/_utils/__init__.py +0 -0
- {uiform → retab}/_utils/usage/__init__.py +0 -0
- {uiform → retab}/py.typed +0 -0
- {uiform → retab}/resources/__init__.py +0 -0
- {uiform → retab}/resources/consensus/__init__.py +0 -0
- {uiform → retab}/resources/documents/__init__.py +0 -0
- {uiform → retab}/resources/finetuning.py +0 -0
- {uiform → retab}/resources/openai_example.py +0 -0
- {uiform → retab}/resources/processors/__init__.py +0 -0
- {uiform → retab}/resources/processors/automations/__init__.py +0 -0
- {uiform → retab}/resources/prompt_optimization.py +0 -0
- {uiform → retab}/resources/secrets/__init__.py +0 -0
- {uiform → retab}/resources/secrets/client.py +0 -0
- {uiform → retab}/types/__init__.py +0 -0
- {uiform → retab}/types/automations/__init__.py +0 -0
- {uiform → retab}/types/db/__init__.py +0 -0
- {uiform → retab}/types/documents/__init__.py +0 -0
- {uiform → retab}/types/documents/correct_orientation.py +0 -0
- {uiform → retab}/types/jobs/__init__.py +0 -0
- {uiform → retab}/types/jobs/finetune.py +0 -0
- {uiform → retab}/types/jobs/prompt_optimization.py +0 -0
- {uiform → retab}/types/jobs/webcrawl.py +0 -0
- {uiform → retab}/types/pagination.py +0 -0
- {uiform → retab}/types/schemas/__init__.py +0 -0
- {uiform → retab}/types/secrets/__init__.py +0 -0
- {retab-0.0.36.dist-info → retab-0.0.38.dist-info}/WHEEL +0 -0
@@ -1,255 +0,0 @@
|
|
1
|
-
from io import IOBase
|
2
|
-
from pathlib import Path
|
3
|
-
from typing import Any, Literal
|
4
|
-
|
5
|
-
import PIL.Image
|
6
|
-
from pydantic import HttpUrl
|
7
|
-
|
8
|
-
from ..._resource import AsyncAPIResource, SyncAPIResource
|
9
|
-
from ..._utils.mime import convert_mime_data_to_pil_image, prepare_mime_document
|
10
|
-
from ...types.documents.create_messages import DocumentCreateMessageRequest, DocumentMessage, DocumentCreateInputRequest
|
11
|
-
from ...types.mime import MIMEData
|
12
|
-
from ...types.modalities import Modality
|
13
|
-
from ...types.standards import PreparedRequest
|
14
|
-
from .extractions import AsyncExtractions, Extractions
|
15
|
-
from ..._utils.json_schema import load_json_schema
|
16
|
-
|
17
|
-
|
18
|
-
class BaseDocumentsMixin:
|
19
|
-
def _prepare_create_messages(
|
20
|
-
self,
|
21
|
-
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
22
|
-
modality: Modality = "native",
|
23
|
-
image_resolution_dpi: int | None = None,
|
24
|
-
browser_canvas: Literal['A3', 'A4', 'A5'] | None = None,
|
25
|
-
idempotency_key: str | None = None,
|
26
|
-
) -> PreparedRequest:
|
27
|
-
mime_document = prepare_mime_document(document)
|
28
|
-
data: dict[str, Any] = {
|
29
|
-
"document": mime_document.model_dump(),
|
30
|
-
"modality": modality,
|
31
|
-
}
|
32
|
-
if image_resolution_dpi:
|
33
|
-
data["image_resolution_dpi"] = image_resolution_dpi
|
34
|
-
if browser_canvas:
|
35
|
-
data["browser_canvas"] = browser_canvas
|
36
|
-
|
37
|
-
loading_request = DocumentCreateMessageRequest.model_validate(data)
|
38
|
-
return PreparedRequest(method="POST", url="/v1/documents/create_messages", data=loading_request.model_dump(), idempotency_key=idempotency_key)
|
39
|
-
|
40
|
-
def _prepare_create_inputs(
|
41
|
-
self,
|
42
|
-
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
43
|
-
json_schema: dict[str, Any] | Path | str,
|
44
|
-
modality: Modality = "native",
|
45
|
-
image_resolution_dpi: int | None = None,
|
46
|
-
browser_canvas: Literal['A3', 'A4', 'A5'] | None = None,
|
47
|
-
idempotency_key: str | None = None,
|
48
|
-
) -> PreparedRequest:
|
49
|
-
mime_document = prepare_mime_document(document)
|
50
|
-
loaded_schema = load_json_schema(json_schema)
|
51
|
-
|
52
|
-
data: dict[str, Any] = {
|
53
|
-
"document": mime_document.model_dump(),
|
54
|
-
"modality": modality,
|
55
|
-
"json_schema": loaded_schema,
|
56
|
-
}
|
57
|
-
if image_resolution_dpi:
|
58
|
-
data["image_resolution_dpi"] = image_resolution_dpi
|
59
|
-
if browser_canvas:
|
60
|
-
data["browser_canvas"] = browser_canvas
|
61
|
-
|
62
|
-
loading_request = DocumentCreateInputRequest.model_validate(data)
|
63
|
-
return PreparedRequest(method="POST", url="/v1/documents/create_inputs", data=loading_request.model_dump(), idempotency_key=idempotency_key)
|
64
|
-
|
65
|
-
def _prepare_correct_image_orientation(self, document: Path | str | IOBase | MIMEData | PIL.Image.Image) -> PreparedRequest:
|
66
|
-
mime_document = prepare_mime_document(document)
|
67
|
-
|
68
|
-
if not mime_document.mime_type.startswith("image/"):
|
69
|
-
raise ValueError("Image is not a valid image")
|
70
|
-
|
71
|
-
return PreparedRequest(
|
72
|
-
method="POST",
|
73
|
-
url="/v1/documents/correct_image_orientation",
|
74
|
-
data={"document": mime_document.model_dump()},
|
75
|
-
)
|
76
|
-
|
77
|
-
|
78
|
-
class Documents(SyncAPIResource, BaseDocumentsMixin):
|
79
|
-
"""Documents API wrapper"""
|
80
|
-
|
81
|
-
def __init__(self, client: Any) -> None:
|
82
|
-
super().__init__(client=client)
|
83
|
-
self.extractions = Extractions(client=client)
|
84
|
-
# self.batch = Batch(client=client)
|
85
|
-
|
86
|
-
def correct_image_orientation(self, document: Path | str | IOBase | MIMEData | PIL.Image.Image) -> PIL.Image.Image:
|
87
|
-
"""Corrects the orientation of an image using the UiForm API.
|
88
|
-
|
89
|
-
This method takes an image in various formats and returns a PIL Image with corrected orientation.
|
90
|
-
Useful for handling images from mobile devices or cameras that may have incorrect EXIF orientation.
|
91
|
-
|
92
|
-
Args:
|
93
|
-
image: The input image to correct. Can be:
|
94
|
-
- A file path (Path or str)
|
95
|
-
- A file-like object (IOBase)
|
96
|
-
- A MIMEData object
|
97
|
-
- A PIL Image object
|
98
|
-
|
99
|
-
Returns:
|
100
|
-
PIL.Image.Image: The orientation-corrected image as a PIL Image object
|
101
|
-
|
102
|
-
Raises:
|
103
|
-
ValueError: If the input is not a valid image
|
104
|
-
UiformAPIError: If the API request fails
|
105
|
-
"""
|
106
|
-
request = self._prepare_correct_image_orientation(document)
|
107
|
-
response = self._client._prepared_request(request)
|
108
|
-
mime_response = MIMEData.model_validate(response['document'])
|
109
|
-
return convert_mime_data_to_pil_image(mime_response)
|
110
|
-
|
111
|
-
def create_messages(
|
112
|
-
self,
|
113
|
-
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
114
|
-
modality: Modality = "native",
|
115
|
-
image_resolution_dpi: int | None = None,
|
116
|
-
browser_canvas: Literal['A3', 'A4', 'A5'] | None = None,
|
117
|
-
idempotency_key: str | None = None,
|
118
|
-
) -> DocumentMessage:
|
119
|
-
"""
|
120
|
-
Create document messages from a file using the UiForm API.
|
121
|
-
|
122
|
-
Args:
|
123
|
-
document: The document to process. Can be a file path (Path or str) or a file-like object.
|
124
|
-
modality: The processing modality to use. Defaults to "native".
|
125
|
-
image_resolution_dpi: Optional image resolution DPI.
|
126
|
-
browser_canvas: Optional browser canvas size.
|
127
|
-
idempotency_key: Optional idempotency key for the request
|
128
|
-
Returns:
|
129
|
-
DocumentMessage: The processed document message containing extracted content.
|
130
|
-
|
131
|
-
Raises:
|
132
|
-
UiformAPIError: If the API request fails.
|
133
|
-
"""
|
134
|
-
request = self._prepare_create_messages(document, modality, image_resolution_dpi, browser_canvas, idempotency_key)
|
135
|
-
response = self._client._prepared_request(request)
|
136
|
-
return DocumentMessage.model_validate(response)
|
137
|
-
|
138
|
-
def create_inputs(
|
139
|
-
self,
|
140
|
-
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
141
|
-
json_schema: dict[str, Any] | Path | str,
|
142
|
-
modality: Modality = "native",
|
143
|
-
image_resolution_dpi: int | None = None,
|
144
|
-
browser_canvas: Literal['A3', 'A4', 'A5'] | None = None,
|
145
|
-
idempotency_key: str | None = None,
|
146
|
-
) -> DocumentMessage:
|
147
|
-
"""
|
148
|
-
Create document inputs (messages with schema) from a file using the UiForm API.
|
149
|
-
|
150
|
-
Args:
|
151
|
-
document: The document to process. Can be a file path (Path or str), file-like object, MIMEData, PIL Image, or URL.
|
152
|
-
json_schema: The JSON schema to use for structuring the document content.
|
153
|
-
modality: The processing modality to use. Defaults to "native".
|
154
|
-
image_resolution_dpi: Optional image resolution DPI.
|
155
|
-
browser_canvas: Optional browser canvas size.
|
156
|
-
idempotency_key: Optional idempotency key for the request
|
157
|
-
Returns:
|
158
|
-
DocumentMessage: The processed document message containing extracted content with schema context.
|
159
|
-
|
160
|
-
Raises:
|
161
|
-
UiformAPIError: If the API request fails.
|
162
|
-
"""
|
163
|
-
request = self._prepare_create_inputs(document, json_schema, modality, image_resolution_dpi, browser_canvas, idempotency_key)
|
164
|
-
response = self._client._prepared_request(request)
|
165
|
-
return DocumentMessage.model_validate(response)
|
166
|
-
|
167
|
-
|
168
|
-
class AsyncDocuments(AsyncAPIResource, BaseDocumentsMixin):
|
169
|
-
"""Documents API wrapper for asynchronous usage."""
|
170
|
-
|
171
|
-
def __init__(self, client: Any) -> None:
|
172
|
-
super().__init__(client=client)
|
173
|
-
self.extractions = AsyncExtractions(client=client)
|
174
|
-
|
175
|
-
async def create_messages(
|
176
|
-
self,
|
177
|
-
document: Path | str | IOBase | MIMEData | PIL.Image.Image,
|
178
|
-
modality: Modality = "native",
|
179
|
-
image_resolution_dpi: int | None = None,
|
180
|
-
browser_canvas: Literal['A3', 'A4', 'A5'] | None = None,
|
181
|
-
idempotency_key: str | None = None,
|
182
|
-
) -> DocumentMessage:
|
183
|
-
"""
|
184
|
-
Create document messages from a file using the UiForm API asynchronously.
|
185
|
-
|
186
|
-
Args:
|
187
|
-
document: The document to process. Can be a file path (Path or str) or a file-like object.
|
188
|
-
modality: The processing modality to use. Defaults to "native".
|
189
|
-
idempotency_key: Idempotency key for request
|
190
|
-
Returns:
|
191
|
-
DocumentMessage: The processed document message containing extracted content.
|
192
|
-
|
193
|
-
Raises:
|
194
|
-
UiformAPIError: If the API request fails.
|
195
|
-
"""
|
196
|
-
request = self._prepare_create_messages(document, modality, image_resolution_dpi, browser_canvas, idempotency_key)
|
197
|
-
assert request.data is not None
|
198
|
-
print(request.data.keys())
|
199
|
-
print(request.data)
|
200
|
-
response = await self._client._prepared_request(request)
|
201
|
-
return DocumentMessage.model_validate(response)
|
202
|
-
|
203
|
-
async def create_inputs(
|
204
|
-
self,
|
205
|
-
document: Path | str | IOBase | MIMEData | PIL.Image.Image | HttpUrl,
|
206
|
-
json_schema: dict[str, Any] | Path | str,
|
207
|
-
modality: Modality = "native",
|
208
|
-
image_resolution_dpi: int | None = None,
|
209
|
-
browser_canvas: Literal['A3', 'A4', 'A5'] | None = None,
|
210
|
-
idempotency_key: str | None = None,
|
211
|
-
) -> DocumentMessage:
|
212
|
-
"""
|
213
|
-
Create document inputs (messages with schema) from a file using the UiForm API asynchronously.
|
214
|
-
|
215
|
-
Args:
|
216
|
-
document: The document to process. Can be a file path (Path or str), file-like object, MIMEData, PIL Image, or URL.
|
217
|
-
json_schema: The JSON schema to use for structuring the document content.
|
218
|
-
modality: The processing modality to use. Defaults to "native".
|
219
|
-
image_resolution_dpi: Optional image resolution DPI.
|
220
|
-
browser_canvas: Optional browser canvas size.
|
221
|
-
idempotency_key: Idempotency key for request
|
222
|
-
Returns:
|
223
|
-
DocumentMessage: The processed document message containing extracted content with schema context.
|
224
|
-
|
225
|
-
Raises:
|
226
|
-
UiformAPIError: If the API request fails.
|
227
|
-
"""
|
228
|
-
request = self._prepare_create_inputs(document, json_schema, modality, image_resolution_dpi, browser_canvas, idempotency_key)
|
229
|
-
response = await self._client._prepared_request(request)
|
230
|
-
return DocumentMessage.model_validate(response)
|
231
|
-
|
232
|
-
async def correct_image_orientation(self, document: Path | str | IOBase | MIMEData | PIL.Image.Image) -> PIL.Image.Image:
|
233
|
-
"""Corrects the orientation of an image using the UiForm API asynchronously.
|
234
|
-
|
235
|
-
This method takes an image in various formats and returns a PIL Image with corrected orientation.
|
236
|
-
Useful for handling images from mobile devices or cameras that may have incorrect EXIF orientation.
|
237
|
-
|
238
|
-
Args:
|
239
|
-
image: The input image to correct. Can be:
|
240
|
-
- A file path (Path or str)
|
241
|
-
- A file-like object (IOBase)
|
242
|
-
- A MIMEData object
|
243
|
-
- A PIL Image object
|
244
|
-
|
245
|
-
Returns:
|
246
|
-
PIL.Image.Image: The orientation-corrected image as a PIL Image object
|
247
|
-
|
248
|
-
Raises:
|
249
|
-
ValueError: If the input is not a valid image
|
250
|
-
UiformAPIError: If the API request fails
|
251
|
-
"""
|
252
|
-
request = self._prepare_correct_image_orientation(document)
|
253
|
-
response = await self._client._prepared_request(request)
|
254
|
-
mime_response = MIMEData.model_validate(response['document'])
|
255
|
-
return convert_mime_data_to_pil_image(mime_response)
|
uiform/resources/models.py
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
from openai.types.model import Model
|
2
|
-
|
3
|
-
from .._resource import AsyncAPIResource, SyncAPIResource
|
4
|
-
from ..types.standards import PreparedRequest
|
5
|
-
|
6
|
-
|
7
|
-
class ModelsMixin:
|
8
|
-
def prepare_list(self) -> PreparedRequest:
|
9
|
-
return PreparedRequest(method="GET", url="/v1/models")
|
10
|
-
|
11
|
-
|
12
|
-
class Models(SyncAPIResource, ModelsMixin):
|
13
|
-
"""Models API wrapper"""
|
14
|
-
|
15
|
-
def list(self) -> list[Model]:
|
16
|
-
"""
|
17
|
-
List all available models.
|
18
|
-
|
19
|
-
Returns:
|
20
|
-
list[str]: List of available models
|
21
|
-
Raises:
|
22
|
-
HTTPException if the request fails
|
23
|
-
"""
|
24
|
-
|
25
|
-
request = self.prepare_list()
|
26
|
-
output = self._client._prepared_request(request)
|
27
|
-
return [Model(**model) for model in output["data"]]
|
28
|
-
|
29
|
-
|
30
|
-
class AsyncModels(AsyncAPIResource, ModelsMixin):
|
31
|
-
"""Models Asyncronous API wrapper"""
|
32
|
-
|
33
|
-
async def list(self) -> list[Model]:
|
34
|
-
"""
|
35
|
-
List all available models.
|
36
|
-
|
37
|
-
Returns:
|
38
|
-
list[str]: List of available models
|
39
|
-
Raises:
|
40
|
-
HTTPException if the request fails
|
41
|
-
"""
|
42
|
-
|
43
|
-
request = self.prepare_list()
|
44
|
-
output = await self._client._prepared_request(request)
|
45
|
-
return [Model(**model) for model in output["data"]]
|
@@ -1,78 +0,0 @@
|
|
1
|
-
import hashlib
|
2
|
-
import hmac
|
3
|
-
import json
|
4
|
-
from typing import Any
|
5
|
-
|
6
|
-
from ...._resource import AsyncAPIResource, SyncAPIResource
|
7
|
-
from .endpoints import AsyncEndpoints, Endpoints
|
8
|
-
from .links import AsyncLinks, Links
|
9
|
-
from .mailboxes import AsyncMailboxes, Mailboxes
|
10
|
-
from .outlook import AsyncOutlooks, Outlooks
|
11
|
-
from .tests import AsyncTests, Tests
|
12
|
-
from .logs import AsyncLogs, Logs
|
13
|
-
|
14
|
-
class SignatureVerificationError(Exception):
|
15
|
-
"""Raised when webhook signature verification fails."""
|
16
|
-
|
17
|
-
pass
|
18
|
-
|
19
|
-
|
20
|
-
class AutomationsMixin:
|
21
|
-
def _verify_event(self, event_body: bytes, event_signature: str, secret: str) -> Any:
|
22
|
-
"""
|
23
|
-
Verify the signature of a webhook event.
|
24
|
-
|
25
|
-
Args:
|
26
|
-
body: The raw request body
|
27
|
-
signature: The signature header
|
28
|
-
secret: The secret key used for signing
|
29
|
-
|
30
|
-
Returns:
|
31
|
-
The parsed event payload
|
32
|
-
|
33
|
-
Raises:
|
34
|
-
SignatureVerificationError: If the signature verification fails
|
35
|
-
"""
|
36
|
-
expected_signature = hmac.new(secret.encode(), event_body, hashlib.sha256).hexdigest()
|
37
|
-
|
38
|
-
if not hmac.compare_digest(event_signature, expected_signature):
|
39
|
-
raise SignatureVerificationError("Invalid signature")
|
40
|
-
|
41
|
-
return json.loads(event_body.decode('utf-8'))
|
42
|
-
|
43
|
-
|
44
|
-
class Automations(SyncAPIResource, AutomationsMixin):
|
45
|
-
"""Automations API wrapper"""
|
46
|
-
|
47
|
-
def __init__(self, client: Any) -> None:
|
48
|
-
super().__init__(client=client)
|
49
|
-
self.mailboxes = Mailboxes(client=client)
|
50
|
-
self.links = Links(client=client)
|
51
|
-
self.outlook = Outlooks(client=client)
|
52
|
-
self.endpoints = Endpoints(client=client)
|
53
|
-
self.tests = Tests(client=client)
|
54
|
-
self.logs = Logs(client=client)
|
55
|
-
def verify_event(self, event_body: bytes, event_signature: str, secret: str) -> Any:
|
56
|
-
"""
|
57
|
-
Verify the signature of a webhook event.
|
58
|
-
"""
|
59
|
-
return self._verify_event(event_body, event_signature, secret)
|
60
|
-
|
61
|
-
|
62
|
-
class AsyncAutomations(AsyncAPIResource, AutomationsMixin):
|
63
|
-
"""Async Automations API wrapper"""
|
64
|
-
|
65
|
-
def __init__(self, client: Any) -> None:
|
66
|
-
super().__init__(client=client)
|
67
|
-
self.mailboxes = AsyncMailboxes(client=client)
|
68
|
-
self.links = AsyncLinks(client=client)
|
69
|
-
self.outlook = AsyncOutlooks(client=client)
|
70
|
-
self.endpoints = AsyncEndpoints(client=client)
|
71
|
-
self.tests = AsyncTests(client=client)
|
72
|
-
self.logs = AsyncLogs(client=client)
|
73
|
-
|
74
|
-
async def verify_event(self, event_body: bytes, event_signature: str, secret: str) -> Any:
|
75
|
-
"""
|
76
|
-
Verify the signature of a webhook event.
|
77
|
-
"""
|
78
|
-
return self._verify_event(event_body, event_signature, secret)
|