ateve 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {ateve-0.2.0 → ateve-0.2.2}/PKG-INFO +29 -17
- {ateve-0.2.0 → ateve-0.2.2}/README.md +28 -16
- {ateve-0.2.0 → ateve-0.2.2}/pyproject.toml +1 -1
- ateve-0.2.2/src/ateve/_version.py +1 -0
- {ateve-0.2.0 → ateve-0.2.2}/src/ateve/models.py +2 -1
- {ateve-0.2.0 → ateve-0.2.2}/tests/test_client.py +12 -6
- {ateve-0.2.0 → ateve-0.2.2}/tests/test_models.py +26 -5
- ateve-0.2.0/src/ateve/_version.py +0 -1
- {ateve-0.2.0 → ateve-0.2.2}/.generated-models.json +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/.gitignore +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/.turbo/turbo-build.log +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/.turbo/turbo-check.log +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/src/ateve/__init__.py +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/src/ateve/_model_exports.py +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/src/ateve/client.py +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/src/ateve/errors.py +0 -0
- {ateve-0.2.0 → ateve-0.2.2}/src/ateve/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ateve
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Official Python SDK for the Ateve Search API
|
|
5
5
|
Project-URL: Homepage, https://ateve.ai
|
|
6
6
|
Project-URL: Documentation, https://ateve.ai/docs
|
|
@@ -81,20 +81,32 @@ decisions remain caller-owned.
|
|
|
81
81
|
|
|
82
82
|
## Search contract limits
|
|
83
83
|
|
|
84
|
-
Use `max_results` (1–100, default 10)
|
|
85
|
-
`
|
|
86
|
-
|
|
84
|
+
Use `max_results` to set the maximum number of results (1–100, default 10).
|
|
85
|
+
`limit` and `offset` have been removed. Both synchronous and asynchronous
|
|
86
|
+
clients accept `content` and `max_results`, or a `SearchRequest` instance.
|
|
87
|
+
|
|
88
|
+
Snippets are always returned and cannot be disabled. To request full text, pass
|
|
89
|
+
`content=ContentOptions(text=TextOptions())`. To customize the output, use
|
|
87
90
|
`TextOptions(max_characters=8000, format=ContentFormat.MARKDOWN)`.
|
|
88
|
-
`format` accepts `
|
|
89
|
-
|
|
90
|
-
integer
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
91
|
+
`format` accepts `ContentFormat.TEXT` (default) or `ContentFormat.MARKDOWN`.
|
|
92
|
+
Full text is requested only when `text` is supplied. `max_characters` must be a
|
|
93
|
+
strict positive signed 32-bit integer. The server default is 5,000 characters
|
|
94
|
+
per result, applied after format conversion. Both formats return content in
|
|
95
|
+
`SearchResult.text`, which is `None` when absent or when extraction fails.
|
|
96
|
+
`model_fields_set` distinguishes those cases. Full text is returned alongside
|
|
97
|
+
snippets.
|
|
98
|
+
|
|
99
|
+
Highlights are optional and disabled by default. Set
|
|
100
|
+
`content=ContentOptions(highlights=True)` to return concise, query-relevant
|
|
101
|
+
excerpts in addition to snippets. `SearchResult.highlights` is a `list[str]`, or
|
|
102
|
+
`None` when the field is absent. Highlights can coexist with snippets and full text.
|
|
103
|
+
|
|
104
|
+
For token-efficient workflows, your agent can prioritize highlights when building
|
|
105
|
+
model context and supplement them with snippets when additional context is needed.
|
|
106
|
+
When the API returns both fields, token savings depend on which content your
|
|
107
|
+
agent passes to the model.
|
|
108
|
+
|
|
109
|
+
`summary` and the snippet toggle have been removed from `ContentOptions`.
|
|
110
|
+
`favicon` remains optional under `content`. Obsolete answer, usage, news/video,
|
|
111
|
+
query tuning, and raw content/summary response fields and models have been removed.
|
|
112
|
+
Unknown response fields continue to be retained by Pydantic for forward compatibility.
|
|
@@ -55,20 +55,32 @@ decisions remain caller-owned.
|
|
|
55
55
|
|
|
56
56
|
## Search contract limits
|
|
57
57
|
|
|
58
|
-
Use `max_results` (1–100, default 10)
|
|
59
|
-
`
|
|
60
|
-
|
|
58
|
+
Use `max_results` to set the maximum number of results (1–100, default 10).
|
|
59
|
+
`limit` and `offset` have been removed. Both synchronous and asynchronous
|
|
60
|
+
clients accept `content` and `max_results`, or a `SearchRequest` instance.
|
|
61
|
+
|
|
62
|
+
Snippets are always returned and cannot be disabled. To request full text, pass
|
|
63
|
+
`content=ContentOptions(text=TextOptions())`. To customize the output, use
|
|
61
64
|
`TextOptions(max_characters=8000, format=ContentFormat.MARKDOWN)`.
|
|
62
|
-
`format` accepts `
|
|
63
|
-
|
|
64
|
-
integer
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
`format` accepts `ContentFormat.TEXT` (default) or `ContentFormat.MARKDOWN`.
|
|
66
|
+
Full text is requested only when `text` is supplied. `max_characters` must be a
|
|
67
|
+
strict positive signed 32-bit integer. The server default is 5,000 characters
|
|
68
|
+
per result, applied after format conversion. Both formats return content in
|
|
69
|
+
`SearchResult.text`, which is `None` when absent or when extraction fails.
|
|
70
|
+
`model_fields_set` distinguishes those cases. Full text is returned alongside
|
|
71
|
+
snippets.
|
|
72
|
+
|
|
73
|
+
Highlights are optional and disabled by default. Set
|
|
74
|
+
`content=ContentOptions(highlights=True)` to return concise, query-relevant
|
|
75
|
+
excerpts in addition to snippets. `SearchResult.highlights` is a `list[str]`, or
|
|
76
|
+
`None` when the field is absent. Highlights can coexist with snippets and full text.
|
|
77
|
+
|
|
78
|
+
For token-efficient workflows, your agent can prioritize highlights when building
|
|
79
|
+
model context and supplement them with snippets when additional context is needed.
|
|
80
|
+
When the API returns both fields, token savings depend on which content your
|
|
81
|
+
agent passes to the model.
|
|
82
|
+
|
|
83
|
+
`summary` and the snippet toggle have been removed from `ContentOptions`.
|
|
84
|
+
`favicon` remains optional under `content`. Obsolete answer, usage, news/video,
|
|
85
|
+
query tuning, and raw content/summary response fields and models have been removed.
|
|
86
|
+
Unknown response fields continue to be retained by Pydantic for forward compatibility.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.2"
|
|
@@ -87,7 +87,7 @@ class TextOptions(RequestModel):
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
class ContentOptions(RequestModel):
|
|
90
|
-
|
|
90
|
+
highlights: Optional[bool] = Field(default=False)
|
|
91
91
|
text: Optional[TextOptions] = None
|
|
92
92
|
favicon: Optional[bool] = None
|
|
93
93
|
|
|
@@ -144,6 +144,7 @@ class SearchResult(ResponseModel):
|
|
|
144
144
|
published_at: Optional[datetime] = None
|
|
145
145
|
score: Optional[float] = None
|
|
146
146
|
snippet: Optional[str] = None
|
|
147
|
+
highlights: Optional[List[str]] = None
|
|
147
148
|
text: Optional[str] = None
|
|
148
149
|
favicon: Optional[str] = None
|
|
149
150
|
images: List[ImageItem] = Field(default_factory=list)
|
|
@@ -57,7 +57,8 @@ def test_sync_golden_contract_and_wire_names() -> None:
|
|
|
57
57
|
date_range="2026-01-01..2026-06-30",
|
|
58
58
|
locale=LocaleSettings(mkt="US", language="en"),
|
|
59
59
|
content=ContentOptions(
|
|
60
|
-
|
|
60
|
+
highlights=True,
|
|
61
|
+
text=TextOptions(format=ContentFormat.MARKDOWN, max_characters=5000)
|
|
61
62
|
),
|
|
62
63
|
safe_search=False,
|
|
63
64
|
)
|
|
@@ -66,7 +67,8 @@ def test_sync_golden_contract_and_wire_names() -> None:
|
|
|
66
67
|
assert payload["date_range"] == "2026-01-01..2026-06-30"
|
|
67
68
|
assert payload["safe_search"] is False
|
|
68
69
|
assert payload["max_results"] == 20
|
|
69
|
-
assert payload["content"]
|
|
70
|
+
assert "snippet" not in payload["content"]
|
|
71
|
+
assert payload["content"]["highlights"] is True
|
|
70
72
|
assert not {"limit", "offset", "contents"}.intersection(payload)
|
|
71
73
|
assert payload["content"]["text"]["max_characters"] == 5000
|
|
72
74
|
assert "images" not in payload["content"]
|
|
@@ -77,6 +79,7 @@ def test_sync_golden_contract_and_wire_names() -> None:
|
|
|
77
79
|
assert captured[0].headers["User-Agent"] == f"ateve-python/{__version__}"
|
|
78
80
|
assert response.id == "req_01J9ZK3V6XQ8"
|
|
79
81
|
assert response.results[0].published_at is not None
|
|
82
|
+
assert response.results[0].highlights == GOLDEN_RESPONSE["results"][0]["highlights"]
|
|
80
83
|
assert response.query.original == "climate policy analysis"
|
|
81
84
|
assert response.total_estimated_matches == 128000
|
|
82
85
|
|
|
@@ -341,7 +344,10 @@ def test_sync_and_async_send_new_defaults_and_nested_text_options() -> None:
|
|
|
341
344
|
httpx.AsyncClient(transport=httpx.MockTransport(handler)) as transport,
|
|
342
345
|
AsyncAteve("sk_test", http_client=transport) as client,
|
|
343
346
|
):
|
|
344
|
-
await client.search(
|
|
347
|
+
response = await client.search(
|
|
348
|
+
"q", max_results=100, content=ContentOptions(highlights=True)
|
|
349
|
+
)
|
|
350
|
+
assert response.results[0].highlights == GOLDEN_RESPONSE["results"][0]["highlights"]
|
|
345
351
|
await client.search(
|
|
346
352
|
SearchRequest(query="q", content=ContentOptions(text=TextOptions()))
|
|
347
353
|
)
|
|
@@ -352,12 +358,12 @@ def test_sync_and_async_send_new_defaults_and_nested_text_options() -> None:
|
|
|
352
358
|
{
|
|
353
359
|
"query": "q",
|
|
354
360
|
"max_results": 10,
|
|
355
|
-
"content": {"
|
|
361
|
+
"content": {"highlights": False, "text": {"format": "text"}},
|
|
356
362
|
},
|
|
357
|
-
{"query": "q", "max_results": 100, "content": {"
|
|
363
|
+
{"query": "q", "max_results": 100, "content": {"highlights": True}},
|
|
358
364
|
{
|
|
359
365
|
"query": "q",
|
|
360
366
|
"max_results": 10,
|
|
361
|
-
"content": {"
|
|
367
|
+
"content": {"highlights": False, "text": {"format": "text"}},
|
|
362
368
|
},
|
|
363
369
|
]
|
|
@@ -25,6 +25,8 @@ def test_request_models_preserve_validation_and_frozen_configuration() -> None:
|
|
|
25
25
|
request.query = "changed"
|
|
26
26
|
with pytest.raises(ValidationError):
|
|
27
27
|
TextOptions(max_characters=True)
|
|
28
|
+
with pytest.raises(ValidationError, match="snippet"):
|
|
29
|
+
ContentOptions.model_validate({"snippet": False})
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def test_response_models_preserve_defaults_nulls_extra_fields_and_dates() -> None:
|
|
@@ -54,16 +56,31 @@ def test_request_lists_are_snapshots_and_wire_names_stay_snake_case() -> None:
|
|
|
54
56
|
|
|
55
57
|
def test_request_defaults_and_nested_text_activation() -> None:
|
|
56
58
|
assert SearchRequest(query="q").max_results == 10
|
|
57
|
-
assert ContentOptions().
|
|
59
|
+
assert ContentOptions().highlights is False
|
|
58
60
|
assert ContentOptions().text is None
|
|
59
61
|
assert TextOptions().format == ContentFormat.TEXT
|
|
60
62
|
request = SearchRequest(query="q", content=ContentOptions(text=TextOptions()))
|
|
61
63
|
assert request.model_dump(mode="json", exclude_none=True) == {
|
|
62
64
|
"query": "q",
|
|
63
65
|
"max_results": 10,
|
|
64
|
-
"content": {"
|
|
66
|
+
"content": {"highlights": False, "text": {"format": "text"}},
|
|
65
67
|
}
|
|
66
|
-
assert ContentOptions(
|
|
68
|
+
assert ContentOptions(highlights=True).highlights is True
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_highlights_are_typed_and_preserve_missing_and_empty_values() -> None:
|
|
72
|
+
missing = SearchResult()
|
|
73
|
+
assert missing.highlights is None
|
|
74
|
+
assert "highlights" not in missing.model_fields_set
|
|
75
|
+
result = SearchResult(snippet="excerpt", highlights=["Answer support", "Further evidence"])
|
|
76
|
+
assert result.snippet == "excerpt"
|
|
77
|
+
assert result.highlights == ["Answer support", "Further evidence"]
|
|
78
|
+
assert result.model_extra == {}
|
|
79
|
+
assert SearchResult(highlights=[]).highlights == []
|
|
80
|
+
with pytest.raises(ValidationError):
|
|
81
|
+
SearchResult.model_validate({"highlights": "excerpt"})
|
|
82
|
+
with pytest.raises(ValidationError):
|
|
83
|
+
SearchResult.model_validate({"highlights": [1]})
|
|
67
84
|
|
|
68
85
|
|
|
69
86
|
@pytest.mark.parametrize("value", [0, -1, 101])
|
|
@@ -87,7 +104,6 @@ def test_removed_request_fields_and_invalid_text_options_are_rejected() -> None:
|
|
|
87
104
|
SearchRequest.model_validate({"query": "q", name: value})
|
|
88
105
|
for name, value in [
|
|
89
106
|
("summary", True),
|
|
90
|
-
("highlights", True),
|
|
91
107
|
("raw_content", True),
|
|
92
108
|
("max_characters", 100),
|
|
93
109
|
("format", "text"),
|
|
@@ -99,7 +115,10 @@ def test_removed_request_fields_and_invalid_text_options_are_rejected() -> None:
|
|
|
99
115
|
ContentOptions.model_validate({"text": value})
|
|
100
116
|
|
|
101
117
|
|
|
102
|
-
@pytest.mark.parametrize("scenario", [
|
|
118
|
+
@pytest.mark.parametrize("scenario", [
|
|
119
|
+
"default", "text", "markdown", "no-snippet",
|
|
120
|
+
"highlights", "highlights-no-snippet", "highlights-markdown",
|
|
121
|
+
])
|
|
103
122
|
def test_captured_live_responses_preserve_missing_and_null_text(scenario: str) -> None:
|
|
104
123
|
fixture = (
|
|
105
124
|
Path(__file__).resolve().parents[2] / f"contract/fixtures/live-{scenario}-response.json"
|
|
@@ -112,8 +131,10 @@ def test_captured_live_responses_preserve_missing_and_null_text(scenario: str) -
|
|
|
112
131
|
for result, raw in zip(response.results, wire["results"], strict=True):
|
|
113
132
|
assert result.text == raw.get("text")
|
|
114
133
|
assert result.snippet == raw.get("snippet")
|
|
134
|
+
assert result.highlights == raw.get("highlights")
|
|
115
135
|
assert ("text" in result.model_fields_set) == ("text" in raw)
|
|
116
136
|
assert ("snippet" in result.model_fields_set) == ("snippet" in raw)
|
|
137
|
+
assert ("highlights" in result.model_fields_set) == ("highlights" in raw)
|
|
117
138
|
assert result.model_extra == {}
|
|
118
139
|
if scenario in {"text", "markdown"}:
|
|
119
140
|
assert response.results[0].text is not None and len(response.results[0].text) == 300
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|