exa-py 1.8.9__py3-none-any.whl → 1.9.1__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 +59 -8
- exa_py/websets/__init__.py +5 -0
- exa_py/websets/_generator/pydantic/BaseModel.jinja2 +42 -0
- exa_py/websets/client.py +126 -0
- exa_py/websets/core/__init__.py +9 -0
- exa_py/websets/core/base.py +41 -0
- exa_py/websets/enrichments/__init__.py +3 -0
- exa_py/websets/enrichments/client.py +65 -0
- exa_py/websets/items/__init__.py +3 -0
- exa_py/websets/items/client.py +78 -0
- exa_py/websets/searches/__init__.py +3 -0
- exa_py/websets/searches/client.py +52 -0
- exa_py/websets/types.py +1054 -0
- exa_py/websets/webhooks/__init__.py +3 -0
- exa_py/websets/webhooks/client.py +80 -0
- {exa_py-1.8.9.dist-info → exa_py-1.9.1.dist-info}/METADATA +13 -13
- exa_py-1.9.1.dist-info/RECORD +21 -0
- {exa_py-1.8.9.dist-info → exa_py-1.9.1.dist-info}/WHEEL +1 -2
- exa_py-1.8.9.dist-info/RECORD +0 -8
- exa_py-1.8.9.dist-info/top_level.txt +0 -1
exa_py/api.py
CHANGED
|
@@ -34,6 +34,7 @@ from exa_py.utils import (
|
|
|
34
34
|
format_exa_result,
|
|
35
35
|
maybe_get_query,
|
|
36
36
|
)
|
|
37
|
+
from .websets import WebsetsClient
|
|
37
38
|
|
|
38
39
|
is_beta = os.getenv("IS_BETA") == "True"
|
|
39
40
|
|
|
@@ -47,6 +48,12 @@ def snake_to_camel(snake_str: str) -> str:
|
|
|
47
48
|
Returns:
|
|
48
49
|
str: The string converted to camelCase format.
|
|
49
50
|
"""
|
|
51
|
+
# Handle special cases where the field should start with non-alphanumeric characters
|
|
52
|
+
if snake_str == "schema_":
|
|
53
|
+
return "$schema"
|
|
54
|
+
if snake_str == "not_":
|
|
55
|
+
return "not"
|
|
56
|
+
|
|
50
57
|
components = snake_str.split("_")
|
|
51
58
|
return components[0] + "".join(x.title() for x in components[1:])
|
|
52
59
|
|
|
@@ -247,15 +254,38 @@ class HighlightsContentsOptions(TypedDict, total=False):
|
|
|
247
254
|
highlights_per_url: int
|
|
248
255
|
|
|
249
256
|
|
|
257
|
+
class JSONSchema(TypedDict, total=False):
|
|
258
|
+
"""Represents a JSON Schema definition used for structured summary output.
|
|
259
|
+
To learn more visit https://json-schema.org/overview/what-is-jsonschema.
|
|
260
|
+
"""
|
|
261
|
+
schema_: str # This will be converted to "$schema" in JSON
|
|
262
|
+
title: str
|
|
263
|
+
description: str
|
|
264
|
+
type: Literal["object", "array", "string", "number", "boolean", "null", "integer"]
|
|
265
|
+
properties: Dict[str, JSONSchema]
|
|
266
|
+
items: Union[JSONSchema, List[JSONSchema]]
|
|
267
|
+
required: List[str]
|
|
268
|
+
enum: List
|
|
269
|
+
additionalProperties: Union[bool, JSONSchema]
|
|
270
|
+
definitions: Dict[str, JSONSchema]
|
|
271
|
+
patternProperties: Dict[str, JSONSchema]
|
|
272
|
+
allOf: List[JSONSchema]
|
|
273
|
+
anyOf: List[JSONSchema]
|
|
274
|
+
oneOf: List[JSONSchema]
|
|
275
|
+
not_: JSONSchema # This will be converted to "not" in JSON
|
|
276
|
+
|
|
277
|
+
|
|
250
278
|
class SummaryContentsOptions(TypedDict, total=False):
|
|
251
279
|
"""A class representing the options that you can specify when requesting summary
|
|
252
280
|
|
|
253
281
|
Attributes:
|
|
254
282
|
query (str): The query string for the summary. Summary will bias towards answering the query.
|
|
283
|
+
schema (JSONSchema): JSON schema for structured output from summary.
|
|
255
284
|
"""
|
|
256
285
|
|
|
257
286
|
query: str
|
|
258
|
-
|
|
287
|
+
schema: JSONSchema
|
|
288
|
+
|
|
259
289
|
|
|
260
290
|
class ExtrasOptions(TypedDict, total=False):
|
|
261
291
|
"""A class representing additional extraction fields (e.g. links, images)"""
|
|
@@ -759,7 +789,7 @@ class Exa:
|
|
|
759
789
|
self,
|
|
760
790
|
api_key: Optional[str],
|
|
761
791
|
base_url: str = "https://api.exa.ai",
|
|
762
|
-
user_agent: str = "exa-py 1.
|
|
792
|
+
user_agent: str = "exa-py 1.9.1",
|
|
763
793
|
):
|
|
764
794
|
"""Initialize the Exa client with the provided API key and optional base URL and user agent.
|
|
765
795
|
|
|
@@ -777,13 +807,16 @@ class Exa:
|
|
|
777
807
|
)
|
|
778
808
|
self.base_url = base_url
|
|
779
809
|
self.headers = {"x-api-key": api_key, "User-Agent": user_agent}
|
|
810
|
+
self.websets = WebsetsClient(self)
|
|
780
811
|
|
|
781
|
-
def request(self, endpoint: str, data):
|
|
782
|
-
"""Send a
|
|
812
|
+
def request(self, endpoint: str, data=None, method="POST", params=None):
|
|
813
|
+
"""Send a request to the Exa API, optionally streaming if data['stream'] is True.
|
|
783
814
|
|
|
784
815
|
Args:
|
|
785
816
|
endpoint (str): The API endpoint (path).
|
|
786
|
-
data (dict): The JSON payload to send.
|
|
817
|
+
data (dict, optional): The JSON payload to send. Defaults to None.
|
|
818
|
+
method (str, optional): The HTTP method to use. Defaults to "POST".
|
|
819
|
+
params (dict, optional): Query parameters to include. Defaults to None.
|
|
787
820
|
|
|
788
821
|
Returns:
|
|
789
822
|
Union[dict, requests.Response]: If streaming, returns the Response object.
|
|
@@ -792,14 +825,32 @@ class Exa:
|
|
|
792
825
|
Raises:
|
|
793
826
|
ValueError: If the request fails (non-200 status code).
|
|
794
827
|
"""
|
|
795
|
-
if data.get("stream"):
|
|
828
|
+
if data and data.get("stream"):
|
|
796
829
|
res = requests.post(
|
|
797
830
|
self.base_url + endpoint, json=data, headers=self.headers, stream=True
|
|
798
831
|
)
|
|
799
832
|
return res
|
|
800
833
|
|
|
801
|
-
|
|
802
|
-
|
|
834
|
+
if method.upper() == "GET":
|
|
835
|
+
res = requests.get(
|
|
836
|
+
self.base_url + endpoint, headers=self.headers, params=params
|
|
837
|
+
)
|
|
838
|
+
elif method.upper() == "POST":
|
|
839
|
+
res = requests.post(
|
|
840
|
+
self.base_url + endpoint, json=data, headers=self.headers
|
|
841
|
+
)
|
|
842
|
+
elif method.upper() == "PATCH":
|
|
843
|
+
res = requests.patch(
|
|
844
|
+
self.base_url + endpoint, json=data, headers=self.headers
|
|
845
|
+
)
|
|
846
|
+
elif method.upper() == "DELETE":
|
|
847
|
+
res = requests.delete(
|
|
848
|
+
self.base_url + endpoint, headers=self.headers
|
|
849
|
+
)
|
|
850
|
+
else:
|
|
851
|
+
raise ValueError(f"Unsupported HTTP method: {method}")
|
|
852
|
+
|
|
853
|
+
if res.status_code >= 400:
|
|
803
854
|
raise ValueError(
|
|
804
855
|
f"Request failed with status code {res.status_code}: {res.text}"
|
|
805
856
|
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{% for decorator in decorators -%}
|
|
2
|
+
{{ decorator }}
|
|
3
|
+
{% endfor -%}
|
|
4
|
+
class {{ class_name }}({{ base_class }}):{% if comment is defined %} # {{ comment }}{% endif %}
|
|
5
|
+
{%- if description %}
|
|
6
|
+
"""
|
|
7
|
+
{{ description | indent(4) }}
|
|
8
|
+
"""
|
|
9
|
+
{%- endif %}
|
|
10
|
+
{%- if not fields and not description %}
|
|
11
|
+
pass
|
|
12
|
+
{%- endif %}
|
|
13
|
+
{%- if config %}
|
|
14
|
+
{%- filter indent(4) %}
|
|
15
|
+
{%- endfilter %}
|
|
16
|
+
{%- endif %}
|
|
17
|
+
{%- for field in fields -%}
|
|
18
|
+
{%- if field.name == "type" and field.field %}
|
|
19
|
+
type: Literal['{{ field.default }}']
|
|
20
|
+
{%- elif field.name == "object" and field.field %}
|
|
21
|
+
object: Literal['{{ field.default }}']
|
|
22
|
+
{%- elif not field.annotated and field.field %}
|
|
23
|
+
{{ field.name }}: {{ field.type_hint }} = {{ field.field }}
|
|
24
|
+
{%- else %}
|
|
25
|
+
{%- if field.annotated %}
|
|
26
|
+
{{ field.name }}: {{ field.annotated }}
|
|
27
|
+
{%- else %}
|
|
28
|
+
{{ field.name }}: {{ field.type_hint }}
|
|
29
|
+
{%- endif %}
|
|
30
|
+
{%- if not (field.required or (field.represented_default == 'None' and field.strip_default_none)) or field.data_type.is_optional
|
|
31
|
+
%} = {{ field.represented_default }}
|
|
32
|
+
{%- endif -%}
|
|
33
|
+
{%- endif %}
|
|
34
|
+
{%- if field.docstring %}
|
|
35
|
+
"""
|
|
36
|
+
{{ field.docstring | indent(4) }}
|
|
37
|
+
"""
|
|
38
|
+
{%- endif %}
|
|
39
|
+
{%- for method in methods -%}
|
|
40
|
+
{{ method }}
|
|
41
|
+
{%- endfor -%}
|
|
42
|
+
{%- endfor -%}
|
exa_py/websets/client.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import List, Optional, Literal
|
|
6
|
+
|
|
7
|
+
from .types import (
|
|
8
|
+
Webset,
|
|
9
|
+
ListWebsetsResponse,
|
|
10
|
+
GetWebsetResponse,
|
|
11
|
+
UpdateWebsetRequest,
|
|
12
|
+
WebsetStatus,
|
|
13
|
+
CreateWebsetParameters,
|
|
14
|
+
)
|
|
15
|
+
from .core.base import WebsetsBaseClient
|
|
16
|
+
from .items import WebsetItemsClient
|
|
17
|
+
from .searches import WebsetSearchesClient
|
|
18
|
+
from .enrichments import WebsetEnrichmentsClient
|
|
19
|
+
from .webhooks import WebsetWebhooksClient
|
|
20
|
+
|
|
21
|
+
class WebsetsClient(WebsetsBaseClient):
|
|
22
|
+
"""Client for managing Websets."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, client):
|
|
25
|
+
super().__init__(client)
|
|
26
|
+
self.items = WebsetItemsClient(client)
|
|
27
|
+
self.searches = WebsetSearchesClient(client)
|
|
28
|
+
self.enrichments = WebsetEnrichmentsClient(client)
|
|
29
|
+
self.webhooks = WebsetWebhooksClient(client)
|
|
30
|
+
|
|
31
|
+
def create(self, params: CreateWebsetParameters) -> Webset:
|
|
32
|
+
"""Create a new Webset.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
params (CreateWebsetRequest): The parameters for creating a webset.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Webset: The created webset.
|
|
39
|
+
"""
|
|
40
|
+
response = self.request("/v0/websets", data=params.model_dump(by_alias=True, exclude_none=True))
|
|
41
|
+
return Webset.model_validate(response)
|
|
42
|
+
|
|
43
|
+
def get(self, id: str, *, expand: Optional[List[Literal["items"]]] = None) -> GetWebsetResponse:
|
|
44
|
+
"""Get a Webset by ID.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
id (str): The id or externalId of the Webset.
|
|
48
|
+
expand (List[Literal["items"]], optional): Expand the response with specified resources.
|
|
49
|
+
Allowed values: ["items"]
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
GetWebsetResponse: The retrieved webset.
|
|
53
|
+
"""
|
|
54
|
+
params = {"expand": expand} if expand else {}
|
|
55
|
+
response = self.request(f"/v0/websets/{id}", params=params, method="GET")
|
|
56
|
+
return GetWebsetResponse.model_validate(response)
|
|
57
|
+
|
|
58
|
+
def list(self, *, cursor: Optional[str] = None, limit: Optional[int] = None) -> ListWebsetsResponse:
|
|
59
|
+
"""List all Websets.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
cursor (str, optional): The cursor to paginate through the results.
|
|
63
|
+
limit (int, optional): The number of results to return (max 200).
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
ListWebsetsResponse: List of websets.
|
|
67
|
+
"""
|
|
68
|
+
params = {k: v for k, v in {"cursor": cursor, "limit": limit}.items() if v is not None}
|
|
69
|
+
response = self.request("/v0/websets", params=params, method="GET")
|
|
70
|
+
return ListWebsetsResponse.model_validate(response)
|
|
71
|
+
|
|
72
|
+
def update(self, id: str, params: UpdateWebsetRequest) -> Webset:
|
|
73
|
+
"""Update a Webset.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
id (str): The id or externalId of the Webset.
|
|
77
|
+
params (UpdateWebsetRequest): The parameters for updating a webset.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Webset: The updated webset.
|
|
81
|
+
"""
|
|
82
|
+
response = self.request(f"/v0/websets/{id}", data=params.model_dump(by_alias=True, exclude_none=True), method="POST")
|
|
83
|
+
return Webset.model_validate(response)
|
|
84
|
+
|
|
85
|
+
def delete(self, id: str) -> Webset:
|
|
86
|
+
"""Delete a Webset.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
id (str): The id or externalId of the Webset.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Webset: The deleted webset.
|
|
93
|
+
"""
|
|
94
|
+
response = self.request(f"/v0/websets/{id}", method="DELETE")
|
|
95
|
+
return Webset.model_validate(response)
|
|
96
|
+
|
|
97
|
+
def cancel(self, id: str) -> Webset:
|
|
98
|
+
"""Cancel a running Webset.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
id (str): The id or externalId of the Webset.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Webset: The canceled webset.
|
|
105
|
+
"""
|
|
106
|
+
response = self.request(f"/v0/websets/{id}/cancel", method="POST")
|
|
107
|
+
return Webset.model_validate(response)
|
|
108
|
+
|
|
109
|
+
def wait_until_idle(self, id: str, *, timeout: Optional[int] = None) -> Webset:
|
|
110
|
+
"""Wait until a Webset is idle.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
id (str): The id or externalId of the Webset.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Webset: The webset.
|
|
117
|
+
"""
|
|
118
|
+
start_time = time.time()
|
|
119
|
+
while True:
|
|
120
|
+
webset = self.get(id)
|
|
121
|
+
if webset.status == WebsetStatus.idle:
|
|
122
|
+
break
|
|
123
|
+
time.sleep(1)
|
|
124
|
+
if timeout and time.time() - start_time > timeout:
|
|
125
|
+
raise Exception("Webset timed out")
|
|
126
|
+
return webset
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from ..types import *
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# Get all public names from model module that don't start with underscore
|
|
5
|
+
model_module = sys.modules[__name__]
|
|
6
|
+
__all__ = ['WebsetsBaseClient', 'ExaBaseModel'] + [
|
|
7
|
+
name for name in dir(model_module)
|
|
8
|
+
if not name.startswith('_') and name not in ('WebsetsBaseClient', 'ExaBaseModel')
|
|
9
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from pydantic import ConfigDict
|
|
5
|
+
|
|
6
|
+
from typing import Any, Dict, Optional
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
class ExaBaseModel(BaseModel):
|
|
11
|
+
"""Base model for all Exa models with common configuration."""
|
|
12
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
13
|
+
|
|
14
|
+
class WebsetsBaseClient:
|
|
15
|
+
base_url: str
|
|
16
|
+
|
|
17
|
+
"""Base client for Exa API resources."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, client):
|
|
20
|
+
"""Initialize the client.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
client: The parent Exa client.
|
|
24
|
+
"""
|
|
25
|
+
self._client = client
|
|
26
|
+
|
|
27
|
+
def request(self, endpoint: str, data: Optional[Dict[str, Any]] = None,
|
|
28
|
+
method: str = "POST", params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
29
|
+
"""Make a request to the Exa API.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
endpoint (str): The API endpoint to request.
|
|
33
|
+
data (Dict[str, Any], optional): The request data. Defaults to None.
|
|
34
|
+
method (str, optional): The HTTP method. Defaults to "POST".
|
|
35
|
+
params (Dict[str, Any], optional): The query parameters. Defaults to None.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Dict[str, Any]: The API response.
|
|
39
|
+
"""
|
|
40
|
+
return self._client.request("/websets/" + endpoint, data=data, method=method, params=params)
|
|
41
|
+
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ..types import (
|
|
4
|
+
CreateEnrichmentParameters,
|
|
5
|
+
WebsetEnrichment,
|
|
6
|
+
)
|
|
7
|
+
from ..core.base import WebsetsBaseClient
|
|
8
|
+
|
|
9
|
+
class WebsetEnrichmentsClient(WebsetsBaseClient):
|
|
10
|
+
"""Client for managing Webset Enrichments."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, client):
|
|
13
|
+
super().__init__(client)
|
|
14
|
+
|
|
15
|
+
def create(self, webset_id: str, params: CreateEnrichmentParameters) -> WebsetEnrichment:
|
|
16
|
+
"""Create an Enrichment for a Webset.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
webset_id (str): The id of the Webset.
|
|
20
|
+
params (CreateEnrichmentParameters): The parameters for creating an enrichment.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
WebsetEnrichment: The created enrichment.
|
|
24
|
+
"""
|
|
25
|
+
response = self.request(f"/v0/websets/{webset_id}/enrichments", data=params.model_dump(by_alias=True, exclude_none=True))
|
|
26
|
+
return WebsetEnrichment.model_validate(response)
|
|
27
|
+
|
|
28
|
+
def get(self, webset_id: str, id: str) -> WebsetEnrichment:
|
|
29
|
+
"""Get an Enrichment by ID.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
webset_id (str): The id of the Webset.
|
|
33
|
+
id (str): The id of the Enrichment.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
WebsetEnrichment: The retrieved enrichment.
|
|
37
|
+
"""
|
|
38
|
+
response = self.request(f"/v0/websets/{webset_id}/enrichments/{id}", method="GET")
|
|
39
|
+
return WebsetEnrichment.model_validate(response)
|
|
40
|
+
|
|
41
|
+
def delete(self, webset_id: str, id: str) -> WebsetEnrichment:
|
|
42
|
+
"""Delete an Enrichment.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
webset_id (str): The id of the Webset.
|
|
46
|
+
id (str): The id of the Enrichment.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
WebsetEnrichment: The deleted enrichment.
|
|
50
|
+
"""
|
|
51
|
+
response = self.request(f"/v0/websets/{webset_id}/enrichments/{id}", method="DELETE")
|
|
52
|
+
return WebsetEnrichment.model_validate(response)
|
|
53
|
+
|
|
54
|
+
def cancel(self, webset_id: str, id: str) -> WebsetEnrichment:
|
|
55
|
+
"""Cancel a running Enrichment.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
webset_id (str): The id of the Webset.
|
|
59
|
+
id (str): The id of the Enrichment.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
WebsetEnrichment: The canceled enrichment.
|
|
63
|
+
"""
|
|
64
|
+
response = self.request(f"/v0/websets/{webset_id}/enrichments/{id}/cancel", method="POST")
|
|
65
|
+
return WebsetEnrichment.model_validate(response)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional, Iterator
|
|
4
|
+
|
|
5
|
+
from ..types import (
|
|
6
|
+
WebsetItem,
|
|
7
|
+
ListWebsetItemResponse,
|
|
8
|
+
)
|
|
9
|
+
from ..core.base import WebsetsBaseClient
|
|
10
|
+
|
|
11
|
+
class WebsetItemsClient(WebsetsBaseClient):
|
|
12
|
+
"""Client for managing Webset Items."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, client):
|
|
15
|
+
super().__init__(client)
|
|
16
|
+
|
|
17
|
+
def list(self, webset_id: str, *, cursor: Optional[str] = None,
|
|
18
|
+
limit: Optional[int] = None) -> ListWebsetItemResponse:
|
|
19
|
+
"""List all Items for a Webset.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
webset_id (str): The id or externalId of the Webset.
|
|
23
|
+
cursor (str, optional): The cursor to paginate through the results.
|
|
24
|
+
limit (int, optional): The number of results to return (max 200).
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
ListWebsetItemResponse: List of webset items.
|
|
28
|
+
"""
|
|
29
|
+
params = {k: v for k, v in {"cursor": cursor, "limit": limit}.items() if v is not None}
|
|
30
|
+
response = self.request(f"/v0/websets/{webset_id}/items", params=params, method="GET")
|
|
31
|
+
return ListWebsetItemResponse.model_validate(response)
|
|
32
|
+
|
|
33
|
+
def list_all(self, webset_id: str, *, limit: Optional[int] = None) -> Iterator[WebsetItem]:
|
|
34
|
+
"""Iterate through all Items in a Webset, handling pagination automatically.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
webset_id (str): The id or externalId of the Webset.
|
|
38
|
+
limit (int, optional): The number of results to return per page (max 200).
|
|
39
|
+
|
|
40
|
+
Yields:
|
|
41
|
+
WebsetItem: Each item in the webset.
|
|
42
|
+
"""
|
|
43
|
+
cursor = None
|
|
44
|
+
while True:
|
|
45
|
+
response = self.list(webset_id, cursor=cursor, limit=limit)
|
|
46
|
+
for item in response.data:
|
|
47
|
+
yield item
|
|
48
|
+
|
|
49
|
+
if not response.has_more or not response.next_cursor:
|
|
50
|
+
break
|
|
51
|
+
|
|
52
|
+
cursor = response.next_cursor
|
|
53
|
+
|
|
54
|
+
def get(self, webset_id: str, id: str) -> WebsetItem:
|
|
55
|
+
"""Get an Item by ID.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
webset_id (str): The id or externalId of the Webset.
|
|
59
|
+
id (str): The id of the Webset item.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
WebsetItem: The retrieved item.
|
|
63
|
+
"""
|
|
64
|
+
response = self.request(f"/v0/websets/{webset_id}/items/{id}", method="GET")
|
|
65
|
+
return WebsetItem.model_validate(response)
|
|
66
|
+
|
|
67
|
+
def delete(self, webset_id: str, id: str) -> WebsetItem:
|
|
68
|
+
"""Delete an Item.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
webset_id (str): The id or externalId of the Webset.
|
|
72
|
+
id (str): The id of the Webset item.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
WebsetItem: The deleted item.
|
|
76
|
+
"""
|
|
77
|
+
response = self.request(f"/v0/websets/{webset_id}/items/{id}", method="DELETE")
|
|
78
|
+
return WebsetItem.model_validate(response)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ..types import (
|
|
4
|
+
CreateWebsetSearchParameters,
|
|
5
|
+
WebsetSearch,
|
|
6
|
+
)
|
|
7
|
+
from ..core.base import WebsetsBaseClient
|
|
8
|
+
|
|
9
|
+
class WebsetSearchesClient(WebsetsBaseClient):
|
|
10
|
+
"""Client for managing Webset Searches."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, client):
|
|
13
|
+
super().__init__(client)
|
|
14
|
+
|
|
15
|
+
def create(self, webset_id: str, params: CreateWebsetSearchParameters) -> WebsetSearch:
|
|
16
|
+
"""Create a new Search for the Webset.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
webset_id (str): The id of the Webset.
|
|
20
|
+
params (CreateWebsetSearchParameters): The parameters for creating a search.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
WebsetSearch: The created search.
|
|
24
|
+
"""
|
|
25
|
+
response = self.request(f"/v0/websets/{webset_id}/searches", data=params.model_dump(by_alias=True, exclude_none=True))
|
|
26
|
+
return WebsetSearch.model_validate(response)
|
|
27
|
+
|
|
28
|
+
def get(self, webset_id: str, id: str) -> WebsetSearch:
|
|
29
|
+
"""Get a Search by ID.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
webset_id (str): The id of the Webset.
|
|
33
|
+
id (str): The id of the Search.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
WebsetSearch: The retrieved search.
|
|
37
|
+
"""
|
|
38
|
+
response = self.request(f"/v0/websets/{webset_id}/searches/{id}", method="GET")
|
|
39
|
+
return WebsetSearch.model_validate(response)
|
|
40
|
+
|
|
41
|
+
def cancel(self, webset_id: str, id: str) -> WebsetSearch:
|
|
42
|
+
"""Cancel a running Search.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
webset_id (str): The id of the Webset.
|
|
46
|
+
id (str): The id of the Search.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
WebsetSearch: The canceled search.
|
|
50
|
+
"""
|
|
51
|
+
response = self.request(f"/v0/websets/{webset_id}/searches/{id}/cancel", method="POST")
|
|
52
|
+
return WebsetSearch.model_validate(response)
|