exa-py 1.15.1__py3-none-any.whl → 1.15.2__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.
Potentially problematic release.
This version of exa-py might be problematic. Click here for more details.
- exa_py/api.py +3 -0
- exa_py/websets/__init__.py +2 -1
- exa_py/websets/async_client.py +153 -0
- exa_py/websets/client.py +140 -7
- exa_py/websets/core/__init__.py +4 -2
- exa_py/websets/core/async_base.py +77 -0
- exa_py/websets/enrichments/__init__.py +2 -2
- exa_py/websets/enrichments/client.py +74 -0
- exa_py/websets/events/__init__.py +2 -2
- exa_py/websets/events/client.py +82 -0
- exa_py/websets/imports/__init__.py +3 -3
- exa_py/websets/imports/client.py +169 -1
- exa_py/websets/items/__init__.py +2 -2
- exa_py/websets/items/client.py +74 -1
- exa_py/websets/monitors/__init__.py +3 -3
- exa_py/websets/monitors/client.py +36 -0
- exa_py/websets/monitors/runs/__init__.py +2 -2
- exa_py/websets/monitors/runs/client.py +18 -0
- exa_py/websets/searches/__init__.py +2 -2
- exa_py/websets/searches/client.py +47 -0
- exa_py/websets/types.py +13 -4
- exa_py/websets/webhooks/__init__.py +2 -2
- exa_py/websets/webhooks/client.py +63 -1
- {exa_py-1.15.1.dist-info → exa_py-1.15.2.dist-info}/METADATA +1 -1
- exa_py-1.15.2.dist-info/RECORD +37 -0
- exa_py-1.15.1.dist-info/RECORD +0 -35
- {exa_py-1.15.1.dist-info → exa_py-1.15.2.dist-info}/WHEEL +0 -0
exa_py/api.py
CHANGED
|
@@ -23,6 +23,7 @@ from typing import (
|
|
|
23
23
|
overload,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
+
from .websets import AsyncWebsetsClient
|
|
26
27
|
import httpx
|
|
27
28
|
import requests
|
|
28
29
|
from openai import OpenAI
|
|
@@ -2413,6 +2414,8 @@ class AsyncExa(Exa):
|
|
|
2413
2414
|
super().__init__(api_key, api_base)
|
|
2414
2415
|
# Override the synchronous ResearchClient with its async counterpart.
|
|
2415
2416
|
self.research = AsyncResearchClient(self)
|
|
2417
|
+
# Override the synchronous WebsetsClient with its async counterpart.
|
|
2418
|
+
self.websets = AsyncWebsetsClient(self)
|
|
2416
2419
|
self._client = None
|
|
2417
2420
|
|
|
2418
2421
|
@property
|
exa_py/websets/__init__.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from .client import WebsetsClient
|
|
1
|
+
from .client import WebsetsClient, AsyncWebsetsClient
|
|
2
2
|
from .imports import ImportsClient
|
|
3
3
|
from .events import EventsClient
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
6
|
"WebsetsClient",
|
|
7
|
+
"AsyncWebsetsClient",
|
|
7
8
|
"ImportsClient",
|
|
8
9
|
"EventsClient",
|
|
9
10
|
]
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import List, Optional, Literal, Dict, Any, Union
|
|
5
|
+
|
|
6
|
+
from .types import (
|
|
7
|
+
Webset,
|
|
8
|
+
ListWebsetsResponse,
|
|
9
|
+
GetWebsetResponse,
|
|
10
|
+
UpdateWebsetRequest,
|
|
11
|
+
WebsetStatus,
|
|
12
|
+
CreateWebsetParameters,
|
|
13
|
+
PreviewWebsetParameters,
|
|
14
|
+
PreviewWebsetResponse,
|
|
15
|
+
)
|
|
16
|
+
from .core.async_base import WebsetsAsyncBaseClient
|
|
17
|
+
from .async_items.client import AsyncWebsetItemsClient
|
|
18
|
+
from .async_searches.client import AsyncWebsetSearchesClient
|
|
19
|
+
from .async_enrichments.client import AsyncWebsetEnrichmentsClient
|
|
20
|
+
from .async_webhooks.client import AsyncWebsetWebhooksClient
|
|
21
|
+
from .async_monitors.client import AsyncMonitorsClient
|
|
22
|
+
from .async_imports.client import AsyncImportsClient
|
|
23
|
+
from .async_events.client import AsyncEventsClient
|
|
24
|
+
|
|
25
|
+
class AsyncWebsetsClient(WebsetsAsyncBaseClient):
|
|
26
|
+
"""Async client for managing Websets."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, client):
|
|
29
|
+
super().__init__(client)
|
|
30
|
+
self.items = AsyncWebsetItemsClient(client)
|
|
31
|
+
self.searches = AsyncWebsetSearchesClient(client)
|
|
32
|
+
self.enrichments = AsyncWebsetEnrichmentsClient(client)
|
|
33
|
+
self.webhooks = AsyncWebsetWebhooksClient(client)
|
|
34
|
+
self.monitors = AsyncMonitorsClient(client)
|
|
35
|
+
self.imports = AsyncImportsClient(client)
|
|
36
|
+
self.events = AsyncEventsClient(client)
|
|
37
|
+
|
|
38
|
+
async def create(self, params: Union[Dict[str, Any], CreateWebsetParameters]) -> Webset:
|
|
39
|
+
"""Create a new Webset.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
params (CreateWebsetParameters): The parameters for creating a webset.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Webset: The created webset.
|
|
46
|
+
"""
|
|
47
|
+
response = await self.request("/v0/websets", data=params)
|
|
48
|
+
return Webset.model_validate(response)
|
|
49
|
+
|
|
50
|
+
async def preview(self, params: Union[Dict[str, Any], PreviewWebsetParameters]) -> PreviewWebsetResponse:
|
|
51
|
+
"""Preview a Webset before creating it.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
params (PreviewWebsetParameters): The parameters for previewing a webset.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
PreviewWebsetResponse: The preview results.
|
|
58
|
+
"""
|
|
59
|
+
response = await self.request("/v0/websets/preview", data=params)
|
|
60
|
+
return PreviewWebsetResponse.model_validate(response)
|
|
61
|
+
|
|
62
|
+
async def get(self, id: str, *, expand: Optional[List[Literal["items"]]] = None) -> GetWebsetResponse:
|
|
63
|
+
"""Get a Webset by ID.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
id (str): The id or externalId of the Webset.
|
|
67
|
+
expand (List[Literal["items"]], optional): Expand items in the response.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
GetWebsetResponse: The retrieved webset.
|
|
71
|
+
"""
|
|
72
|
+
params = {}
|
|
73
|
+
if expand is not None:
|
|
74
|
+
params["expand"] = expand
|
|
75
|
+
|
|
76
|
+
response = await self.request(f"/v0/websets/{id}", params=params, method="GET")
|
|
77
|
+
return GetWebsetResponse.model_validate(response)
|
|
78
|
+
|
|
79
|
+
async def list(self, *, cursor: Optional[str] = None, limit: Optional[int] = None) -> ListWebsetsResponse:
|
|
80
|
+
"""List all Websets.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
cursor (str, optional): The cursor to paginate through the results.
|
|
84
|
+
limit (int, optional): The number of results to return (max 200).
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
ListWebsetsResponse: List of websets.
|
|
88
|
+
"""
|
|
89
|
+
params = {k: v for k, v in {"cursor": cursor, "limit": limit}.items() if v is not None}
|
|
90
|
+
response = await self.request("/v0/websets", params=params, method="GET")
|
|
91
|
+
return ListWebsetsResponse.model_validate(response)
|
|
92
|
+
|
|
93
|
+
async def update(self, id: str, params: Union[Dict[str, Any], UpdateWebsetRequest]) -> Webset:
|
|
94
|
+
"""Update a Webset.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
id (str): The id or externalId of the Webset.
|
|
98
|
+
params (UpdateWebsetRequest): The parameters for updating a webset.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Webset: The updated webset.
|
|
102
|
+
"""
|
|
103
|
+
response = await self.request(f"/v0/websets/{id}", data=params, method="POST")
|
|
104
|
+
return Webset.model_validate(response)
|
|
105
|
+
|
|
106
|
+
async def delete(self, id: str) -> Webset:
|
|
107
|
+
"""Delete a Webset.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
id (str): The id or externalId of the Webset.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Webset: The deleted webset.
|
|
114
|
+
"""
|
|
115
|
+
response = await self.request(f"/v0/websets/{id}", method="DELETE")
|
|
116
|
+
return Webset.model_validate(response)
|
|
117
|
+
|
|
118
|
+
async def cancel(self, id: str) -> Webset:
|
|
119
|
+
"""Cancel a running Webset.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
id (str): The id or externalId of the Webset.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Webset: The canceled webset.
|
|
126
|
+
"""
|
|
127
|
+
response = await self.request(f"/v0/websets/{id}/cancel", method="POST")
|
|
128
|
+
return Webset.model_validate(response)
|
|
129
|
+
|
|
130
|
+
async def wait_until_idle(self, id: str, *, timeout: int = 3600, poll_interval: int = 5) -> Webset:
|
|
131
|
+
"""Wait until a Webset is idle.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
id (str): The id or externalId of the Webset.
|
|
135
|
+
timeout (int, optional): Maximum time to wait in seconds. Defaults to 3600.
|
|
136
|
+
poll_interval (int, optional): Time to wait between polls in seconds. Defaults to 5.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Webset: The webset once it's idle.
|
|
140
|
+
|
|
141
|
+
Raises:
|
|
142
|
+
TimeoutError: If the webset does not become idle within the timeout period.
|
|
143
|
+
"""
|
|
144
|
+
start_time = asyncio.get_event_loop().time()
|
|
145
|
+
while True:
|
|
146
|
+
webset = await self.get(id)
|
|
147
|
+
if webset.status == WebsetStatus.idle.value:
|
|
148
|
+
return webset
|
|
149
|
+
|
|
150
|
+
if asyncio.get_event_loop().time() - start_time > timeout:
|
|
151
|
+
raise TimeoutError(f"Webset {id} did not become idle within {timeout} seconds")
|
|
152
|
+
|
|
153
|
+
await asyncio.sleep(poll_interval)
|
exa_py/websets/client.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
|
+
import asyncio
|
|
4
5
|
from typing import List, Optional, Literal, Dict, Any, Union
|
|
5
6
|
|
|
6
7
|
from .types import (
|
|
@@ -14,13 +15,14 @@ from .types import (
|
|
|
14
15
|
PreviewWebsetResponse,
|
|
15
16
|
)
|
|
16
17
|
from .core.base import WebsetsBaseClient
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
20
|
-
from .
|
|
21
|
-
from .
|
|
22
|
-
from .
|
|
23
|
-
from .
|
|
18
|
+
from .core.async_base import WebsetsAsyncBaseClient
|
|
19
|
+
from .items import WebsetItemsClient, AsyncWebsetItemsClient
|
|
20
|
+
from .searches import WebsetSearchesClient, AsyncWebsetSearchesClient
|
|
21
|
+
from .enrichments import WebsetEnrichmentsClient, AsyncWebsetEnrichmentsClient
|
|
22
|
+
from .webhooks import WebsetWebhooksClient, AsyncWebsetWebhooksClient
|
|
23
|
+
from .monitors import MonitorsClient, AsyncMonitorsClient
|
|
24
|
+
from .imports import ImportsClient, AsyncImportsClient
|
|
25
|
+
from .events import EventsClient, AsyncEventsClient
|
|
24
26
|
|
|
25
27
|
class WebsetsClient(WebsetsBaseClient):
|
|
26
28
|
"""Client for managing Websets."""
|
|
@@ -154,3 +156,134 @@ class WebsetsClient(WebsetsBaseClient):
|
|
|
154
156
|
raise TimeoutError(f"Webset {id} did not become idle within {timeout} seconds")
|
|
155
157
|
|
|
156
158
|
time.sleep(poll_interval)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class AsyncWebsetsClient(WebsetsAsyncBaseClient):
|
|
162
|
+
"""Async client for managing Websets."""
|
|
163
|
+
|
|
164
|
+
def __init__(self, client):
|
|
165
|
+
super().__init__(client)
|
|
166
|
+
self.items = AsyncWebsetItemsClient(client)
|
|
167
|
+
self.searches = AsyncWebsetSearchesClient(client)
|
|
168
|
+
self.enrichments = AsyncWebsetEnrichmentsClient(client)
|
|
169
|
+
self.webhooks = AsyncWebsetWebhooksClient(client)
|
|
170
|
+
self.monitors = AsyncMonitorsClient(client)
|
|
171
|
+
self.imports = AsyncImportsClient(client)
|
|
172
|
+
self.events = AsyncEventsClient(client)
|
|
173
|
+
|
|
174
|
+
async def create(self, params: Union[Dict[str, Any], CreateWebsetParameters]) -> Webset:
|
|
175
|
+
"""Create a new Webset.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
params (CreateWebsetParameters): The parameters for creating a webset.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Webset: The created webset.
|
|
182
|
+
"""
|
|
183
|
+
response = await self.request("/v0/websets", data=params)
|
|
184
|
+
return Webset.model_validate(response)
|
|
185
|
+
|
|
186
|
+
async def preview(self, params: Union[Dict[str, Any], PreviewWebsetParameters]) -> PreviewWebsetResponse:
|
|
187
|
+
"""Preview a Webset before creating it.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
params (PreviewWebsetParameters): The parameters for previewing a webset.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
PreviewWebsetResponse: The preview results.
|
|
194
|
+
"""
|
|
195
|
+
response = await self.request("/v0/websets/preview", data=params)
|
|
196
|
+
return PreviewWebsetResponse.model_validate(response)
|
|
197
|
+
|
|
198
|
+
async def get(self, id: str, *, expand: Optional[List[Literal["items"]]] = None) -> GetWebsetResponse:
|
|
199
|
+
"""Get a Webset by ID.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
id (str): The id or externalId of the Webset.
|
|
203
|
+
expand (List[Literal["items"]], optional): Expand items in the response.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
GetWebsetResponse: The retrieved webset.
|
|
207
|
+
"""
|
|
208
|
+
params = {}
|
|
209
|
+
if expand is not None:
|
|
210
|
+
params["expand"] = expand
|
|
211
|
+
|
|
212
|
+
response = await self.request(f"/v0/websets/{id}", params=params, method="GET")
|
|
213
|
+
return GetWebsetResponse.model_validate(response)
|
|
214
|
+
|
|
215
|
+
async def list(self, *, cursor: Optional[str] = None, limit: Optional[int] = None) -> ListWebsetsResponse:
|
|
216
|
+
"""List all Websets.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
cursor (str, optional): The cursor to paginate through the results.
|
|
220
|
+
limit (int, optional): The number of results to return (max 200).
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
ListWebsetsResponse: List of websets.
|
|
224
|
+
"""
|
|
225
|
+
params = {k: v for k, v in {"cursor": cursor, "limit": limit}.items() if v is not None}
|
|
226
|
+
response = await self.request("/v0/websets", params=params, method="GET")
|
|
227
|
+
return ListWebsetsResponse.model_validate(response)
|
|
228
|
+
|
|
229
|
+
async def update(self, id: str, params: Union[Dict[str, Any], UpdateWebsetRequest]) -> Webset:
|
|
230
|
+
"""Update a Webset.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
id (str): The id or externalId of the Webset.
|
|
234
|
+
params (UpdateWebsetRequest): The parameters for updating a webset.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Webset: The updated webset.
|
|
238
|
+
"""
|
|
239
|
+
response = await self.request(f"/v0/websets/{id}", data=params, method="POST")
|
|
240
|
+
return Webset.model_validate(response)
|
|
241
|
+
|
|
242
|
+
async def delete(self, id: str) -> Webset:
|
|
243
|
+
"""Delete a Webset.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
id (str): The id or externalId of the Webset.
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
Webset: The deleted webset.
|
|
250
|
+
"""
|
|
251
|
+
response = await self.request(f"/v0/websets/{id}", method="DELETE")
|
|
252
|
+
return Webset.model_validate(response)
|
|
253
|
+
|
|
254
|
+
async def cancel(self, id: str) -> Webset:
|
|
255
|
+
"""Cancel a running Webset.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
id (str): The id or externalId of the Webset.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
Webset: The canceled webset.
|
|
262
|
+
"""
|
|
263
|
+
response = await self.request(f"/v0/websets/{id}/cancel", method="POST")
|
|
264
|
+
return Webset.model_validate(response)
|
|
265
|
+
|
|
266
|
+
async def wait_until_idle(self, id: str, *, timeout: int = 3600, poll_interval: int = 5) -> Webset:
|
|
267
|
+
"""Wait until a Webset is idle.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
id (str): The id or externalId of the Webset.
|
|
271
|
+
timeout (int, optional): Maximum time to wait in seconds. Defaults to 3600.
|
|
272
|
+
poll_interval (int, optional): Time to wait between polls in seconds. Defaults to 5.
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
Webset: The webset once it's idle.
|
|
276
|
+
|
|
277
|
+
Raises:
|
|
278
|
+
TimeoutError: If the webset does not become idle within the timeout period.
|
|
279
|
+
"""
|
|
280
|
+
start_time = asyncio.get_event_loop().time()
|
|
281
|
+
while True:
|
|
282
|
+
webset = await self.get(id)
|
|
283
|
+
if webset.status == WebsetStatus.idle.value:
|
|
284
|
+
return webset
|
|
285
|
+
|
|
286
|
+
if asyncio.get_event_loop().time() - start_time > timeout:
|
|
287
|
+
raise TimeoutError(f"Webset {id} did not become idle within {timeout} seconds")
|
|
288
|
+
|
|
289
|
+
await asyncio.sleep(poll_interval)
|
exa_py/websets/core/__init__.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from ..types import *
|
|
2
|
+
from .base import WebsetsBaseClient
|
|
3
|
+
from .async_base import WebsetsAsyncBaseClient
|
|
2
4
|
import sys
|
|
3
5
|
|
|
4
6
|
# Get all public names from model module that don't start with underscore
|
|
5
7
|
model_module = sys.modules[__name__]
|
|
6
|
-
__all__ = ['WebsetsBaseClient', 'ExaBaseModel'] + [
|
|
8
|
+
__all__ = ['WebsetsBaseClient', 'WebsetsAsyncBaseClient', 'ExaBaseModel'] + [
|
|
7
9
|
name for name in dir(model_module)
|
|
8
|
-
if not name.startswith('_') and name not in ('WebsetsBaseClient', 'ExaBaseModel')
|
|
10
|
+
if not name.startswith('_') and name not in ('WebsetsBaseClient', 'WebsetsAsyncBaseClient', 'ExaBaseModel')
|
|
9
11
|
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import asyncio
|
|
5
|
+
from typing import Any, Dict, Optional, Type, TypeVar, Union
|
|
6
|
+
|
|
7
|
+
from .base import ExaBaseModel
|
|
8
|
+
|
|
9
|
+
# Generic type for any ExaBaseModel
|
|
10
|
+
ModelT = TypeVar('ModelT', bound=ExaBaseModel)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WebsetsAsyncBaseClient:
|
|
15
|
+
base_url: str
|
|
16
|
+
|
|
17
|
+
"""Base async client for Exa API resources."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, client):
|
|
20
|
+
"""Initialize the async client.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
client: The parent AsyncExa client.
|
|
24
|
+
"""
|
|
25
|
+
self._client = client
|
|
26
|
+
|
|
27
|
+
def _prepare_data(self, data: Union[Dict[str, Any], ExaBaseModel, str], model_class: Optional[Type[ModelT]] = None) -> Union[Dict[str, Any], str]:
|
|
28
|
+
"""Prepare data for API request, converting dict to model if needed.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
data: Either a dictionary, model instance, or string
|
|
32
|
+
model_class: The model class to use if data is a dictionary
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Dictionary prepared for API request or string if string data was provided
|
|
36
|
+
"""
|
|
37
|
+
if isinstance(data, str):
|
|
38
|
+
# Return string as is
|
|
39
|
+
return data
|
|
40
|
+
elif isinstance(data, dict) and model_class:
|
|
41
|
+
# Convert dict to model instance
|
|
42
|
+
model_instance = model_class.model_validate(data)
|
|
43
|
+
return model_instance.model_dump(mode='json', by_alias=True, exclude_none=True)
|
|
44
|
+
elif isinstance(data, ExaBaseModel):
|
|
45
|
+
# Use model's dump method
|
|
46
|
+
return data.model_dump(mode='json', by_alias=True, exclude_none=True)
|
|
47
|
+
elif isinstance(data, dict):
|
|
48
|
+
# Use dict directly
|
|
49
|
+
return data
|
|
50
|
+
else:
|
|
51
|
+
raise TypeError(f"Expected dict, ExaBaseModel, or str, got {type(data)}")
|
|
52
|
+
|
|
53
|
+
async def request(self, endpoint: str, data: Optional[Union[Dict[str, Any], ExaBaseModel, str]] = None,
|
|
54
|
+
method: str = "POST", params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
55
|
+
"""Make an async request to the Exa API.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
endpoint (str): The API endpoint to request.
|
|
59
|
+
data (Union[Dict[str, Any], ExaBaseModel, str], optional): The request data. Can be a dictionary, model instance, or string. Defaults to None.
|
|
60
|
+
method (str, optional): The HTTP method. Defaults to "POST".
|
|
61
|
+
params (Dict[str, Any], optional): The query parameters. Defaults to None.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Dict[str, Any]: The API response.
|
|
65
|
+
"""
|
|
66
|
+
if isinstance(data, str):
|
|
67
|
+
# If data is a string, pass it as is
|
|
68
|
+
pass
|
|
69
|
+
elif data is not None and isinstance(data, ExaBaseModel):
|
|
70
|
+
# If data is a model instance, convert it to a dict
|
|
71
|
+
data = data.model_dump(mode='json', by_alias=True, exclude_none=True)
|
|
72
|
+
|
|
73
|
+
# Ensure proper URL construction by removing leading slash from endpoint if present
|
|
74
|
+
if endpoint.startswith("/"):
|
|
75
|
+
endpoint = endpoint[1:]
|
|
76
|
+
|
|
77
|
+
return await self._client.async_request("/websets/" + endpoint, data=data, method=method, params=params)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .client import WebsetEnrichmentsClient
|
|
1
|
+
from .client import WebsetEnrichmentsClient, AsyncWebsetEnrichmentsClient
|
|
2
2
|
|
|
3
|
-
__all__ = ["WebsetEnrichmentsClient"]
|
|
3
|
+
__all__ = ["WebsetEnrichmentsClient", "AsyncWebsetEnrichmentsClient"]
|
|
@@ -8,6 +8,7 @@ from ..types import (
|
|
|
8
8
|
WebsetEnrichment,
|
|
9
9
|
)
|
|
10
10
|
from ..core.base import WebsetsBaseClient
|
|
11
|
+
from ..core.async_base import WebsetsAsyncBaseClient
|
|
11
12
|
|
|
12
13
|
class WebsetEnrichmentsClient(WebsetsBaseClient):
|
|
13
14
|
"""Client for managing Webset Enrichments."""
|
|
@@ -79,4 +80,77 @@ class WebsetEnrichmentsClient(WebsetsBaseClient):
|
|
|
79
80
|
WebsetEnrichment: The canceled enrichment.
|
|
80
81
|
"""
|
|
81
82
|
response = self.request(f"/v0/websets/{webset_id}/enrichments/{id}/cancel", method="POST")
|
|
83
|
+
return WebsetEnrichment.model_validate(response)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class AsyncWebsetEnrichmentsClient(WebsetsAsyncBaseClient):
|
|
87
|
+
"""Async client for managing Webset Enrichments."""
|
|
88
|
+
|
|
89
|
+
def __init__(self, client):
|
|
90
|
+
super().__init__(client)
|
|
91
|
+
|
|
92
|
+
async def create(self, webset_id: str, params: Union[Dict[str, Any], CreateEnrichmentParameters]) -> WebsetEnrichment:
|
|
93
|
+
"""Create an Enrichment for a Webset.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
webset_id (str): The id of the Webset.
|
|
97
|
+
params (CreateEnrichmentParameters): The parameters for creating an enrichment.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
WebsetEnrichment: The created enrichment.
|
|
101
|
+
"""
|
|
102
|
+
response = await self.request(f"/v0/websets/{webset_id}/enrichments", data=params)
|
|
103
|
+
return WebsetEnrichment.model_validate(response)
|
|
104
|
+
|
|
105
|
+
async def get(self, webset_id: str, id: str) -> WebsetEnrichment:
|
|
106
|
+
"""Get an Enrichment by ID.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
webset_id (str): The id of the Webset.
|
|
110
|
+
id (str): The id of the Enrichment.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
WebsetEnrichment: The retrieved enrichment.
|
|
114
|
+
"""
|
|
115
|
+
response = await self.request(f"/v0/websets/{webset_id}/enrichments/{id}", method="GET")
|
|
116
|
+
return WebsetEnrichment.model_validate(response)
|
|
117
|
+
|
|
118
|
+
async def update(self, webset_id: str, id: str, params: Union[Dict[str, Any], UpdateEnrichmentParameters]) -> WebsetEnrichment:
|
|
119
|
+
"""Update an Enrichment.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
webset_id (str): The id of the Webset.
|
|
123
|
+
id (str): The id of the Enrichment.
|
|
124
|
+
params (UpdateEnrichmentParameters): The parameters for updating an enrichment.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
WebsetEnrichment: The updated enrichment.
|
|
128
|
+
"""
|
|
129
|
+
response = await self.request(f"/v0/websets/{webset_id}/enrichments/{id}", data=params, method="PATCH")
|
|
130
|
+
return WebsetEnrichment.model_validate(response)
|
|
131
|
+
|
|
132
|
+
async def delete(self, webset_id: str, id: str) -> WebsetEnrichment:
|
|
133
|
+
"""Delete an Enrichment.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
webset_id (str): The id of the Webset.
|
|
137
|
+
id (str): The id of the Enrichment.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
WebsetEnrichment: The deleted enrichment.
|
|
141
|
+
"""
|
|
142
|
+
response = await self.request(f"/v0/websets/{webset_id}/enrichments/{id}", method="DELETE")
|
|
143
|
+
return WebsetEnrichment.model_validate(response)
|
|
144
|
+
|
|
145
|
+
async def cancel(self, webset_id: str, id: str) -> WebsetEnrichment:
|
|
146
|
+
"""Cancel a running Enrichment.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
webset_id (str): The id of the Webset.
|
|
150
|
+
id (str): The id of the Enrichment.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
WebsetEnrichment: The canceled enrichment.
|
|
154
|
+
"""
|
|
155
|
+
response = await self.request(f"/v0/websets/{webset_id}/enrichments/{id}/cancel", method="POST")
|
|
82
156
|
return WebsetEnrichment.model_validate(response)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .client import EventsClient
|
|
1
|
+
from .client import EventsClient, AsyncEventsClient
|
|
2
2
|
|
|
3
|
-
__all__ = ["EventsClient"]
|
|
3
|
+
__all__ = ["EventsClient", "AsyncEventsClient"]
|
exa_py/websets/events/client.py
CHANGED
|
@@ -24,6 +24,7 @@ from ..types import (
|
|
|
24
24
|
MonitorRunCompletedEvent,
|
|
25
25
|
)
|
|
26
26
|
from ..core.base import WebsetsBaseClient
|
|
27
|
+
from ..core.async_base import WebsetsAsyncBaseClient
|
|
27
28
|
|
|
28
29
|
# Type alias for all event types
|
|
29
30
|
Event = Union[
|
|
@@ -112,6 +113,87 @@ class EventsClient(WebsetsBaseClient):
|
|
|
112
113
|
'monitor.run.completed': MonitorRunCompletedEvent,
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
event_class = event_type_map.get(event_type)
|
|
117
|
+
if event_class:
|
|
118
|
+
return event_class.model_validate(response)
|
|
119
|
+
else:
|
|
120
|
+
# Fallback - try each type until one validates
|
|
121
|
+
# This shouldn't happen in normal operation
|
|
122
|
+
for event_class in event_type_map.values():
|
|
123
|
+
try:
|
|
124
|
+
return event_class.model_validate(response)
|
|
125
|
+
except Exception:
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
raise ValueError(f"Unknown event type: {event_type}")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class AsyncEventsClient(WebsetsAsyncBaseClient):
|
|
132
|
+
"""Async client for managing Events."""
|
|
133
|
+
|
|
134
|
+
def __init__(self, client):
|
|
135
|
+
super().__init__(client)
|
|
136
|
+
|
|
137
|
+
async def list(self, *, cursor: Optional[str] = None, limit: Optional[int] = None,
|
|
138
|
+
types: Optional[List[EventType]] = None) -> ListEventsResponse:
|
|
139
|
+
"""List all Events.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
cursor (str, optional): The cursor to paginate through the results.
|
|
143
|
+
limit (int, optional): The number of results to return.
|
|
144
|
+
types (List[EventType], optional): The types of events to filter by.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
ListEventsResponse: List of events.
|
|
148
|
+
"""
|
|
149
|
+
params = {}
|
|
150
|
+
if cursor is not None:
|
|
151
|
+
params["cursor"] = cursor
|
|
152
|
+
if limit is not None:
|
|
153
|
+
params["limit"] = limit
|
|
154
|
+
if types is not None:
|
|
155
|
+
# Convert EventType enums to their string values
|
|
156
|
+
params["types"] = [t.value if hasattr(t, 'value') else t for t in types]
|
|
157
|
+
|
|
158
|
+
response = await self.request("/v0/events", params=params, method="GET")
|
|
159
|
+
return ListEventsResponse.model_validate(response)
|
|
160
|
+
|
|
161
|
+
async def get(self, id: str) -> Event:
|
|
162
|
+
"""Get an Event by ID.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
id (str): The ID of the Event.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Event: The retrieved event.
|
|
169
|
+
"""
|
|
170
|
+
response = await self.request(f"/v0/events/{id}", method="GET")
|
|
171
|
+
|
|
172
|
+
# The response should contain a 'type' field that helps us determine
|
|
173
|
+
# which specific event class to use for validation
|
|
174
|
+
event_type = response.get('type')
|
|
175
|
+
|
|
176
|
+
# Map event types to their corresponding classes
|
|
177
|
+
event_type_map = {
|
|
178
|
+
'webset.created': WebsetCreatedEvent,
|
|
179
|
+
'webset.deleted': WebsetDeletedEvent,
|
|
180
|
+
'webset.idle': WebsetIdleEvent,
|
|
181
|
+
'webset.paused': WebsetPausedEvent,
|
|
182
|
+
'webset.item.created': WebsetItemCreatedEvent,
|
|
183
|
+
'webset.item.enriched': WebsetItemEnrichedEvent,
|
|
184
|
+
'webset.search.created': WebsetSearchCreatedEvent,
|
|
185
|
+
'webset.search.updated': WebsetSearchUpdatedEvent,
|
|
186
|
+
'webset.search.canceled': WebsetSearchCanceledEvent,
|
|
187
|
+
'webset.search.completed': WebsetSearchCompletedEvent,
|
|
188
|
+
'import.created': ImportCreatedEvent,
|
|
189
|
+
'import.completed': ImportCompletedEvent,
|
|
190
|
+
'monitor.created': MonitorCreatedEvent,
|
|
191
|
+
'monitor.updated': MonitorUpdatedEvent,
|
|
192
|
+
'monitor.deleted': MonitorDeletedEvent,
|
|
193
|
+
'monitor.run.created': MonitorRunCreatedEvent,
|
|
194
|
+
'monitor.run.completed': MonitorRunCompletedEvent,
|
|
195
|
+
}
|
|
196
|
+
|
|
115
197
|
event_class = event_type_map.get(event_type)
|
|
116
198
|
if event_class:
|
|
117
199
|
return event_class.model_validate(response)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .client import ImportsClient
|
|
2
|
-
|
|
3
|
-
__all__ = ["ImportsClient"]
|
|
1
|
+
from .client import ImportsClient, AsyncImportsClient
|
|
2
|
+
|
|
3
|
+
__all__ = ["ImportsClient", "AsyncImportsClient"]
|
exa_py/websets/imports/client.py
CHANGED
|
@@ -4,7 +4,9 @@ import time
|
|
|
4
4
|
import os
|
|
5
5
|
import csv
|
|
6
6
|
import io
|
|
7
|
+
import asyncio
|
|
7
8
|
import requests
|
|
9
|
+
import httpx
|
|
8
10
|
from typing import Dict, Any, Union, Optional
|
|
9
11
|
from pathlib import Path
|
|
10
12
|
|
|
@@ -16,6 +18,7 @@ from ..types import (
|
|
|
16
18
|
UpdateImport,
|
|
17
19
|
)
|
|
18
20
|
from ..core.base import WebsetsBaseClient
|
|
21
|
+
from ..core.async_base import WebsetsAsyncBaseClient
|
|
19
22
|
|
|
20
23
|
class ImportsClient(WebsetsBaseClient):
|
|
21
24
|
"""Client for managing Imports."""
|
|
@@ -176,4 +179,169 @@ class ImportsClient(WebsetsBaseClient):
|
|
|
176
179
|
if time.time() - start_time > timeout:
|
|
177
180
|
raise TimeoutError(f"Import {import_id} did not complete within {timeout} seconds")
|
|
178
181
|
|
|
179
|
-
time.sleep(poll_interval)
|
|
182
|
+
time.sleep(poll_interval)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class AsyncImportsClient(WebsetsAsyncBaseClient):
|
|
186
|
+
"""Async client for managing Imports."""
|
|
187
|
+
|
|
188
|
+
def __init__(self, client):
|
|
189
|
+
super().__init__(client)
|
|
190
|
+
|
|
191
|
+
async def create(
|
|
192
|
+
self,
|
|
193
|
+
params: Union[Dict[str, Any], CreateImportParameters],
|
|
194
|
+
*,
|
|
195
|
+
csv_data: Optional[Union[str, Path]] = None
|
|
196
|
+
) -> Union[CreateImportResponse, Import]:
|
|
197
|
+
"""Create a new import to upload your data into Websets.
|
|
198
|
+
|
|
199
|
+
Imports can be used to:
|
|
200
|
+
- Enrich: Enhance your data with additional information using our AI-powered enrichment engine
|
|
201
|
+
- Search: Query your data using Websets' agentic search with natural language filters
|
|
202
|
+
- Exclude: Prevent duplicate or already known results from appearing in your searches
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
params (CreateImportParameters): The parameters for creating an import.
|
|
206
|
+
csv_data (Union[str, Path], optional): CSV data to upload. Can be raw CSV string or file path.
|
|
207
|
+
When provided, size and count will be automatically calculated
|
|
208
|
+
if not specified in params.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
CreateImportResponse: If csv_data is None (traditional usage with upload URL).
|
|
212
|
+
Import: If csv_data is provided (uploaded and processing).
|
|
213
|
+
"""
|
|
214
|
+
if csv_data is not None:
|
|
215
|
+
if isinstance(csv_data, (str, Path)) and os.path.isfile(csv_data):
|
|
216
|
+
# Use synchronous file reading for simplicity (file reading is typically fast)
|
|
217
|
+
with open(csv_data, 'r', encoding='utf-8') as f:
|
|
218
|
+
csv_content = f.read()
|
|
219
|
+
else:
|
|
220
|
+
csv_content = str(csv_data)
|
|
221
|
+
|
|
222
|
+
if isinstance(params, dict):
|
|
223
|
+
current_size = params.get('size')
|
|
224
|
+
current_count = params.get('count')
|
|
225
|
+
else:
|
|
226
|
+
current_size = getattr(params, 'size', None)
|
|
227
|
+
current_count = getattr(params, 'count', None)
|
|
228
|
+
|
|
229
|
+
if current_size is None or current_count is None:
|
|
230
|
+
calculated_size = len(csv_content.encode('utf-8'))
|
|
231
|
+
csv_reader = csv.reader(io.StringIO(csv_content))
|
|
232
|
+
rows = list(csv_reader)
|
|
233
|
+
calculated_count = max(0, len(rows) - 1)
|
|
234
|
+
|
|
235
|
+
if isinstance(params, dict):
|
|
236
|
+
params = params.copy()
|
|
237
|
+
if current_size is None:
|
|
238
|
+
params['size'] = calculated_size
|
|
239
|
+
if current_count is None:
|
|
240
|
+
params['count'] = calculated_count
|
|
241
|
+
else:
|
|
242
|
+
params_dict = params.model_dump()
|
|
243
|
+
if current_size is None:
|
|
244
|
+
params_dict['size'] = calculated_size
|
|
245
|
+
if current_count is None:
|
|
246
|
+
params_dict['count'] = calculated_count
|
|
247
|
+
params = CreateImportParameters.model_validate(params_dict)
|
|
248
|
+
|
|
249
|
+
response = await self.request("/v0/imports", data=params)
|
|
250
|
+
import_response = CreateImportResponse.model_validate(response)
|
|
251
|
+
|
|
252
|
+
if csv_data is None:
|
|
253
|
+
return import_response
|
|
254
|
+
|
|
255
|
+
# Use httpx for async HTTP requests
|
|
256
|
+
async with httpx.AsyncClient() as http_client:
|
|
257
|
+
upload_response = await http_client.put(
|
|
258
|
+
import_response.upload_url,
|
|
259
|
+
data=csv_content,
|
|
260
|
+
headers={'Content-Type': 'text/csv'}
|
|
261
|
+
)
|
|
262
|
+
upload_response.raise_for_status()
|
|
263
|
+
|
|
264
|
+
return await self.get(import_response.id)
|
|
265
|
+
|
|
266
|
+
async def get(self, import_id: str) -> Import:
|
|
267
|
+
"""Get a specific import.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
import_id (str): The id of the Import.
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
Import: The retrieved import.
|
|
274
|
+
"""
|
|
275
|
+
response = await self.request(f"/v0/imports/{import_id}", method="GET")
|
|
276
|
+
return Import.model_validate(response)
|
|
277
|
+
|
|
278
|
+
async def list(self, *, cursor: Optional[str] = None, limit: Optional[int] = None) -> ListImportsResponse:
|
|
279
|
+
"""List all imports.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
cursor (str, optional): The cursor to paginate through the results.
|
|
283
|
+
limit (int, optional): The number of results to return (1-200, default 25).
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
ListImportsResponse: List of imports with pagination info.
|
|
287
|
+
"""
|
|
288
|
+
params = {
|
|
289
|
+
k: v
|
|
290
|
+
for k, v in {
|
|
291
|
+
"cursor": cursor,
|
|
292
|
+
"limit": limit
|
|
293
|
+
}.items()
|
|
294
|
+
if v is not None
|
|
295
|
+
}
|
|
296
|
+
response = await self.request("/v0/imports", params=params, method="GET")
|
|
297
|
+
return ListImportsResponse.model_validate(response)
|
|
298
|
+
|
|
299
|
+
async def update(self, import_id: str, params: Union[Dict[str, Any], UpdateImport]) -> Import:
|
|
300
|
+
"""Update an import configuration.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
import_id (str): The id of the Import.
|
|
304
|
+
params (UpdateImport): The parameters for updating an import.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Import: The updated import.
|
|
308
|
+
"""
|
|
309
|
+
response = await self.request(f"/v0/imports/{import_id}", data=params, method="PATCH")
|
|
310
|
+
return Import.model_validate(response)
|
|
311
|
+
|
|
312
|
+
async def delete(self, import_id: str) -> Import:
|
|
313
|
+
"""Delete an import.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
import_id (str): The id of the Import.
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Import: The deleted import.
|
|
320
|
+
"""
|
|
321
|
+
response = await self.request(f"/v0/imports/{import_id}", method="DELETE")
|
|
322
|
+
return Import.model_validate(response)
|
|
323
|
+
|
|
324
|
+
async def wait_until_completed(self, import_id: str, *, timeout: int = 1800, poll_interval: int = 5) -> Import:
|
|
325
|
+
"""Wait until an import is completed or failed.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
import_id (str): The id of the Import.
|
|
329
|
+
timeout (int, optional): Maximum time to wait in seconds. Defaults to 1800 (30 minutes).
|
|
330
|
+
poll_interval (int, optional): Time to wait between polls in seconds. Defaults to 5.
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
Import: The import once it's completed or failed.
|
|
334
|
+
|
|
335
|
+
Raises:
|
|
336
|
+
TimeoutError: If the import does not complete within the timeout period.
|
|
337
|
+
"""
|
|
338
|
+
start_time = asyncio.get_event_loop().time()
|
|
339
|
+
while True:
|
|
340
|
+
import_obj = await self.get(import_id)
|
|
341
|
+
if import_obj.status in ['completed', 'failed']:
|
|
342
|
+
return import_obj
|
|
343
|
+
|
|
344
|
+
if asyncio.get_event_loop().time() - start_time > timeout:
|
|
345
|
+
raise TimeoutError(f"Import {import_id} did not complete within {timeout} seconds")
|
|
346
|
+
|
|
347
|
+
await asyncio.sleep(poll_interval)
|
exa_py/websets/items/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .client import WebsetItemsClient
|
|
1
|
+
from .client import WebsetItemsClient, AsyncWebsetItemsClient
|
|
2
2
|
|
|
3
|
-
__all__ = ["WebsetItemsClient"]
|
|
3
|
+
__all__ = ["WebsetItemsClient", "AsyncWebsetItemsClient"]
|
exa_py/websets/items/client.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Optional, Iterator, AsyncIterator
|
|
4
4
|
|
|
5
5
|
from ..types import (
|
|
6
6
|
WebsetItem,
|
|
7
7
|
ListWebsetItemResponse,
|
|
8
8
|
)
|
|
9
9
|
from ..core.base import WebsetsBaseClient
|
|
10
|
+
from ..core.async_base import WebsetsAsyncBaseClient
|
|
10
11
|
|
|
11
12
|
class WebsetItemsClient(WebsetsBaseClient):
|
|
12
13
|
"""Client for managing Webset Items."""
|
|
@@ -77,4 +78,76 @@ class WebsetItemsClient(WebsetsBaseClient):
|
|
|
77
78
|
WebsetItem: The deleted item.
|
|
78
79
|
"""
|
|
79
80
|
response = self.request(f"/v0/websets/{webset_id}/items/{id}", method="DELETE")
|
|
81
|
+
return WebsetItem.model_validate(response)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class AsyncWebsetItemsClient(WebsetsAsyncBaseClient):
|
|
85
|
+
"""Async client for managing Webset Items."""
|
|
86
|
+
|
|
87
|
+
def __init__(self, client):
|
|
88
|
+
super().__init__(client)
|
|
89
|
+
|
|
90
|
+
async def list(self, webset_id: str, *, cursor: Optional[str] = None,
|
|
91
|
+
limit: Optional[int] = None, source_id: Optional[str] = None) -> ListWebsetItemResponse:
|
|
92
|
+
"""List all Items for a Webset.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
webset_id (str): The id or externalId of the Webset.
|
|
96
|
+
cursor (str, optional): The cursor to paginate through the results.
|
|
97
|
+
limit (int, optional): The number of results to return (max 200).
|
|
98
|
+
source_id (str, optional): Filter items by source ID.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
ListWebsetItemResponse: List of webset items.
|
|
102
|
+
"""
|
|
103
|
+
params = {k: v for k, v in {"cursor": cursor, "limit": limit, "sourceId": source_id}.items() if v is not None}
|
|
104
|
+
response = await self.request(f"/v0/websets/{webset_id}/items", params=params, method="GET")
|
|
105
|
+
return ListWebsetItemResponse.model_validate(response)
|
|
106
|
+
|
|
107
|
+
async def list_all(self, webset_id: str, *, limit: Optional[int] = None, source_id: Optional[str] = None) -> AsyncIterator[WebsetItem]:
|
|
108
|
+
"""Iterate through all Items in a Webset, handling pagination automatically.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
webset_id (str): The id or externalId of the Webset.
|
|
112
|
+
limit (int, optional): The number of results to return per page (max 200).
|
|
113
|
+
source_id (str, optional): Filter items by source ID.
|
|
114
|
+
|
|
115
|
+
Yields:
|
|
116
|
+
WebsetItem: Each item in the webset.
|
|
117
|
+
"""
|
|
118
|
+
cursor = None
|
|
119
|
+
while True:
|
|
120
|
+
response = await self.list(webset_id, cursor=cursor, limit=limit, source_id=source_id)
|
|
121
|
+
for item in response.data:
|
|
122
|
+
yield item
|
|
123
|
+
|
|
124
|
+
if not response.has_more or not response.next_cursor:
|
|
125
|
+
break
|
|
126
|
+
|
|
127
|
+
cursor = response.next_cursor
|
|
128
|
+
|
|
129
|
+
async def get(self, webset_id: str, id: str) -> WebsetItem:
|
|
130
|
+
"""Get an Item by ID.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
webset_id (str): The id or externalId of the Webset.
|
|
134
|
+
id (str): The id of the Webset item.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
WebsetItem: The retrieved item.
|
|
138
|
+
"""
|
|
139
|
+
response = await self.request(f"/v0/websets/{webset_id}/items/{id}", method="GET")
|
|
140
|
+
return WebsetItem.model_validate(response)
|
|
141
|
+
|
|
142
|
+
async def delete(self, webset_id: str, id: str) -> WebsetItem:
|
|
143
|
+
"""Delete an Item.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
webset_id (str): The id or externalId of the Webset.
|
|
147
|
+
id (str): The id of the Webset item.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
WebsetItem: The deleted item.
|
|
151
|
+
"""
|
|
152
|
+
response = await self.request(f"/v0/websets/{webset_id}/items/{id}", method="DELETE")
|
|
80
153
|
return WebsetItem.model_validate(response)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .client import MonitorsClient
|
|
2
|
-
from .runs import MonitorRunsClient
|
|
1
|
+
from .client import MonitorsClient, AsyncMonitorsClient
|
|
2
|
+
from .runs import MonitorRunsClient, AsyncMonitorRunsClient
|
|
3
3
|
|
|
4
|
-
__all__ = ["MonitorsClient", "MonitorRunsClient"]
|
|
4
|
+
__all__ = ["MonitorsClient", "AsyncMonitorsClient", "MonitorRunsClient", "AsyncMonitorRunsClient"]
|
|
@@ -9,6 +9,7 @@ from ..types import (
|
|
|
9
9
|
ListMonitorsResponse,
|
|
10
10
|
)
|
|
11
11
|
from ..core.base import WebsetsBaseClient
|
|
12
|
+
from ..core.async_base import WebsetsAsyncBaseClient
|
|
12
13
|
from .runs import MonitorRunsClient
|
|
13
14
|
|
|
14
15
|
class MonitorsClient(WebsetsBaseClient):
|
|
@@ -93,4 +94,39 @@ class MonitorsClient(WebsetsBaseClient):
|
|
|
93
94
|
Monitor: The deleted monitor.
|
|
94
95
|
"""
|
|
95
96
|
response = self.request(f"/v0/monitors/{monitor_id}", method="DELETE")
|
|
97
|
+
return Monitor.model_validate(response)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class AsyncMonitorsClient(WebsetsAsyncBaseClient):
|
|
101
|
+
"""Async client for managing Monitors."""
|
|
102
|
+
|
|
103
|
+
def __init__(self, client):
|
|
104
|
+
super().__init__(client)
|
|
105
|
+
from .runs import AsyncMonitorRunsClient
|
|
106
|
+
self.runs = AsyncMonitorRunsClient(client)
|
|
107
|
+
|
|
108
|
+
async def create(self, params: Union[Dict[str, Any], CreateMonitorParameters]) -> Monitor:
|
|
109
|
+
"""Create a new Monitor to continuously keep your Websets updated with fresh data."""
|
|
110
|
+
response = await self.request("/v0/monitors", data=params)
|
|
111
|
+
return Monitor.model_validate(response)
|
|
112
|
+
|
|
113
|
+
async def get(self, monitor_id: str) -> Monitor:
|
|
114
|
+
"""Get a specific monitor."""
|
|
115
|
+
response = await self.request(f"/v0/monitors/{monitor_id}", method="GET")
|
|
116
|
+
return Monitor.model_validate(response)
|
|
117
|
+
|
|
118
|
+
async def list(self, *, cursor: Optional[str] = None, limit: Optional[int] = None, webset_id: Optional[str] = None) -> ListMonitorsResponse:
|
|
119
|
+
"""List all monitors."""
|
|
120
|
+
params = {k: v for k, v in {"cursor": cursor, "limit": limit, "websetId": webset_id}.items() if v is not None}
|
|
121
|
+
response = await self.request("/v0/monitors", params=params, method="GET")
|
|
122
|
+
return ListMonitorsResponse.model_validate(response)
|
|
123
|
+
|
|
124
|
+
async def update(self, monitor_id: str, params: Union[Dict[str, Any], UpdateMonitor]) -> Monitor:
|
|
125
|
+
"""Update a monitor configuration."""
|
|
126
|
+
response = await self.request(f"/v0/monitors/{monitor_id}", data=params, method="PATCH")
|
|
127
|
+
return Monitor.model_validate(response)
|
|
128
|
+
|
|
129
|
+
async def delete(self, monitor_id: str) -> Monitor:
|
|
130
|
+
"""Delete a monitor."""
|
|
131
|
+
response = await self.request(f"/v0/monitors/{monitor_id}", method="DELETE")
|
|
96
132
|
return Monitor.model_validate(response)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .client import MonitorRunsClient
|
|
1
|
+
from .client import MonitorRunsClient, AsyncMonitorRunsClient
|
|
2
2
|
|
|
3
|
-
__all__ = ["MonitorRunsClient"]
|
|
3
|
+
__all__ = ["MonitorRunsClient", "AsyncMonitorRunsClient"]
|
|
@@ -5,6 +5,7 @@ from ...types import (
|
|
|
5
5
|
ListMonitorRunsResponse,
|
|
6
6
|
)
|
|
7
7
|
from ...core.base import WebsetsBaseClient
|
|
8
|
+
from ...core.async_base import WebsetsAsyncBaseClient
|
|
8
9
|
|
|
9
10
|
class MonitorRunsClient(WebsetsBaseClient):
|
|
10
11
|
"""Client for managing Monitor Runs."""
|
|
@@ -35,4 +36,21 @@ class MonitorRunsClient(WebsetsBaseClient):
|
|
|
35
36
|
MonitorRun: The monitor run details.
|
|
36
37
|
"""
|
|
37
38
|
response = self.request(f"/v0/monitors/{monitor_id}/runs/{run_id}", method="GET")
|
|
39
|
+
return MonitorRun.model_validate(response)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class AsyncMonitorRunsClient(WebsetsAsyncBaseClient):
|
|
43
|
+
"""Async client for managing Monitor Runs."""
|
|
44
|
+
|
|
45
|
+
def __init__(self, client):
|
|
46
|
+
super().__init__(client)
|
|
47
|
+
|
|
48
|
+
async def list(self, monitor_id: str) -> ListMonitorRunsResponse:
|
|
49
|
+
"""List all runs for the Monitor."""
|
|
50
|
+
response = await self.request(f"/v0/monitors/{monitor_id}/runs", method="GET")
|
|
51
|
+
return ListMonitorRunsResponse.model_validate(response)
|
|
52
|
+
|
|
53
|
+
async def get(self, monitor_id: str, run_id: str) -> MonitorRun:
|
|
54
|
+
"""Get a specific monitor run."""
|
|
55
|
+
response = await self.request(f"/v0/monitors/{monitor_id}/runs/{run_id}", method="GET")
|
|
38
56
|
return MonitorRun.model_validate(response)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .client import WebsetSearchesClient
|
|
1
|
+
from .client import WebsetSearchesClient, AsyncWebsetSearchesClient
|
|
2
2
|
|
|
3
|
-
__all__ = ["WebsetSearchesClient"]
|
|
3
|
+
__all__ = ["WebsetSearchesClient", "AsyncWebsetSearchesClient"]
|
|
@@ -7,6 +7,7 @@ from ..types import (
|
|
|
7
7
|
WebsetSearch,
|
|
8
8
|
)
|
|
9
9
|
from ..core.base import WebsetsBaseClient
|
|
10
|
+
from ..core.async_base import WebsetsAsyncBaseClient
|
|
10
11
|
|
|
11
12
|
class WebsetSearchesClient(WebsetsBaseClient):
|
|
12
13
|
"""Client for managing Webset Searches."""
|
|
@@ -51,4 +52,50 @@ class WebsetSearchesClient(WebsetsBaseClient):
|
|
|
51
52
|
WebsetSearch: The canceled search.
|
|
52
53
|
"""
|
|
53
54
|
response = self.request(f"/v0/websets/{webset_id}/searches/{id}/cancel", method="POST")
|
|
55
|
+
return WebsetSearch.model_validate(response)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class AsyncWebsetSearchesClient(WebsetsAsyncBaseClient):
|
|
59
|
+
"""Async client for managing Webset Searches."""
|
|
60
|
+
|
|
61
|
+
def __init__(self, client):
|
|
62
|
+
super().__init__(client)
|
|
63
|
+
|
|
64
|
+
async def create(self, webset_id: str, params: Union[Dict[str, Any], CreateWebsetSearchParameters]) -> WebsetSearch:
|
|
65
|
+
"""Create a new Search for the Webset.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
webset_id (str): The id of the Webset.
|
|
69
|
+
params (CreateWebsetSearchParameters): The parameters for creating a search.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
WebsetSearch: The created search.
|
|
73
|
+
"""
|
|
74
|
+
response = await self.request(f"/v0/websets/{webset_id}/searches", data=params)
|
|
75
|
+
return WebsetSearch.model_validate(response)
|
|
76
|
+
|
|
77
|
+
async def get(self, webset_id: str, id: str) -> WebsetSearch:
|
|
78
|
+
"""Get a Search by ID.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
webset_id (str): The id of the Webset.
|
|
82
|
+
id (str): The id of the Search.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
WebsetSearch: The retrieved search.
|
|
86
|
+
"""
|
|
87
|
+
response = await self.request(f"/v0/websets/{webset_id}/searches/{id}", method="GET")
|
|
88
|
+
return WebsetSearch.model_validate(response)
|
|
89
|
+
|
|
90
|
+
async def cancel(self, webset_id: str, id: str) -> WebsetSearch:
|
|
91
|
+
"""Cancel a running Search.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
webset_id (str): The id of the Webset.
|
|
95
|
+
id (str): The id of the Search.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
WebsetSearch: The canceled search.
|
|
99
|
+
"""
|
|
100
|
+
response = await self.request(f"/v0/websets/{webset_id}/searches/{id}/cancel", method="POST")
|
|
54
101
|
return WebsetSearch.model_validate(response)
|
exa_py/websets/types.py
CHANGED
|
@@ -24,15 +24,24 @@ class WebsetSearchBehavior(Enum):
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class MonitorBehaviorSearchConfig(ExaBaseModel):
|
|
27
|
-
query: str
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
query: Optional[str] = None
|
|
28
|
+
"""
|
|
29
|
+
The query to search for. By default, the query from the last search is used.
|
|
30
|
+
"""
|
|
31
|
+
criteria: Optional[List[SearchCriterion]] = None
|
|
32
|
+
"""
|
|
33
|
+
The criteria to search for. By default, the criteria from the last search is used.
|
|
34
|
+
"""
|
|
35
|
+
entity: Optional[Union[
|
|
30
36
|
WebsetCompanyEntity,
|
|
31
37
|
WebsetPersonEntity,
|
|
32
38
|
WebsetArticleEntity,
|
|
33
39
|
WebsetResearchPaperEntity,
|
|
34
40
|
WebsetCustomEntity,
|
|
35
|
-
] = Field(
|
|
41
|
+
]] = Field(None, title='WebsetEntity')
|
|
42
|
+
"""
|
|
43
|
+
The entity to search for. By default, the entity from the last search/import is used.
|
|
44
|
+
"""
|
|
36
45
|
count: int
|
|
37
46
|
"""
|
|
38
47
|
The maximum number of results to find
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .client import WebsetWebhooksClient
|
|
1
|
+
from .client import WebsetWebhooksClient, AsyncWebsetWebhooksClient, AsyncWebhookAttemptsClient
|
|
2
2
|
|
|
3
|
-
__all__ = ["WebsetWebhooksClient"]
|
|
3
|
+
__all__ = ["WebsetWebhooksClient", "AsyncWebsetWebhooksClient", "AsyncWebhookAttemptsClient"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Optional, Dict, Any, Union
|
|
3
|
+
from typing import Optional, Dict, Any, Union
|
|
4
4
|
|
|
5
5
|
from ..types import (
|
|
6
6
|
CreateWebhookParameters,
|
|
@@ -11,6 +11,7 @@ from ..types import (
|
|
|
11
11
|
EventType,
|
|
12
12
|
)
|
|
13
13
|
from ..core.base import WebsetsBaseClient
|
|
14
|
+
from ..core.async_base import WebsetsAsyncBaseClient
|
|
14
15
|
|
|
15
16
|
class WebhookAttemptsClient(WebsetsBaseClient):
|
|
16
17
|
"""Client for managing Webhook Attempts."""
|
|
@@ -118,4 +119,65 @@ class WebsetWebhooksClient(WebsetsBaseClient):
|
|
|
118
119
|
Webhook: The deleted webhook.
|
|
119
120
|
"""
|
|
120
121
|
response = self.request(f"/v0/webhooks/{id}", method="DELETE")
|
|
122
|
+
return Webhook.model_validate(response)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class AsyncWebhookAttemptsClient(WebsetsAsyncBaseClient):
|
|
126
|
+
"""Async client for managing Webhook Attempts."""
|
|
127
|
+
|
|
128
|
+
def __init__(self, client):
|
|
129
|
+
super().__init__(client)
|
|
130
|
+
|
|
131
|
+
async def list(self, webhook_id: str, *, cursor: Optional[str] = None,
|
|
132
|
+
limit: Optional[int] = None, event_type: Optional[Union[EventType, str]] = None,
|
|
133
|
+
successful: Optional[bool] = None) -> ListWebhookAttemptsResponse:
|
|
134
|
+
"""List all attempts made by a Webhook ordered in descending order."""
|
|
135
|
+
event_type_value = None
|
|
136
|
+
if event_type is not None:
|
|
137
|
+
if isinstance(event_type, EventType):
|
|
138
|
+
event_type_value = event_type.value
|
|
139
|
+
else:
|
|
140
|
+
event_type_value = event_type
|
|
141
|
+
|
|
142
|
+
params = {k: v for k, v in {
|
|
143
|
+
"cursor": cursor,
|
|
144
|
+
"limit": limit,
|
|
145
|
+
"eventType": event_type_value,
|
|
146
|
+
"successful": successful
|
|
147
|
+
}.items() if v is not None}
|
|
148
|
+
|
|
149
|
+
response = await self.request(f"/v0/webhooks/{webhook_id}/attempts", params=params, method="GET")
|
|
150
|
+
return ListWebhookAttemptsResponse.model_validate(response)
|
|
151
|
+
|
|
152
|
+
class AsyncWebsetWebhooksClient(WebsetsAsyncBaseClient):
|
|
153
|
+
"""Async client for managing Webset Webhooks."""
|
|
154
|
+
|
|
155
|
+
def __init__(self, client):
|
|
156
|
+
super().__init__(client)
|
|
157
|
+
self.attempts = AsyncWebhookAttemptsClient(client)
|
|
158
|
+
|
|
159
|
+
async def create(self, params: Union[Dict[str, Any], CreateWebhookParameters]) -> Webhook:
|
|
160
|
+
"""Create a Webhook."""
|
|
161
|
+
response = await self.request("/v0/webhooks", data=params)
|
|
162
|
+
return Webhook.model_validate(response)
|
|
163
|
+
|
|
164
|
+
async def get(self, id: str) -> Webhook:
|
|
165
|
+
"""Get a Webhook by ID."""
|
|
166
|
+
response = await self.request(f"/v0/webhooks/{id}", method="GET")
|
|
167
|
+
return Webhook.model_validate(response)
|
|
168
|
+
|
|
169
|
+
async def list(self, *, cursor: Optional[str] = None, limit: Optional[int] = None) -> ListWebhooksResponse:
|
|
170
|
+
"""List all Webhooks."""
|
|
171
|
+
params = {k: v for k, v in {"cursor": cursor, "limit": limit}.items() if v is not None}
|
|
172
|
+
response = await self.request("/v0/webhooks", params=params, method="GET")
|
|
173
|
+
return ListWebhooksResponse.model_validate(response)
|
|
174
|
+
|
|
175
|
+
async def update(self, id: str, params: Union[Dict[str, Any], UpdateWebhookParameters]) -> Webhook:
|
|
176
|
+
"""Update a Webhook."""
|
|
177
|
+
response = await self.request(f"/v0/webhooks/{id}", data=params, method="PATCH")
|
|
178
|
+
return Webhook.model_validate(response)
|
|
179
|
+
|
|
180
|
+
async def delete(self, id: str) -> Webhook:
|
|
181
|
+
"""Delete a Webhook."""
|
|
182
|
+
response = await self.request(f"/v0/webhooks/{id}", method="DELETE")
|
|
121
183
|
return Webhook.model_validate(response)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
exa_py/__init__.py,sha256=M2GC9oSdoV6m2msboW0vMWWl8wrth4o6gmEV4MYLGG8,66
|
|
2
|
+
exa_py/api.py,sha256=ftJRM7qnF-Ki4agnG4PLtCn7YcrBV1JlC_TmhH5bbG4,109112
|
|
3
|
+
exa_py/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
exa_py/research/__init__.py,sha256=qbWY5c3LYBM7L4yGVtiMs9nUg_kMcAVhMhT0DvN6EI4,1014
|
|
5
|
+
exa_py/research/async_client.py,sha256=jP6BF8nc29Mt4iU2ZEQGAC5dGM-Z9I4k3pzpPcCKJIs,9436
|
|
6
|
+
exa_py/research/base.py,sha256=0C52XGUMRwRox1JSVBrbiHZxqPI6Cgif7EFNqYxpc40,5451
|
|
7
|
+
exa_py/research/models.py,sha256=2gu4jckbLYHlTmln8BhDzovuqg1fejTCncqi4r0oDow,9822
|
|
8
|
+
exa_py/research/sync_client.py,sha256=LHMkgqUZgKCQWgLP41Fj6EWLbt_YfX4aAgvWGjNgbXM,9155
|
|
9
|
+
exa_py/research/utils.py,sha256=YR61UkReyK-LrvOTaX_aG_neS1DsmCkv7B6YODpwHvU,5965
|
|
10
|
+
exa_py/utils.py,sha256=1jwKwcJwHSbrzwgMkprXSEZ-xssCtXxwf-GTRgaFmz8,6395
|
|
11
|
+
exa_py/websets/__init__.py,sha256=8ZWndRgeTKceZ3Wcm5xCh_dykrKkoCYdZdKcK7C3aSw,226
|
|
12
|
+
exa_py/websets/_generator/pydantic/BaseModel.jinja2,sha256=RUDCmPZVamoVx1WudylscYFfDhGoNNtRYlpTvKjAiuA,1276
|
|
13
|
+
exa_py/websets/async_client.py,sha256=fewb7T64Ip5R67sZ2fceHv-Lv0gJPqQrsXq-v6ZuZPY,5823
|
|
14
|
+
exa_py/websets/client.py,sha256=mdzZSfzgajfPQKWmjvwhUqjJSrtm3aErKcv4zcp7tWI,11137
|
|
15
|
+
exa_py/websets/core/__init__.py,sha256=L8dLhlle-Y7yoo0p0s60S07UyknyrcEn64W9JxkvCjM,458
|
|
16
|
+
exa_py/websets/core/async_base.py,sha256=RlJEaNR7OfZFzSy4sCk5aiPNT3cztuFZIyfP5vXMGtI,3121
|
|
17
|
+
exa_py/websets/core/base.py,sha256=RldWYwBg2iVfkWmdPke7xjXdwb4JKeABIOgiZtqvz-4,4125
|
|
18
|
+
exa_py/websets/enrichments/__init__.py,sha256=DA57V8s3169lfMnnLcFIOMQxhFIZ9I0uwXPYZMJzs9A,145
|
|
19
|
+
exa_py/websets/enrichments/client.py,sha256=EStsgPgAggEa0FiYrIG9HNZ30akuUrXtKY27f-Fa3sI,5903
|
|
20
|
+
exa_py/websets/events/__init__.py,sha256=VfJzObC3rSstdqz6q2ePnOIRW50GKJoSSH3-mpmDG0w,100
|
|
21
|
+
exa_py/websets/events/client.py,sha256=_jLGUlf27W5XYa7AeUVVvJ9hffwbPZ7981Qz-Fi6U1c,7691
|
|
22
|
+
exa_py/websets/imports/__init__.py,sha256=5fxYvRQdJQsVngvuq278Yw5W0Ckw17I_aPRrrtPcJ1w,105
|
|
23
|
+
exa_py/websets/imports/client.py,sha256=Zr_qWO1rhYTXm62Jz5bR7orfvzDhcb7pHVfeO8uvVmQ,13700
|
|
24
|
+
exa_py/websets/items/__init__.py,sha256=aJZto81Zp9eK1Dou2cFrRXgv3ZBuEvCHqb2G4KuKoao,121
|
|
25
|
+
exa_py/websets/items/client.py,sha256=74vRjMrEoy6cVA8679dFtD43IU2jKDH8Zlw4hLIRs8I,6027
|
|
26
|
+
exa_py/websets/monitors/__init__.py,sha256=cTRxTrsUuQmmmVEN3ewKsOq26xxiBJKTy7v0UjdOooc,216
|
|
27
|
+
exa_py/websets/monitors/client.py,sha256=PmIkizecQSLnicKpIPEBJafId9rx_iJlP-LD_ApuAik,5333
|
|
28
|
+
exa_py/websets/monitors/runs/__init__.py,sha256=rfE6PmQds4uPAd0fN3u992pG7INwbx1QvdyH8M-t8rs,121
|
|
29
|
+
exa_py/websets/monitors/runs/client.py,sha256=_fMPqxzF0gy5g76wU6N8i7XrKTtq5vaOrrIzXkM1ZcA,1985
|
|
30
|
+
exa_py/websets/searches/__init__.py,sha256=w6fJnCTKwl07GWgRVKQbYkPcoAct975YyOZog37C2q8,133
|
|
31
|
+
exa_py/websets/searches/client.py,sha256=_mCuQtdLvKus5ofgs2a9MtY56Zg07JBJzqIg6YWre2A,3495
|
|
32
|
+
exa_py/websets/types.py,sha256=naBzmlJ-nZK3ynDGBE15lmItD5p8-x_OfsWGFpKZRDs,50874
|
|
33
|
+
exa_py/websets/webhooks/__init__.py,sha256=DMl6RFkS0c79AWzkuHOXnaU5QKHmkIHYW2PhZWUFIGc,191
|
|
34
|
+
exa_py/websets/webhooks/client.py,sha256=rdYU0DZKAslw5LwGKB567j3T8L34ZF9tSnlN9jLi23A,7143
|
|
35
|
+
exa_py-1.15.2.dist-info/METADATA,sha256=Izyx0YsIaj8Q8bztKKC0UD1L75KJHJrZsMjZ_CVbLv0,3826
|
|
36
|
+
exa_py-1.15.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
37
|
+
exa_py-1.15.2.dist-info/RECORD,,
|
exa_py-1.15.1.dist-info/RECORD
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
exa_py/__init__.py,sha256=M2GC9oSdoV6m2msboW0vMWWl8wrth4o6gmEV4MYLGG8,66
|
|
2
|
-
exa_py/api.py,sha256=gUvQ2NXtUgBlrFrWrCIUwiq-z2lAlo_gWVFncN68Vhw,108947
|
|
3
|
-
exa_py/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
exa_py/research/__init__.py,sha256=qbWY5c3LYBM7L4yGVtiMs9nUg_kMcAVhMhT0DvN6EI4,1014
|
|
5
|
-
exa_py/research/async_client.py,sha256=jP6BF8nc29Mt4iU2ZEQGAC5dGM-Z9I4k3pzpPcCKJIs,9436
|
|
6
|
-
exa_py/research/base.py,sha256=0C52XGUMRwRox1JSVBrbiHZxqPI6Cgif7EFNqYxpc40,5451
|
|
7
|
-
exa_py/research/models.py,sha256=2gu4jckbLYHlTmln8BhDzovuqg1fejTCncqi4r0oDow,9822
|
|
8
|
-
exa_py/research/sync_client.py,sha256=LHMkgqUZgKCQWgLP41Fj6EWLbt_YfX4aAgvWGjNgbXM,9155
|
|
9
|
-
exa_py/research/utils.py,sha256=YR61UkReyK-LrvOTaX_aG_neS1DsmCkv7B6YODpwHvU,5965
|
|
10
|
-
exa_py/utils.py,sha256=1jwKwcJwHSbrzwgMkprXSEZ-xssCtXxwf-GTRgaFmz8,6395
|
|
11
|
-
exa_py/websets/__init__.py,sha256=x7Dc0MS8raRXA7Ud6alKgnsUmLi6X9GTqfB8kOwC9iQ,179
|
|
12
|
-
exa_py/websets/_generator/pydantic/BaseModel.jinja2,sha256=RUDCmPZVamoVx1WudylscYFfDhGoNNtRYlpTvKjAiuA,1276
|
|
13
|
-
exa_py/websets/client.py,sha256=sKkji8QaPFnGM1-J5TB6yKJcGAEd6gk7lsnIebzXNQ8,5856
|
|
14
|
-
exa_py/websets/core/__init__.py,sha256=xOyrFaqtBocMUu321Jpbk7IzIQRNZufSIGJXrKoG-Bg,323
|
|
15
|
-
exa_py/websets/core/base.py,sha256=RldWYwBg2iVfkWmdPke7xjXdwb4JKeABIOgiZtqvz-4,4125
|
|
16
|
-
exa_py/websets/enrichments/__init__.py,sha256=5dJIEKKceUost3RnI6PpCSB3VjUCBzxseEsIXu-ZY-Y,83
|
|
17
|
-
exa_py/websets/enrichments/client.py,sha256=Qn6B19Gf1z4pQ5CCeXMFeTJnVi2OiVx9Ck5XlcQBZVI,2999
|
|
18
|
-
exa_py/websets/events/__init__.py,sha256=aFJ9O5UudtQQzndVmdB96IaM2l07qyM1B_8xKY7rp58,60
|
|
19
|
-
exa_py/websets/events/client.py,sha256=-7sQ61P0SdHj-LuYq6G0u9a_IrtmcCljyDCzZPf330U,4370
|
|
20
|
-
exa_py/websets/imports/__init__.py,sha256=iEl-fZZSdcvKaqLgjMES_0RwYn7hZDCMf6BZriCrjgw,64
|
|
21
|
-
exa_py/websets/imports/client.py,sha256=nJs46hxlSkZm7qjboYHNBuJ62gLmA_Yzr9fc-NDky0Y,6795
|
|
22
|
-
exa_py/websets/items/__init__.py,sha256=DCWZJVtRmUjnMEkKdb5gW1LT9cHcb-J8lENMnyyBeKU,71
|
|
23
|
-
exa_py/websets/items/client.py,sha256=stAQ47AgkJdEsNb1E_YAXLe96VrtglOZsG79KVcy--M,3038
|
|
24
|
-
exa_py/websets/monitors/__init__.py,sha256=jfr-gq8eKVa_gNe_DEqX9XCZPbJjpOe7QpH_D4RCFJQ,122
|
|
25
|
-
exa_py/websets/monitors/client.py,sha256=fFxCSngkUPXqf9ilUMl8DaO2ihYveD-WfSoqARwf1eQ,3526
|
|
26
|
-
exa_py/websets/monitors/runs/__init__.py,sha256=TmcETf3zdQouA_vAeLiosCNL1MYJnZ0yW2sbOAjTmm8,71
|
|
27
|
-
exa_py/websets/monitors/runs/client.py,sha256=WnwcWCf7UKk68VCNUp8mRXBtlU8vglTSX-eoWVXzKIw,1229
|
|
28
|
-
exa_py/websets/searches/__init__.py,sha256=_0Zx8ES5fFTEL3T8mhLxq_xK2t0JONx6ad6AtbvClsE,77
|
|
29
|
-
exa_py/websets/searches/client.py,sha256=X3f7axWGfecmxf-2tBTX0Yf_--xToz1X8ZHbbudEzy0,1790
|
|
30
|
-
exa_py/websets/types.py,sha256=iDZqvt22hjhkU8_AIczQ9iHexUw9C4PHh7C66ujfhk4,50523
|
|
31
|
-
exa_py/websets/webhooks/__init__.py,sha256=iTPBCxFd73z4RifLQMX6iRECx_6pwlI5qscLNjMOUHE,77
|
|
32
|
-
exa_py/websets/webhooks/client.py,sha256=zS1eoWKliuiY4AIeFJdpAlPZeOINyphn7KEWANF-zaE,4384
|
|
33
|
-
exa_py-1.15.1.dist-info/METADATA,sha256=6MtMgPdsfzWgOKeQtywu4aZASbZjYpetbiirn17CzjE,3826
|
|
34
|
-
exa_py-1.15.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
35
|
-
exa_py-1.15.1.dist-info/RECORD,,
|
|
File without changes
|