Skip to content

Commit 4185d7a

Browse files
feat(api): manual updates
1 parent da3806c commit 4185d7a

File tree

7 files changed

+102
-27
lines changed

7 files changed

+102
-27
lines changed

.stats.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 15
22
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/zeroentropy%2Fzeroentropy-f06c49dfd4b38a4f9d5bcad56348156bbf641aa8b7968acfbf655ad6ceff2126.yml
33
openapi_spec_hash: cac52dd65fbcb65ffa7a183e764b7f06
4-
config_hash: a7dc8380ffa9d78eee964a96e0eb7b54
4+
config_hash: 34c8a6deaedce51a258bc46b38c9caa0

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,77 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
8888

8989
Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.
9090

91+
## Pagination
92+
93+
List methods in the ZeroEntropy API are paginated.
94+
95+
This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
96+
97+
```python
98+
from zeroentropy import ZeroEntropy
99+
100+
client = ZeroEntropy()
101+
102+
all_documents = []
103+
# Automatically fetches more pages as needed.
104+
for document in client.documents.get_info_list(
105+
collection_name="example_collection",
106+
):
107+
# Do something with document here
108+
all_documents.append(document)
109+
print(all_documents)
110+
```
111+
112+
Or, asynchronously:
113+
114+
```python
115+
import asyncio
116+
from zeroentropy import AsyncZeroEntropy
117+
118+
client = AsyncZeroEntropy()
119+
120+
121+
async def main() -> None:
122+
all_documents = []
123+
# Iterate through items across all pages, issuing requests as needed.
124+
async for document in client.documents.get_info_list(
125+
collection_name="example_collection",
126+
):
127+
all_documents.append(document)
128+
print(all_documents)
129+
130+
131+
asyncio.run(main())
132+
```
133+
134+
Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
135+
136+
```python
137+
first_page = await client.documents.get_info_list(
138+
collection_name="example_collection",
139+
)
140+
if first_page.has_next_page():
141+
print(f"will fetch next page using these details: {first_page.next_page_info()}")
142+
next_page = await first_page.get_next_page()
143+
print(f"number of items we just fetched: {len(next_page.documents)}")
144+
145+
# Remove `await` for non-async usage.
146+
```
147+
148+
Or just work directly with the returned data:
149+
150+
```python
151+
first_page = await client.documents.get_info_list(
152+
collection_name="example_collection",
153+
)
154+
155+
print(f"next page cursor: {first_page.path_gt}") # => "next page cursor: ..."
156+
for document in first_page.documents:
157+
print(document.id)
158+
159+
# Remove `await` for non-async usage.
160+
```
161+
91162
## Handling errors
92163

93164
When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `zeroentropy.APIConnectionError` is raised.

api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Methods:
6161
- <code title="post /documents/delete-document">client.documents.<a href="./src/zeroentropy/resources/documents.py">delete</a>(\*\*<a href="src/zeroentropy/types/document_delete_params.py">params</a>) -> <a href="./src/zeroentropy/types/document_delete_response.py">DocumentDeleteResponse</a></code>
6262
- <code title="post /documents/add-document">client.documents.<a href="./src/zeroentropy/resources/documents.py">add</a>(\*\*<a href="src/zeroentropy/types/document_add_params.py">params</a>) -> <a href="./src/zeroentropy/types/document_add_response.py">DocumentAddResponse</a></code>
6363
- <code title="post /documents/get-document-info">client.documents.<a href="./src/zeroentropy/resources/documents.py">get_info</a>(\*\*<a href="src/zeroentropy/types/document_get_info_params.py">params</a>) -> <a href="./src/zeroentropy/types/document_get_info_response.py">DocumentGetInfoResponse</a></code>
64-
- <code title="post /documents/get-document-info-list">client.documents.<a href="./src/zeroentropy/resources/documents.py">get_info_list</a>(\*\*<a href="src/zeroentropy/types/document_get_info_list_params.py">params</a>) -> <a href="./src/zeroentropy/types/document_get_info_list_response.py">DocumentGetInfoListResponse</a></code>
64+
- <code title="post /documents/get-document-info-list">client.documents.<a href="./src/zeroentropy/resources/documents.py">get_info_list</a>(\*\*<a href="src/zeroentropy/types/document_get_info_list_params.py">params</a>) -> <a href="./src/zeroentropy/types/document_get_info_list_response.py">SyncGetDocumentInfoListCursor[DocumentGetInfoListResponse]</a></code>
6565
- <code title="post /documents/get-page-info">client.documents.<a href="./src/zeroentropy/resources/documents.py">get_page_info</a>(\*\*<a href="src/zeroentropy/types/document_get_page_info_params.py">params</a>) -> <a href="./src/zeroentropy/types/document_get_page_info_response.py">DocumentGetPageInfoResponse</a></code>
6666

6767
# Queries

src/zeroentropy/pagination.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def next_page_info(self) -> Optional[PageInfo]:
3636
# TODO emit warning log
3737
return None
3838

39-
return PageInfo(params={"path_gt": item.id})
39+
return PageInfo(json={"path_gt": item.id})
4040

4141

4242
class AsyncGetDocumentInfoListCursor(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
@@ -60,4 +60,4 @@ def next_page_info(self) -> Optional[PageInfo]:
6060
# TODO emit warning log
6161
return None
6262

63-
return PageInfo(params={"path_gt": item.id})
63+
return PageInfo(json={"path_gt": item.id})

src/zeroentropy/resources/documents.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
async_to_raw_response_wrapper,
2525
async_to_streamed_response_wrapper,
2626
)
27-
from .._base_client import make_request_options
27+
from ..pagination import SyncGetDocumentInfoListCursor, AsyncGetDocumentInfoListCursor
28+
from .._base_client import AsyncPaginator, make_request_options
2829
from ..types.document_add_response import DocumentAddResponse
2930
from ..types.document_delete_response import DocumentDeleteResponse
3031
from ..types.document_update_response import DocumentUpdateResponse
@@ -314,7 +315,7 @@ def get_info_list(
314315
extra_query: Query | None = None,
315316
extra_body: Body | None = None,
316317
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
317-
) -> DocumentGetInfoListResponse:
318+
) -> SyncGetDocumentInfoListCursor[DocumentGetInfoListResponse]:
318319
"""
319320
Retrives a list of document metadata information that matches the provided
320321
filters.
@@ -348,8 +349,9 @@ def get_info_list(
348349
349350
timeout: Override the client-level default timeout for this request, in seconds
350351
"""
351-
return self._post(
352+
return self._get_api_list(
352353
"/documents/get-document-info-list",
354+
page=SyncGetDocumentInfoListCursor[DocumentGetInfoListResponse],
353355
body=maybe_transform(
354356
{
355357
"collection_name": collection_name,
@@ -362,7 +364,8 @@ def get_info_list(
362364
options=make_request_options(
363365
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
364366
),
365-
cast_to=DocumentGetInfoListResponse,
367+
model=DocumentGetInfoListResponse,
368+
method="post",
366369
)
367370

368371
def get_page_info(
@@ -694,7 +697,7 @@ async def get_info(
694697
cast_to=DocumentGetInfoResponse,
695698
)
696699

697-
async def get_info_list(
700+
def get_info_list(
698701
self,
699702
*,
700703
collection_name: str,
@@ -707,7 +710,7 @@ async def get_info_list(
707710
extra_query: Query | None = None,
708711
extra_body: Body | None = None,
709712
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
710-
) -> DocumentGetInfoListResponse:
713+
) -> AsyncPaginator[DocumentGetInfoListResponse, AsyncGetDocumentInfoListCursor[DocumentGetInfoListResponse]]:
711714
"""
712715
Retrives a list of document metadata information that matches the provided
713716
filters.
@@ -741,9 +744,10 @@ async def get_info_list(
741744
742745
timeout: Override the client-level default timeout for this request, in seconds
743746
"""
744-
return await self._post(
747+
return self._get_api_list(
745748
"/documents/get-document-info-list",
746-
body=await async_maybe_transform(
749+
page=AsyncGetDocumentInfoListCursor[DocumentGetInfoListResponse],
750+
body=maybe_transform(
747751
{
748752
"collection_name": collection_name,
749753
"limit": limit,
@@ -755,7 +759,8 @@ async def get_info_list(
755759
options=make_request_options(
756760
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
757761
),
758-
cast_to=DocumentGetInfoListResponse,
762+
model=DocumentGetInfoListResponse,
763+
method="post",
759764
)
760765

761766
async def get_page_info(

src/zeroentropy/types/document_get_info_list_response.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55

66
from .._models import BaseModel
77

8-
__all__ = ["DocumentGetInfoListResponse", "Document"]
8+
__all__ = ["DocumentGetInfoListResponse"]
99

1010

11-
class Document(BaseModel):
11+
class DocumentGetInfoListResponse(BaseModel):
1212
id: str
1313

1414
collection_name: str
@@ -41,7 +41,3 @@ class Document(BaseModel):
4141

4242
size: int
4343
"""The total size of the raw document data, in bytes."""
44-
45-
46-
class DocumentGetInfoListResponse(BaseModel):
47-
documents: List[Document]

tests/api_resources/test_documents.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
DocumentGetInfoListResponse,
1818
DocumentGetPageInfoResponse,
1919
)
20+
from zeroentropy.pagination import SyncGetDocumentInfoListCursor, AsyncGetDocumentInfoListCursor
2021

2122
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
2223

@@ -209,7 +210,7 @@ def test_method_get_info_list(self, client: ZeroEntropy) -> None:
209210
document = client.documents.get_info_list(
210211
collection_name="collection_name",
211212
)
212-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
213+
assert_matches_type(SyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"])
213214

214215
@parametrize
215216
def test_method_get_info_list_with_all_params(self, client: ZeroEntropy) -> None:
@@ -219,7 +220,7 @@ def test_method_get_info_list_with_all_params(self, client: ZeroEntropy) -> None
219220
path_gt="path_gt",
220221
path_prefix="path_prefix",
221222
)
222-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
223+
assert_matches_type(SyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"])
223224

224225
@parametrize
225226
def test_raw_response_get_info_list(self, client: ZeroEntropy) -> None:
@@ -230,7 +231,7 @@ def test_raw_response_get_info_list(self, client: ZeroEntropy) -> None:
230231
assert response.is_closed is True
231232
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
232233
document = response.parse()
233-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
234+
assert_matches_type(SyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"])
234235

235236
@parametrize
236237
def test_streaming_response_get_info_list(self, client: ZeroEntropy) -> None:
@@ -241,7 +242,7 @@ def test_streaming_response_get_info_list(self, client: ZeroEntropy) -> None:
241242
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
242243

243244
document = response.parse()
244-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
245+
assert_matches_type(SyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"])
245246

246247
assert cast(Any, response.is_closed) is True
247248

@@ -481,7 +482,7 @@ async def test_method_get_info_list(self, async_client: AsyncZeroEntropy) -> Non
481482
document = await async_client.documents.get_info_list(
482483
collection_name="collection_name",
483484
)
484-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
485+
assert_matches_type(AsyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"])
485486

486487
@parametrize
487488
async def test_method_get_info_list_with_all_params(self, async_client: AsyncZeroEntropy) -> None:
@@ -491,7 +492,7 @@ async def test_method_get_info_list_with_all_params(self, async_client: AsyncZer
491492
path_gt="path_gt",
492493
path_prefix="path_prefix",
493494
)
494-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
495+
assert_matches_type(AsyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"])
495496

496497
@parametrize
497498
async def test_raw_response_get_info_list(self, async_client: AsyncZeroEntropy) -> None:
@@ -502,7 +503,7 @@ async def test_raw_response_get_info_list(self, async_client: AsyncZeroEntropy)
502503
assert response.is_closed is True
503504
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
504505
document = await response.parse()
505-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
506+
assert_matches_type(AsyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"])
506507

507508
@parametrize
508509
async def test_streaming_response_get_info_list(self, async_client: AsyncZeroEntropy) -> None:
@@ -513,7 +514,9 @@ async def test_streaming_response_get_info_list(self, async_client: AsyncZeroEnt
513514
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
514515

515516
document = await response.parse()
516-
assert_matches_type(DocumentGetInfoListResponse, document, path=["response"])
517+
assert_matches_type(
518+
AsyncGetDocumentInfoListCursor[DocumentGetInfoListResponse], document, path=["response"]
519+
)
517520

518521
assert cast(Any, response.is_closed) is True
519522

0 commit comments

Comments
 (0)