Skip to content

Commit f6e304a

Browse files
feat(api): api update
1 parent 55c65e1 commit f6e304a

31 files changed

Lines changed: 2598 additions & 291 deletions

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 2
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-4a17ecf235fd346afe631381db80e46b26346368a323939de7b0741a5b60ce3d.yml
3-
openapi_spec_hash: c46bca368a4f85e1a684b309e4129ef5
4-
config_hash: 6f0ab1fd6c4433590ee82d88ab5298a7
1+
configured_endpoints: 9
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-61ca0326580cb90b4bc39c85c49cb2083d14ce9865ea272f2cb84cc7c639b0b2.yml
3+
openapi_spec_hash: 6940490040b26eeb3c38bb2d7d9f00ce
4+
config_hash: aed0d6cc8b4cffa1f02021baec0a6da3

README.md

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

116116
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`.
117117

118+
## Pagination
119+
120+
List methods in the Docstrange API are paginated.
121+
122+
This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
123+
124+
```python
125+
from docstrange import Docstrange
126+
127+
client = Docstrange()
128+
129+
all_results = []
130+
# Automatically fetches more pages as needed.
131+
for result in client.extract.results.list():
132+
# Do something with result here
133+
all_results.append(result)
134+
print(all_results)
135+
```
136+
137+
Or, asynchronously:
138+
139+
```python
140+
import asyncio
141+
from docstrange import AsyncDocstrange
142+
143+
client = AsyncDocstrange()
144+
145+
146+
async def main() -> None:
147+
all_results = []
148+
# Iterate through items across all pages, issuing requests as needed.
149+
async for result in client.extract.results.list():
150+
all_results.append(result)
151+
print(all_results)
152+
153+
154+
asyncio.run(main())
155+
```
156+
157+
Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
158+
159+
```python
160+
first_page = await client.extract.results.list()
161+
if first_page.has_next_page():
162+
print(f"will fetch next page using these details: {first_page.next_page_info()}")
163+
next_page = await first_page.get_next_page()
164+
print(f"number of items we just fetched: {len(next_page.results)}")
165+
166+
# Remove `await` for non-async usage.
167+
```
168+
169+
Or just work directly with the returned data:
170+
171+
```python
172+
first_page = await client.extract.results.list()
173+
for result in first_page.results:
174+
print(result)
175+
176+
# Remove `await` for non-async usage.
177+
```
178+
118179
## File uploads
119180

120181
Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.

api.md

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,62 @@
33
Types:
44

55
```python
6-
from docstrange.types import ExtractResponse
6+
from docstrange.types import (
7+
BatchExtractRequestBody,
8+
BatchExtractResponse,
9+
ExtractRequestBody,
10+
ExtractResponse,
11+
StreamExtractRequestBody,
12+
ExtractStreamResponse,
13+
)
714
```
815

916
Methods:
1017

11-
- <code title="post /api/v1/extract/sync">client.extract.<a href="./src/docstrange/resources/extract.py">sync</a>(\*\*<a href="src/docstrange/types/extract_sync_params.py">params</a>) -> <a href="./src/docstrange/types/extract_response.py">ExtractResponse</a></code>
18+
- <code title="post /api/v1/extract/async">client.extract.<a href="./src/docstrange/resources/extract/extract.py">async\_</a>(\*\*<a href="src/docstrange/types/extract_async_params.py">params</a>) -> <a href="./src/docstrange/types/extract_response.py">ExtractResponse</a></code>
19+
- <code title="post /api/v1/extract/batch">client.extract.<a href="./src/docstrange/resources/extract/extract.py">batch</a>(\*\*<a href="src/docstrange/types/extract_batch_params.py">params</a>) -> <a href="./src/docstrange/types/batch_extract_response.py">BatchExtractResponse</a></code>
20+
- <code title="post /api/v1/extract/stream">client.extract.<a href="./src/docstrange/resources/extract/extract.py">stream</a>(\*\*<a href="src/docstrange/types/extract_stream_params.py">params</a>) -> str</code>
21+
- <code title="post /api/v1/extract/sync">client.extract.<a href="./src/docstrange/resources/extract/extract.py">sync</a>(\*\*<a href="src/docstrange/types/extract_sync_params.py">params</a>) -> <a href="./src/docstrange/types/extract_response.py">ExtractResponse</a></code>
22+
23+
## Results
24+
25+
Types:
26+
27+
```python
28+
from docstrange.types.extract import ExtractionListResponse
29+
```
30+
31+
Methods:
32+
33+
- <code title="get /api/v1/extract/results/{record_id}">client.extract.results.<a href="./src/docstrange/resources/extract/results.py">retrieve</a>(record_id, \*\*<a href="src/docstrange/types/extract/result_retrieve_params.py">params</a>) -> <a href="./src/docstrange/types/extract_response.py">ExtractResponse</a></code>
34+
- <code title="get /api/v1/extract/results">client.extract.results.<a href="./src/docstrange/resources/extract/results.py">list</a>(\*\*<a href="src/docstrange/types/extract/result_list_params.py">params</a>) -> SyncPageNumberPagination[object]</code>
1235

1336
# Classify
1437

1538
Types:
1639

1740
```python
18-
from docstrange.types import ClassifyResponse
41+
from docstrange.types import (
42+
BatchClassifyRequestBody,
43+
BatchClassifyResponse,
44+
ClassifyRequestBody,
45+
ClassifyResponse,
46+
)
1947
```
2048

2149
Methods:
2250

51+
- <code title="post /api/v1/classify/batch">client.classify.<a href="./src/docstrange/resources/classify.py">batch</a>(\*\*<a href="src/docstrange/types/classify_batch_params.py">params</a>) -> <a href="./src/docstrange/types/batch_classify_response.py">BatchClassifyResponse</a></code>
2352
- <code title="post /api/v1/classify/sync">client.classify.<a href="./src/docstrange/resources/classify.py">sync</a>(\*\*<a href="src/docstrange/types/classify_sync_params.py">params</a>) -> <a href="./src/docstrange/types/classify_response.py">ClassifyResponse</a></code>
53+
54+
# Chat
55+
56+
Types:
57+
58+
```python
59+
from docstrange.types import ChatCompletionsRequest
60+
```
61+
62+
Methods:
63+
64+
- <code title="post /v1/chat/completions">client.chat.<a href="./src/docstrange/resources/chat.py">create_completion</a>(\*\*<a href="src/docstrange/types/chat_create_completion_params.py">params</a>) -> object</code>

src/docstrange/_client.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@
3131
)
3232

3333
if TYPE_CHECKING:
34-
from .resources import extract, classify
35-
from .resources.extract import ExtractResource, AsyncExtractResource
34+
from .resources import chat, extract, classify
35+
from .resources.chat import ChatResource, AsyncChatResource
3636
from .resources.classify import ClassifyResource, AsyncClassifyResource
37+
from .resources.extract.extract import ExtractResource, AsyncExtractResource
3738

3839
__all__ = [
3940
"Timeout",
@@ -114,6 +115,12 @@ def classify(self) -> ClassifyResource:
114115

115116
return ClassifyResource(self)
116117

118+
@cached_property
119+
def chat(self) -> ChatResource:
120+
from .resources.chat import ChatResource
121+
122+
return ChatResource(self)
123+
117124
@cached_property
118125
def with_raw_response(self) -> DocstrangeWithRawResponse:
119126
return DocstrangeWithRawResponse(self)
@@ -294,6 +301,12 @@ def classify(self) -> AsyncClassifyResource:
294301

295302
return AsyncClassifyResource(self)
296303

304+
@cached_property
305+
def chat(self) -> AsyncChatResource:
306+
from .resources.chat import AsyncChatResource
307+
308+
return AsyncChatResource(self)
309+
297310
@cached_property
298311
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
299312
return AsyncDocstrangeWithRawResponse(self)
@@ -425,6 +438,12 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
425438

426439
return ClassifyResourceWithRawResponse(self._client.classify)
427440

441+
@cached_property
442+
def chat(self) -> chat.ChatResourceWithRawResponse:
443+
from .resources.chat import ChatResourceWithRawResponse
444+
445+
return ChatResourceWithRawResponse(self._client.chat)
446+
428447

429448
class AsyncDocstrangeWithRawResponse:
430449
_client: AsyncDocstrange
@@ -444,6 +463,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
444463

445464
return AsyncClassifyResourceWithRawResponse(self._client.classify)
446465

466+
@cached_property
467+
def chat(self) -> chat.AsyncChatResourceWithRawResponse:
468+
from .resources.chat import AsyncChatResourceWithRawResponse
469+
470+
return AsyncChatResourceWithRawResponse(self._client.chat)
471+
447472

448473
class DocstrangeWithStreamedResponse:
449474
_client: Docstrange
@@ -463,6 +488,12 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
463488

464489
return ClassifyResourceWithStreamingResponse(self._client.classify)
465490

491+
@cached_property
492+
def chat(self) -> chat.ChatResourceWithStreamingResponse:
493+
from .resources.chat import ChatResourceWithStreamingResponse
494+
495+
return ChatResourceWithStreamingResponse(self._client.chat)
496+
466497

467498
class AsyncDocstrangeWithStreamedResponse:
468499
_client: AsyncDocstrange
@@ -482,6 +513,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
482513

483514
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
484515

516+
@cached_property
517+
def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
518+
from .resources.chat import AsyncChatResourceWithStreamingResponse
519+
520+
return AsyncChatResourceWithStreamingResponse(self._client.chat)
521+
485522

486523
Client = Docstrange
487524

src/docstrange/pagination.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from typing import List, Generic, TypeVar, Optional, cast
4+
from typing_extensions import override
5+
6+
from ._models import BaseModel
7+
from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
8+
9+
__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
10+
11+
_T = TypeVar("_T")
12+
13+
14+
class PageNumberPaginationPagination(BaseModel):
15+
has_next: Optional[bool] = None
16+
17+
total_count: Optional[int] = None
18+
19+
20+
class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
21+
results: List[_T]
22+
pagination: Optional[PageNumberPaginationPagination] = None
23+
24+
@override
25+
def _get_page_items(self) -> List[_T]:
26+
results = self.results
27+
if not results:
28+
return []
29+
return results
30+
31+
@override
32+
def next_page_info(self) -> Optional[PageInfo]:
33+
last_page = cast("int | None", self._options.params.get("page")) or 1
34+
35+
total_pages = None
36+
if self.pagination is not None:
37+
if self.pagination.total_count is not None:
38+
total_pages = self.pagination.total_count
39+
if total_pages is not None and last_page >= total_pages:
40+
return None
41+
42+
return PageInfo(params={"page": last_page + 1})
43+
44+
45+
class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
46+
results: List[_T]
47+
pagination: Optional[PageNumberPaginationPagination] = None
48+
49+
@override
50+
def _get_page_items(self) -> List[_T]:
51+
results = self.results
52+
if not results:
53+
return []
54+
return results
55+
56+
@override
57+
def next_page_info(self) -> Optional[PageInfo]:
58+
last_page = cast("int | None", self._options.params.get("page")) or 1
59+
60+
total_pages = None
61+
if self.pagination is not None:
62+
if self.pagination.total_count is not None:
63+
total_pages = self.pagination.total_count
64+
if total_pages is not None and last_page >= total_pages:
65+
return None
66+
67+
return PageInfo(params={"page": last_page + 1})

src/docstrange/resources/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

3+
from .chat import (
4+
ChatResource,
5+
AsyncChatResource,
6+
ChatResourceWithRawResponse,
7+
AsyncChatResourceWithRawResponse,
8+
ChatResourceWithStreamingResponse,
9+
AsyncChatResourceWithStreamingResponse,
10+
)
311
from .extract import (
412
ExtractResource,
513
AsyncExtractResource,
@@ -30,4 +38,10 @@
3038
"AsyncClassifyResourceWithRawResponse",
3139
"ClassifyResourceWithStreamingResponse",
3240
"AsyncClassifyResourceWithStreamingResponse",
41+
"ChatResource",
42+
"AsyncChatResource",
43+
"ChatResourceWithRawResponse",
44+
"AsyncChatResourceWithRawResponse",
45+
"ChatResourceWithStreamingResponse",
46+
"AsyncChatResourceWithStreamingResponse",
3347
]

0 commit comments

Comments
 (0)