From 19fe0ddf024bf761e50dc300b02903068ea3a2cf Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 10 Feb 2026 02:31:57 +0000
Subject: [PATCH 01/26] chore: update SDK settings
---
.github/workflows/publish-pypi.yml | 28 ++++++++
.github/workflows/release-doctor.yml | 21 ++++++
.release-please-manifest.json | 3 +
.stats.yml | 2 +-
CONTRIBUTING.md | 4 +-
README.md | 14 ++--
bin/check-release-environment | 21 ++++++
pyproject.toml | 6 +-
release-please-config.json | 66 +++++++++++++++++++
src/docstrange/_files.py | 2 +-
src/docstrange/_version.py | 2 +-
src/docstrange/resources/api/api.py | 8 +--
src/docstrange/resources/api/v1/classify.py | 8 +--
.../resources/api/v1/extract/extract.py | 8 +--
.../resources/api/v1/extract/results.py | 8 +--
src/docstrange/resources/api/v1/v1.py | 8 +--
src/docstrange/resources/chat.py | 8 +--
17 files changed, 178 insertions(+), 39 deletions(-)
create mode 100644 .github/workflows/publish-pypi.yml
create mode 100644 .github/workflows/release-doctor.yml
create mode 100644 .release-please-manifest.json
create mode 100644 bin/check-release-environment
create mode 100644 release-please-config.json
diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
new file mode 100644
index 0000000..1be9543
--- /dev/null
+++ b/.github/workflows/publish-pypi.yml
@@ -0,0 +1,28 @@
+# This workflow is triggered when a GitHub release is created.
+# It can also be run manually to re-publish to PyPI in case it failed for some reason.
+# You can run this workflow by navigating to https://www.github.com/NanoNets/docstrange-python/actions/workflows/publish-pypi.yml
+name: Publish PyPI
+on:
+ workflow_dispatch:
+
+ release:
+ types: [published]
+
+jobs:
+ publish:
+ name: publish
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Install uv
+ uses: astral-sh/setup-uv@v5
+ with:
+ version: '0.9.13'
+
+ - name: Publish to PyPI
+ run: |
+ bash ./bin/publish-pypi
+ env:
+ PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml
new file mode 100644
index 0000000..7f49e8e
--- /dev/null
+++ b/.github/workflows/release-doctor.yml
@@ -0,0 +1,21 @@
+name: Release Doctor
+on:
+ pull_request:
+ branches:
+ - main
+ workflow_dispatch:
+
+jobs:
+ release_doctor:
+ name: release doctor
+ runs-on: ubuntu-latest
+ if: github.repository == 'NanoNets/docstrange-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')
+
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Check release environment
+ run: |
+ bash ./bin/check-release-environment
+ env:
+ PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
new file mode 100644
index 0000000..1332969
--- /dev/null
+++ b/.release-please-manifest.json
@@ -0,0 +1,3 @@
+{
+ ".": "0.0.1"
+}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 2d4c88e..6eceaf7 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: e00c8070feb190d613cf77e700818950
+config_hash: c087f5b6085f5869d1403c39fc1e3db2
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7b9c275..62e046f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -62,7 +62,7 @@ If you’d like to use the repository from source, you can either install from g
To install via git:
```sh
-$ pip install git+ssh://git@github.com/stainless-sdks/docstrange-python.git
+$ pip install git+ssh://git@github.com/NanoNets/docstrange-python.git
```
Alternatively, you can build from source and install the wheel file:
@@ -120,7 +120,7 @@ the changes aren't made through the automated pipeline, you may want to make rel
### Publish with a GitHub workflow
-You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/stainless-sdks/docstrange-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up.
+You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/NanoNets/docstrange-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up.
### Publish manually
diff --git a/README.md b/README.md
index 76d3c24..d10f2e4 100644
--- a/README.md
+++ b/README.md
@@ -16,8 +16,8 @@ The full API of this library can be found in [api.md](api.md).
## Installation
```sh
-# install from this staging repo
-pip install git+ssh://git@github.com/stainless-sdks/docstrange-python.git
+# install from the production repo
+pip install git+ssh://git@github.com/NanoNets/docstrange-python.git
```
> [!NOTE]
@@ -79,8 +79,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv
You can enable this by installing `aiohttp`:
```sh
-# install from this staging repo
-pip install 'docstrange[aiohttp] @ git+ssh://git@github.com/stainless-sdks/docstrange-python.git'
+# install from the production repo
+pip install 'docstrange[aiohttp] @ git+ssh://git@github.com/NanoNets/docstrange-python.git'
```
Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
@@ -271,9 +271,9 @@ extract = response.parse() # get the object that `api.v1.extract.sync()` would
print(extract.record_id)
```
-These methods return an [`APIResponse`](https://github.com/stainless-sdks/docstrange-python/tree/main/src/docstrange/_response.py) object.
+These methods return an [`APIResponse`](https://github.com/NanoNets/docstrange-python/tree/main/src/docstrange/_response.py) object.
-The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/docstrange-python/tree/main/src/docstrange/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.
+The async client returns an [`AsyncAPIResponse`](https://github.com/NanoNets/docstrange-python/tree/main/src/docstrange/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.
#### `.with_streaming_response`
@@ -379,7 +379,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con
We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
-We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/docstrange-python/issues) with questions, bugs, or suggestions.
+We are keen for your feedback; please open an [issue](https://www.github.com/NanoNets/docstrange-python/issues) with questions, bugs, or suggestions.
### Determining the installed version
diff --git a/bin/check-release-environment b/bin/check-release-environment
new file mode 100644
index 0000000..b845b0f
--- /dev/null
+++ b/bin/check-release-environment
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+errors=()
+
+if [ -z "${PYPI_TOKEN}" ]; then
+ errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
+fi
+
+lenErrors=${#errors[@]}
+
+if [[ lenErrors -gt 0 ]]; then
+ echo -e "Found the following errors in the release environment:\n"
+
+ for error in "${errors[@]}"; do
+ echo -e "- $error\n"
+ done
+
+ exit 1
+fi
+
+echo "The environment is ready to push releases!"
diff --git a/pyproject.toml b/pyproject.toml
index c5df32e..760311d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -37,8 +37,8 @@ classifiers = [
]
[project.urls]
-Homepage = "https://github.com/stainless-sdks/docstrange-python"
-Repository = "https://github.com/stainless-sdks/docstrange-python"
+Homepage = "https://github.com/NanoNets/docstrange-python"
+Repository = "https://github.com/NanoNets/docstrange-python"
[project.optional-dependencies]
aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"]
@@ -112,7 +112,7 @@ path = "README.md"
[[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]]
# replace relative links with absolute links
pattern = '\[(.+?)\]\(((?!https?://)\S+?)\)'
-replacement = '[\1](https://github.com/stainless-sdks/docstrange-python/tree/main/\g<2>)'
+replacement = '[\1](https://github.com/NanoNets/docstrange-python/tree/main/\g<2>)'
[tool.pytest.ini_options]
testpaths = ["tests"]
diff --git a/release-please-config.json b/release-please-config.json
new file mode 100644
index 0000000..24a8f54
--- /dev/null
+++ b/release-please-config.json
@@ -0,0 +1,66 @@
+{
+ "packages": {
+ ".": {}
+ },
+ "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json",
+ "include-v-in-tag": true,
+ "include-component-in-tag": false,
+ "versioning": "prerelease",
+ "prerelease": true,
+ "bump-minor-pre-major": true,
+ "bump-patch-for-minor-pre-major": false,
+ "pull-request-header": "Automated Release PR",
+ "pull-request-title-pattern": "release: ${version}",
+ "changelog-sections": [
+ {
+ "type": "feat",
+ "section": "Features"
+ },
+ {
+ "type": "fix",
+ "section": "Bug Fixes"
+ },
+ {
+ "type": "perf",
+ "section": "Performance Improvements"
+ },
+ {
+ "type": "revert",
+ "section": "Reverts"
+ },
+ {
+ "type": "chore",
+ "section": "Chores"
+ },
+ {
+ "type": "docs",
+ "section": "Documentation"
+ },
+ {
+ "type": "style",
+ "section": "Styles"
+ },
+ {
+ "type": "refactor",
+ "section": "Refactors"
+ },
+ {
+ "type": "test",
+ "section": "Tests",
+ "hidden": true
+ },
+ {
+ "type": "build",
+ "section": "Build System"
+ },
+ {
+ "type": "ci",
+ "section": "Continuous Integration",
+ "hidden": true
+ }
+ ],
+ "release-type": "python",
+ "extra-files": [
+ "src/docstrange/_version.py"
+ ]
+}
\ No newline at end of file
diff --git a/src/docstrange/_files.py b/src/docstrange/_files.py
index 48c137c..4ea5ccb 100644
--- a/src/docstrange/_files.py
+++ b/src/docstrange/_files.py
@@ -34,7 +34,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None:
if not is_file_content(obj):
prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`"
raise RuntimeError(
- f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/stainless-sdks/docstrange-python/tree/main#file-uploads"
+ f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/NanoNets/docstrange-python/tree/main#file-uploads"
) from None
diff --git a/src/docstrange/_version.py b/src/docstrange/_version.py
index 7b3567a..fc8a3e5 100644
--- a/src/docstrange/_version.py
+++ b/src/docstrange/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "docstrange"
-__version__ = "0.0.1"
+__version__ = "0.0.1" # x-release-please-version
diff --git a/src/docstrange/resources/api/api.py b/src/docstrange/resources/api/api.py
index 2156132..b771b29 100644
--- a/src/docstrange/resources/api/api.py
+++ b/src/docstrange/resources/api/api.py
@@ -27,7 +27,7 @@ def with_raw_response(self) -> APIResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return APIResourceWithRawResponse(self)
@@ -36,7 +36,7 @@ def with_streaming_response(self) -> APIResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return APIResourceWithStreamingResponse(self)
@@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncAPIResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return AsyncAPIResourceWithRawResponse(self)
@@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncAPIResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return AsyncAPIResourceWithStreamingResponse(self)
diff --git a/src/docstrange/resources/api/v1/classify.py b/src/docstrange/resources/api/v1/classify.py
index b31e9d9..fdd4c7a 100644
--- a/src/docstrange/resources/api/v1/classify.py
+++ b/src/docstrange/resources/api/v1/classify.py
@@ -39,7 +39,7 @@ def with_raw_response(self) -> ClassifyResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return ClassifyResourceWithRawResponse(self)
@@ -48,7 +48,7 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return ClassifyResourceWithStreamingResponse(self)
@@ -166,7 +166,7 @@ def with_raw_response(self) -> AsyncClassifyResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return AsyncClassifyResourceWithRawResponse(self)
@@ -175,7 +175,7 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return AsyncClassifyResourceWithStreamingResponse(self)
diff --git a/src/docstrange/resources/api/v1/extract/extract.py b/src/docstrange/resources/api/v1/extract/extract.py
index adc79ea..94ced26 100644
--- a/src/docstrange/resources/api/v1/extract/extract.py
+++ b/src/docstrange/resources/api/v1/extract/extract.py
@@ -56,7 +56,7 @@ def with_raw_response(self) -> ExtractResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return ExtractResourceWithRawResponse(self)
@@ -65,7 +65,7 @@ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return ExtractResourceWithStreamingResponse(self)
@@ -401,7 +401,7 @@ def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return AsyncExtractResourceWithRawResponse(self)
@@ -410,7 +410,7 @@ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return AsyncExtractResourceWithStreamingResponse(self)
diff --git a/src/docstrange/resources/api/v1/extract/results.py b/src/docstrange/resources/api/v1/extract/results.py
index 434ba0b..51832fe 100644
--- a/src/docstrange/resources/api/v1/extract/results.py
+++ b/src/docstrange/resources/api/v1/extract/results.py
@@ -31,7 +31,7 @@ def with_raw_response(self) -> ResultsResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return ResultsResourceWithRawResponse(self)
@@ -40,7 +40,7 @@ def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return ResultsResourceWithStreamingResponse(self)
@@ -141,7 +141,7 @@ def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return AsyncResultsResourceWithRawResponse(self)
@@ -150,7 +150,7 @@ def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return AsyncResultsResourceWithStreamingResponse(self)
diff --git a/src/docstrange/resources/api/v1/v1.py b/src/docstrange/resources/api/v1/v1.py
index 496bd48..1dbb99b 100644
--- a/src/docstrange/resources/api/v1/v1.py
+++ b/src/docstrange/resources/api/v1/v1.py
@@ -39,7 +39,7 @@ def with_raw_response(self) -> V1ResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return V1ResourceWithRawResponse(self)
@@ -48,7 +48,7 @@ def with_streaming_response(self) -> V1ResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return V1ResourceWithStreamingResponse(self)
@@ -68,7 +68,7 @@ def with_raw_response(self) -> AsyncV1ResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return AsyncV1ResourceWithRawResponse(self)
@@ -77,7 +77,7 @@ def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return AsyncV1ResourceWithStreamingResponse(self)
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
index c25880d..0a892c1 100644
--- a/src/docstrange/resources/chat.py
+++ b/src/docstrange/resources/chat.py
@@ -29,7 +29,7 @@ def with_raw_response(self) -> ChatResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return ChatResourceWithRawResponse(self)
@@ -38,7 +38,7 @@ def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return ChatResourceWithStreamingResponse(self)
@@ -109,7 +109,7 @@ def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
This property can be used as a prefix for any HTTP method call to return
the raw response object instead of the parsed content.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#accessing-raw-response-data-eg-headers
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
"""
return AsyncChatResourceWithRawResponse(self)
@@ -118,7 +118,7 @@ def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
"""
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- For more information, see https://www.github.com/stainless-sdks/docstrange-python#with_streaming_response
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
"""
return AsyncChatResourceWithStreamingResponse(self)
From 2c177c784f8492fd77ae6371e2cf229f5fd6d151 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 10 Feb 2026 02:32:16 +0000
Subject: [PATCH 02/26] chore: update SDK settings
---
.stats.yml | 2 +-
README.md | 13 ++--
pyproject.toml | 2 +-
requirements-dev.lock | 12 +--
uv.lock | 170 +++++++++++++++++++++---------------------
5 files changed, 98 insertions(+), 101 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 6eceaf7..18ffc41 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: c087f5b6085f5869d1403c39fc1e3db2
+config_hash: ed1c4120702af3765a79005ac3ed79a9
diff --git a/README.md b/README.md
index d10f2e4..751b894 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# Docstrange Python API library
-[)](https://pypi.org/project/docstrange/)
+[)](https://pypi.org/project/docstrange-api/)
The Docstrange Python library provides convenient access to the Docstrange REST API from any Python 3.9+
application. The library includes type definitions for all request params and response fields,
@@ -16,13 +16,10 @@ The full API of this library can be found in [api.md](api.md).
## Installation
```sh
-# install from the production repo
-pip install git+ssh://git@github.com/NanoNets/docstrange-python.git
+# install from PyPI
+pip install docstrange-api
```
-> [!NOTE]
-> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install docstrange`
-
## Usage
The full API of this library can be found in [api.md](api.md).
@@ -79,8 +76,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv
You can enable this by installing `aiohttp`:
```sh
-# install from the production repo
-pip install 'docstrange[aiohttp] @ git+ssh://git@github.com/NanoNets/docstrange-python.git'
+# install from PyPI
+pip install docstrange-api[aiohttp]
```
Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
diff --git a/pyproject.toml b/pyproject.toml
index 760311d..0d11a7e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,5 +1,5 @@
[project]
-name = "docstrange"
+name = "docstrange-api"
version = "0.0.1"
description = "The official Python library for the docstrange API"
dynamic = ["readme"]
diff --git a/requirements-dev.lock b/requirements-dev.lock
index 01d01bc..e92af26 100644
--- a/requirements-dev.lock
+++ b/requirements-dev.lock
@@ -5,7 +5,7 @@ annotated-types==0.7.0
# via pydantic
anyio==4.12.1
# via
- # docstrange
+ # docstrange-api
# httpx
backports-asyncio-runner==1.2.0 ; python_full_version < '3.11'
# via pytest-asyncio
@@ -17,7 +17,7 @@ colorama==0.4.6 ; sys_platform == 'win32'
# via pytest
dirty-equals==0.11
distro==1.9.0
- # via docstrange
+ # via docstrange-api
exceptiongroup==1.3.1 ; python_full_version < '3.11'
# via
# anyio
@@ -30,7 +30,7 @@ httpcore==1.0.9
# via httpx
httpx==0.28.1
# via
- # docstrange
+ # docstrange-api
# respx
idna==3.11
# via
@@ -59,7 +59,7 @@ pathspec==1.0.3
pluggy==1.6.0
# via pytest
pydantic==2.12.5
- # via docstrange
+ # via docstrange-api
pydantic-core==2.41.5
# via pydantic
pygments==2.19.2
@@ -86,7 +86,7 @@ ruff==0.14.13
six==1.17.0 ; python_full_version < '3.10'
# via python-dateutil
sniffio==1.3.1
- # via docstrange
+ # via docstrange-api
time-machine==2.19.0 ; python_full_version < '3.10'
time-machine==3.2.0 ; python_full_version >= '3.10'
tomli==2.4.0 ; python_full_version < '3.11'
@@ -96,7 +96,7 @@ tomli==2.4.0 ; python_full_version < '3.11'
typing-extensions==4.15.0
# via
# anyio
- # docstrange
+ # docstrange-api
# exceptiongroup
# mypy
# pydantic
diff --git a/uv.lock b/uv.lock
index 67db705..8e4d6e0 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2,17 +2,17 @@ version = 1
revision = 3
requires-python = ">=3.9"
resolution-markers = [
- "python_full_version >= '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version < '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version < '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version < '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
+ "python_full_version >= '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version < '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version < '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version < '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
]
conflicts = [[
- { package = "docstrange", group = "pydantic-v1" },
- { package = "docstrange", group = "pydantic-v2" },
+ { package = "docstrange-api", group = "pydantic-v1" },
+ { package = "docstrange-api", group = "pydantic-v2" },
]]
[[package]]
@@ -31,7 +31,7 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohappyeyeballs" },
{ name = "aiosignal" },
- { name = "async-timeout", marker = "python_full_version < '3.11' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "async-timeout", marker = "python_full_version < '3.11' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
{ name = "attrs" },
{ name = "frozenlist" },
{ name = "multidict" },
@@ -167,7 +167,7 @@ version = "1.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "frozenlist" },
- { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" }
wheels = [
@@ -188,9 +188,9 @@ name = "anyio"
version = "4.12.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
{ name = "idna" },
- { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" }
wheels = [
@@ -261,15 +261,15 @@ wheels = [
]
[[package]]
-name = "docstrange"
+name = "docstrange-api"
version = "0.0.1"
source = { editable = "." }
dependencies = [
{ name = "anyio" },
{ name = "distro" },
{ name = "httpx" },
- { name = "pydantic", version = "1.10.26", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-10-docstrange-pydantic-v1'" },
- { name = "pydantic", version = "2.12.5", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-10-docstrange-pydantic-v2' or extra != 'group-10-docstrange-pydantic-v1'" },
+ { name = "pydantic", version = "1.10.26", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-14-docstrange-api-pydantic-v1'" },
+ { name = "pydantic", version = "2.12.5", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-14-docstrange-api-pydantic-v2' or extra != 'group-14-docstrange-api-pydantic-v1'" },
{ name = "sniffio" },
{ name = "typing-extensions" },
]
@@ -286,16 +286,16 @@ dev = [
{ name = "importlib-metadata" },
{ name = "mypy" },
{ name = "pyright" },
- { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pytest-asyncio", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pytest-asyncio", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pytest-asyncio", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pytest-asyncio", version = "1.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
{ name = "pytest-xdist" },
{ name = "respx" },
{ name = "rich" },
{ name = "ruff" },
- { name = "time-machine", version = "2.19.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "time-machine", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "time-machine", version = "2.19.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "time-machine", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
pydantic-v1 = [
{ name = "pydantic", version = "1.10.26", source = { registry = "https://pypi.org/simple" } },
@@ -342,7 +342,7 @@ name = "exceptiongroup"
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
wheels = [
@@ -583,10 +583,10 @@ name = "iniconfig"
version = "2.3.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
- "python_full_version >= '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
+ "python_full_version >= '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
]
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
wheels = [
@@ -601,7 +601,7 @@ resolution-markers = [
"python_full_version < '3.10'",
]
dependencies = [
- { name = "mdurl", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "mdurl", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" }
wheels = [
@@ -613,13 +613,13 @@ name = "markdown-it-py"
version = "4.0.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
- "python_full_version >= '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
+ "python_full_version >= '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
]
dependencies = [
- { name = "mdurl", marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "mdurl", marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
wheels = [
@@ -640,7 +640,7 @@ name = "multidict"
version = "6.7.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" }
wheels = [
@@ -798,7 +798,7 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mypy-extensions" },
{ name = "pathspec" },
- { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1e/e3/034322d5a779685218ed69286c32faa505247f1f096251ef66c8fd203b08/mypy-1.17.0.tar.gz", hash = "sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03", size = 3352114, upload-time = "2025-07-14T20:34:30.181Z" }
@@ -1019,7 +1019,7 @@ resolution-markers = [
"python_full_version < '3.10'",
]
dependencies = [
- { name = "typing-extensions", marker = "extra == 'group-10-docstrange-pydantic-v1'" },
+ { name = "typing-extensions", marker = "extra == 'group-14-docstrange-api-pydantic-v1'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/7b/da/fd89f987a376c807cd81ea0eff4589aade783bbb702637b4734ef2c743a2/pydantic-1.10.26.tar.gz", hash = "sha256:8c6aa39b494c5af092e690127c283d84f363ac36017106a9e66cb33a22ac412e", size = 357906, upload-time = "2025-12-18T15:47:46.557Z" }
wheels = [
@@ -1061,17 +1061,17 @@ name = "pydantic"
version = "2.12.5"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
- "python_full_version >= '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version < '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version < '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
+ "python_full_version >= '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version < '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version < '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
]
dependencies = [
- { name = "annotated-types", marker = "extra == 'group-10-docstrange-pydantic-v2' or extra != 'group-10-docstrange-pydantic-v1'" },
- { name = "pydantic-core", marker = "extra == 'group-10-docstrange-pydantic-v2' or extra != 'group-10-docstrange-pydantic-v1'" },
- { name = "typing-extensions", marker = "extra == 'group-10-docstrange-pydantic-v2' or extra != 'group-10-docstrange-pydantic-v1'" },
- { name = "typing-inspection", marker = "extra == 'group-10-docstrange-pydantic-v2' or extra != 'group-10-docstrange-pydantic-v1'" },
+ { name = "annotated-types", marker = "extra == 'group-14-docstrange-api-pydantic-v2' or extra != 'group-14-docstrange-api-pydantic-v1'" },
+ { name = "pydantic-core", marker = "extra == 'group-14-docstrange-api-pydantic-v2' or extra != 'group-14-docstrange-api-pydantic-v1'" },
+ { name = "typing-extensions", marker = "extra == 'group-14-docstrange-api-pydantic-v2' or extra != 'group-14-docstrange-api-pydantic-v1'" },
+ { name = "typing-inspection", marker = "extra == 'group-14-docstrange-api-pydantic-v2' or extra != 'group-14-docstrange-api-pydantic-v1'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" }
wheels = [
@@ -1083,7 +1083,7 @@ name = "pydantic-core"
version = "2.41.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "typing-extensions", marker = "extra == 'group-10-docstrange-pydantic-v2' or extra != 'group-10-docstrange-pydantic-v1'" },
+ { name = "typing-extensions", marker = "extra == 'group-14-docstrange-api-pydantic-v2' or extra != 'group-14-docstrange-api-pydantic-v1'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" }
wheels = [
@@ -1239,13 +1239,13 @@ resolution-markers = [
"python_full_version < '3.10'",
]
dependencies = [
- { name = "colorama", marker = "(python_full_version < '3.10' and sys_platform == 'win32') or (python_full_version >= '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2') or (sys_platform != 'win32' and extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "exceptiongroup", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "packaging", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pluggy", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pygments", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "tomli", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "colorama", marker = "(python_full_version < '3.10' and sys_platform == 'win32') or (python_full_version >= '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2') or (sys_platform != 'win32' and extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "exceptiongroup", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "packaging", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pluggy", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pygments", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "tomli", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" }
wheels = [
@@ -1257,19 +1257,19 @@ name = "pytest"
version = "9.0.2"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
- "python_full_version >= '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
+ "python_full_version >= '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
]
dependencies = [
- { name = "colorama", marker = "(python_full_version >= '3.10' and sys_platform == 'win32') or (python_full_version < '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2') or (sys_platform != 'win32' and extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "exceptiongroup", marker = "python_full_version == '3.10.*' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "packaging", marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pluggy", marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pygments", marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "tomli", marker = "python_full_version == '3.10.*' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "colorama", marker = "(python_full_version >= '3.10' and sys_platform == 'win32') or (python_full_version < '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2') or (sys_platform != 'win32' and extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "exceptiongroup", marker = "python_full_version == '3.10.*' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "packaging", marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pluggy", marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pygments", marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "tomli", marker = "python_full_version == '3.10.*' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
wheels = [
@@ -1284,9 +1284,9 @@ resolution-markers = [
"python_full_version < '3.10'",
]
dependencies = [
- { name = "backports-asyncio-runner", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "typing-extensions", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "backports-asyncio-runner", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "typing-extensions", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/42/86/9e3c5f48f7b7b638b216e4b9e645f54d199d7abbbab7a64a13b4e12ba10f/pytest_asyncio-1.2.0.tar.gz", hash = "sha256:c609a64a2a8768462d0c99811ddb8bd2583c33fd33cf7f21af1c142e824ffb57", size = 50119, upload-time = "2025-09-12T07:33:53.816Z" }
wheels = [
@@ -1298,15 +1298,15 @@ name = "pytest-asyncio"
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
- "python_full_version >= '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
+ "python_full_version >= '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
]
dependencies = [
- { name = "backports-asyncio-runner", marker = "python_full_version == '3.10.*' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "backports-asyncio-runner", marker = "python_full_version == '3.10.*' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "typing-extensions", marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version < '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2') or (python_full_version >= '3.13' and extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" }
wheels = [
@@ -1319,8 +1319,8 @@ version = "3.8.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "execnet" },
- { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" }
wheels = [
@@ -1332,7 +1332,7 @@ name = "python-dateutil"
version = "2.9.0.post0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "six", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "six", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
wheels = [
@@ -1356,8 +1356,8 @@ name = "rich"
version = "14.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
- { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
+ { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
{ name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" }
@@ -1417,7 +1417,7 @@ resolution-markers = [
"python_full_version < '3.10'",
]
dependencies = [
- { name = "python-dateutil", marker = "python_full_version < '3.10' or (extra == 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2')" },
+ { name = "python-dateutil", marker = "python_full_version < '3.10' or (extra == 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/1b5fdd165f61b67f445fac2a7feb0c655118edef429cd09ff5a8067f7f1d/time_machine-2.19.0.tar.gz", hash = "sha256:7c5065a8b3f2bbb449422c66ef71d114d3f909c276a6469642ecfffb6a0fcd29", size = 14576, upload-time = "2025-08-19T17:22:08.402Z" }
wheels = [
@@ -1516,10 +1516,10 @@ name = "time-machine"
version = "3.2.0"
source = { registry = "https://pypi.org/simple" }
resolution-markers = [
- "python_full_version >= '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-10-docstrange-pydantic-v1' and extra == 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra == 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
- "python_full_version >= '3.10' and extra != 'group-10-docstrange-pydantic-v1' and extra != 'group-10-docstrange-pydantic-v2'",
+ "python_full_version >= '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and python_full_version < '3.14' and extra != 'group-14-docstrange-api-pydantic-v1' and extra == 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra == 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
+ "python_full_version >= '3.10' and extra != 'group-14-docstrange-api-pydantic-v1' and extra != 'group-14-docstrange-api-pydantic-v2'",
]
sdist = { url = "https://files.pythonhosted.org/packages/02/fc/37b02f6094dbb1f851145330460532176ed2f1dc70511a35828166c41e52/time_machine-3.2.0.tar.gz", hash = "sha256:a4ddd1cea17b8950e462d1805a42b20c81eb9aafc8f66b392dd5ce997e037d79", size = 14804, upload-time = "2025-12-17T23:33:02.599Z" }
wheels = [
@@ -1670,7 +1670,7 @@ name = "typing-inspection"
version = "0.4.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "typing-extensions", marker = "extra == 'group-10-docstrange-pydantic-v2' or extra != 'group-10-docstrange-pydantic-v1'" },
+ { name = "typing-extensions", marker = "extra == 'group-14-docstrange-api-pydantic-v2' or extra != 'group-14-docstrange-api-pydantic-v1'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
wheels = [
From c2d9004668a9eb79f6cc5a19879ed8d9928f316f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 10 Feb 2026 02:32:34 +0000
Subject: [PATCH 03/26] chore: update SDK settings
---
.github/workflows/publish-pypi.yml | 5 +++--
.github/workflows/release-doctor.yml | 2 --
.stats.yml | 2 +-
bin/check-release-environment | 4 ----
bin/publish-pypi | 6 +++++-
5 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
index 1be9543..e1fd4b7 100644
--- a/.github/workflows/publish-pypi.yml
+++ b/.github/workflows/publish-pypi.yml
@@ -12,6 +12,9 @@ jobs:
publish:
name: publish
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ id-token: write
steps:
- uses: actions/checkout@v6
@@ -24,5 +27,3 @@ jobs:
- name: Publish to PyPI
run: |
bash ./bin/publish-pypi
- env:
- PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml
index 7f49e8e..5be741d 100644
--- a/.github/workflows/release-doctor.yml
+++ b/.github/workflows/release-doctor.yml
@@ -17,5 +17,3 @@ jobs:
- name: Check release environment
run: |
bash ./bin/check-release-environment
- env:
- PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.stats.yml b/.stats.yml
index 18ffc41..ca198c1 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: ed1c4120702af3765a79005ac3ed79a9
+config_hash: 499f6cd156a3fc23a8c12d6d6c9d8ba5
diff --git a/bin/check-release-environment b/bin/check-release-environment
index b845b0f..1e951e9 100644
--- a/bin/check-release-environment
+++ b/bin/check-release-environment
@@ -2,10 +2,6 @@
errors=()
-if [ -z "${PYPI_TOKEN}" ]; then
- errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
-fi
-
lenErrors=${#errors[@]}
if [[ lenErrors -gt 0 ]]; then
diff --git a/bin/publish-pypi b/bin/publish-pypi
index e72ca2f..5895700 100644
--- a/bin/publish-pypi
+++ b/bin/publish-pypi
@@ -4,4 +4,8 @@ set -eux
rm -rf dist
mkdir -p dist
uv build
-uv publish --token=$PYPI_TOKEN
+if [ -n "${PYPI_TOKEN:-}" ]; then
+ uv publish --token=$PYPI_TOKEN
+else
+ uv publish
+fi
From ec90172800803c48e72e6105e265ccd757f80314 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 10 Feb 2026 02:32:52 +0000
Subject: [PATCH 04/26] chore: update SDK settings
---
.github/workflows/publish-pypi.yml | 5 ++---
.github/workflows/release-doctor.yml | 2 ++
.stats.yml | 2 +-
bin/check-release-environment | 4 ++++
bin/publish-pypi | 6 +-----
5 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
index e1fd4b7..1be9543 100644
--- a/.github/workflows/publish-pypi.yml
+++ b/.github/workflows/publish-pypi.yml
@@ -12,9 +12,6 @@ jobs:
publish:
name: publish
runs-on: ubuntu-latest
- permissions:
- contents: read
- id-token: write
steps:
- uses: actions/checkout@v6
@@ -27,3 +24,5 @@ jobs:
- name: Publish to PyPI
run: |
bash ./bin/publish-pypi
+ env:
+ PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml
index 5be741d..7f49e8e 100644
--- a/.github/workflows/release-doctor.yml
+++ b/.github/workflows/release-doctor.yml
@@ -17,3 +17,5 @@ jobs:
- name: Check release environment
run: |
bash ./bin/check-release-environment
+ env:
+ PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.stats.yml b/.stats.yml
index ca198c1..18ffc41 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 499f6cd156a3fc23a8c12d6d6c9d8ba5
+config_hash: ed1c4120702af3765a79005ac3ed79a9
diff --git a/bin/check-release-environment b/bin/check-release-environment
index 1e951e9..b845b0f 100644
--- a/bin/check-release-environment
+++ b/bin/check-release-environment
@@ -2,6 +2,10 @@
errors=()
+if [ -z "${PYPI_TOKEN}" ]; then
+ errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
+fi
+
lenErrors=${#errors[@]}
if [[ lenErrors -gt 0 ]]; then
diff --git a/bin/publish-pypi b/bin/publish-pypi
index 5895700..e72ca2f 100644
--- a/bin/publish-pypi
+++ b/bin/publish-pypi
@@ -4,8 +4,4 @@ set -eux
rm -rf dist
mkdir -p dist
uv build
-if [ -n "${PYPI_TOKEN:-}" ]; then
- uv publish --token=$PYPI_TOKEN
-else
- uv publish
-fi
+uv publish --token=$PYPI_TOKEN
From e231259dabdfcb1ee3d818f5720d484dbc48d7fd Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 10 Feb 2026 02:33:45 +0000
Subject: [PATCH 05/26] chore: update SDK settings
---
.github/workflows/publish-pypi.yml | 5 +++--
.github/workflows/release-doctor.yml | 2 --
.stats.yml | 2 +-
bin/check-release-environment | 4 ----
bin/publish-pypi | 6 +++++-
5 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
index 1be9543..e1fd4b7 100644
--- a/.github/workflows/publish-pypi.yml
+++ b/.github/workflows/publish-pypi.yml
@@ -12,6 +12,9 @@ jobs:
publish:
name: publish
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ id-token: write
steps:
- uses: actions/checkout@v6
@@ -24,5 +27,3 @@ jobs:
- name: Publish to PyPI
run: |
bash ./bin/publish-pypi
- env:
- PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml
index 7f49e8e..5be741d 100644
--- a/.github/workflows/release-doctor.yml
+++ b/.github/workflows/release-doctor.yml
@@ -17,5 +17,3 @@ jobs:
- name: Check release environment
run: |
bash ./bin/check-release-environment
- env:
- PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.stats.yml b/.stats.yml
index 18ffc41..ca198c1 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: ed1c4120702af3765a79005ac3ed79a9
+config_hash: 499f6cd156a3fc23a8c12d6d6c9d8ba5
diff --git a/bin/check-release-environment b/bin/check-release-environment
index b845b0f..1e951e9 100644
--- a/bin/check-release-environment
+++ b/bin/check-release-environment
@@ -2,10 +2,6 @@
errors=()
-if [ -z "${PYPI_TOKEN}" ]; then
- errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
-fi
-
lenErrors=${#errors[@]}
if [[ lenErrors -gt 0 ]]; then
diff --git a/bin/publish-pypi b/bin/publish-pypi
index e72ca2f..5895700 100644
--- a/bin/publish-pypi
+++ b/bin/publish-pypi
@@ -4,4 +4,8 @@ set -eux
rm -rf dist
mkdir -p dist
uv build
-uv publish --token=$PYPI_TOKEN
+if [ -n "${PYPI_TOKEN:-}" ]; then
+ uv publish --token=$PYPI_TOKEN
+else
+ uv publish
+fi
From 2a9320359140a76fd94710fe9b57f0040a4eab84 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 07:08:23 +0000
Subject: [PATCH 06/26] Update config with full model mappings and docstrange
branding
---
.stats.yml | 2 +-
README.md | 22 +--
api.md | 51 +++---
src/docstrange/_client.py | 77 ++++++---
src/docstrange/resources/__init__.py | 42 +++--
src/docstrange/resources/api/__init__.py | 33 ----
src/docstrange/resources/api/api.py | 102 ------------
src/docstrange/resources/api/v1/__init__.py | 47 ------
src/docstrange/resources/api/v1/v1.py | 134 ----------------
.../resources/{api/v1 => }/classify.py | 108 ++++++-------
.../{api/v1 => }/extract/__init__.py | 0
.../resources/{api/v1 => }/extract/extract.py | 147 ++++++++----------
.../resources/{api/v1 => }/extract/results.py | 26 ++--
src/docstrange/types/__init__.py | 16 ++
src/docstrange/types/api/__init__.py | 3 -
src/docstrange/types/api/v1/__init__.py | 17 --
.../types/api/v1/extraction_format_result.py | 22 ---
...response.py => batch_classify_response.py} | 6 +-
..._response.py => batch_extract_response.py} | 6 +-
.../{api/v1 => }/classify_batch_params.py | 2 +-
..._sync_response.py => classify_response.py} | 6 +-
.../{api/v1 => }/classify_sync_params.py | 2 +-
.../types/{api/v1 => }/extract/__init__.py | 3 +-
.../types/extract/extraction_list_response.py | 17 ++
.../pagination_info.py} | 17 +-
.../v1 => }/extract/result_list_params.py | 0
.../v1 => }/extract/result_retrieve_params.py | 0
.../{api/v1 => }/extract_async_params.py | 2 +-
.../{api/v1 => }/extract_batch_params.py | 2 +-
.../types/{api/v1 => }/extract_response.py | 22 +--
.../{api/v1 => }/extract_stream_params.py | 2 +-
.../{api/v1 => }/extract_stream_response.py | 0
.../types/{api/v1 => }/extract_sync_params.py | 2 +-
.../types/extraction_format_result.py | 15 ++
src/docstrange/types/extraction_metadata.py | 15 ++
src/docstrange/types/extraction_result.py | 22 +++
.../types/file_classification_result.py | 24 +++
...ation_result.py => page_classification.py} | 24 +--
tests/api_resources/api/v1/__init__.py | 1 -
.../api_resources/api/v1/extract/__init__.py | 1 -
.../{api => extract}/__init__.py | 0
.../{api/v1 => }/extract/test_results.py | 56 +++----
.../{api/v1 => }/test_classify.py | 53 +++----
.../{api/v1 => }/test_extract.py | 84 +++++-----
tests/test_client.py | 20 +--
45 files changed, 497 insertions(+), 756 deletions(-)
delete mode 100644 src/docstrange/resources/api/__init__.py
delete mode 100644 src/docstrange/resources/api/api.py
delete mode 100644 src/docstrange/resources/api/v1/__init__.py
delete mode 100644 src/docstrange/resources/api/v1/v1.py
rename src/docstrange/resources/{api/v1 => }/classify.py (81%)
rename src/docstrange/resources/{api/v1 => }/extract/__init__.py (100%)
rename src/docstrange/resources/{api/v1 => }/extract/extract.py (89%)
rename src/docstrange/resources/{api/v1 => }/extract/results.py (93%)
delete mode 100644 src/docstrange/types/api/__init__.py
delete mode 100644 src/docstrange/types/api/v1/__init__.py
delete mode 100644 src/docstrange/types/api/v1/extraction_format_result.py
rename src/docstrange/types/{api/v1/classify_batch_response.py => batch_classify_response.py} (76%)
rename src/docstrange/types/{api/v1/extract_batch_response.py => batch_extract_response.py} (75%)
rename src/docstrange/types/{api/v1 => }/classify_batch_params.py (89%)
rename src/docstrange/types/{api/v1/classify_sync_response.py => classify_response.py} (71%)
rename src/docstrange/types/{api/v1 => }/classify_sync_params.py (93%)
rename src/docstrange/types/{api/v1 => }/extract/__init__.py (64%)
create mode 100644 src/docstrange/types/extract/extraction_list_response.py
rename src/docstrange/types/{api/v1/extract/result_list_response.py => extract/pagination_info.py} (50%)
rename src/docstrange/types/{api/v1 => }/extract/result_list_params.py (100%)
rename src/docstrange/types/{api/v1 => }/extract/result_retrieve_params.py (100%)
rename src/docstrange/types/{api/v1 => }/extract_async_params.py (97%)
rename src/docstrange/types/{api/v1 => }/extract_batch_params.py (92%)
rename src/docstrange/types/{api/v1 => }/extract_response.py (57%)
rename src/docstrange/types/{api/v1 => }/extract_stream_params.py (97%)
rename src/docstrange/types/{api/v1 => }/extract_stream_response.py (100%)
rename src/docstrange/types/{api/v1 => }/extract_sync_params.py (97%)
create mode 100644 src/docstrange/types/extraction_format_result.py
create mode 100644 src/docstrange/types/extraction_metadata.py
create mode 100644 src/docstrange/types/extraction_result.py
create mode 100644 src/docstrange/types/file_classification_result.py
rename src/docstrange/types/{api/v1/file_classification_result.py => page_classification.py} (56%)
delete mode 100644 tests/api_resources/api/v1/__init__.py
delete mode 100644 tests/api_resources/api/v1/extract/__init__.py
rename tests/api_resources/{api => extract}/__init__.py (100%)
rename tests/api_resources/{api/v1 => }/extract/test_results.py (76%)
rename tests/api_resources/{api/v1 => }/test_classify.py (78%)
rename tests/api_resources/{api/v1 => }/test_extract.py (84%)
diff --git a/.stats.yml b/.stats.yml
index ca198c1..1774d1c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 499f6cd156a3fc23a8c12d6d6c9d8ba5
+config_hash: 5095aef18b1e8c018bc58e39d6f4b23d
diff --git a/README.md b/README.md
index 751b894..9532911 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ It is generated with [Stainless](https://www.stainless.com/).
## Documentation
-The full API of this library can be found in [api.md](api.md).
+The REST API documentation can be found on [docs.nanonets.com](https://docs.nanonets.com). The full API of this library can be found in [api.md](api.md).
## Installation
@@ -32,7 +32,7 @@ client = Docstrange(
api_key=os.environ.get("DOCSTRANGE_API_KEY"), # This is the default and can be omitted
)
-extract_response = client.api.v1.extract.sync(
+extract_response = client.extract.sync(
output_format="markdown",
)
print(extract_response.record_id)
@@ -58,7 +58,7 @@ client = AsyncDocstrange(
async def main() -> None:
- extract_response = await client.api.v1.extract.sync(
+ extract_response = await client.extract.sync(
output_format="markdown",
)
print(extract_response.record_id)
@@ -94,7 +94,7 @@ async def main() -> None:
api_key=os.environ.get("DOCSTRANGE_API_KEY"), # This is the default and can be omitted
http_client=DefaultAioHttpClient(),
) as client:
- extract_response = await client.api.v1.extract.sync(
+ extract_response = await client.extract.sync(
output_format="markdown",
)
print(extract_response.record_id)
@@ -122,7 +122,7 @@ from docstrange import Docstrange
client = Docstrange()
-client.api.v1.extract.sync(
+client.extract.sync(
output_format="markdown",
file=Path("/path/to/file"),
)
@@ -146,7 +146,7 @@ from docstrange import Docstrange
client = Docstrange()
try:
- client.api.v1.extract.sync(
+ client.extract.sync(
output_format="markdown",
)
except docstrange.APIConnectionError as e:
@@ -191,7 +191,7 @@ client = Docstrange(
)
# Or, configure per-request:
-client.with_options(max_retries=5).api.v1.extract.sync(
+client.with_options(max_retries=5).extract.sync(
output_format="markdown",
)
```
@@ -216,7 +216,7 @@ client = Docstrange(
)
# Override per-request:
-client.with_options(timeout=5.0).api.v1.extract.sync(
+client.with_options(timeout=5.0).extract.sync(
output_format="markdown",
)
```
@@ -259,12 +259,12 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
from docstrange import Docstrange
client = Docstrange()
-response = client.api.v1.extract.with_raw_response.sync(
+response = client.extract.with_raw_response.sync(
output_format="markdown",
)
print(response.headers.get('X-My-Header'))
-extract = response.parse() # get the object that `api.v1.extract.sync()` would have returned
+extract = response.parse() # get the object that `extract.sync()` would have returned
print(extract.record_id)
```
@@ -279,7 +279,7 @@ The above interface eagerly reads the full response body when you make the reque
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
```python
-with client.api.v1.extract.with_streaming_response.sync(
+with client.extract.with_streaming_response.sync(
output_format="markdown",
) as response:
print(response.headers.get("X-My-Header"))
diff --git a/api.md b/api.md
index 3b4eeb8..2f2f496 100644
--- a/api.md
+++ b/api.md
@@ -1,60 +1,69 @@
-# API
-
-## V1
-
-### Extract
+# Extract
Types:
```python
-from docstrange.types.api.v1 import (
+from docstrange.types import (
+ BatchExtractRequestBody,
+ BatchExtractResponse,
ExtractRequestBody,
ExtractResponse,
ExtractionFormatResult,
- ExtractBatchResponse,
+ ExtractionMetadata,
+ ExtractionResult,
+ StreamExtractRequestBody,
ExtractStreamResponse,
)
```
Methods:
-- client.api.v1.extract.async\_(\*\*params) -> ExtractResponse
-- client.api.v1.extract.batch(\*\*params) -> ExtractBatchResponse
-- client.api.v1.extract.stream(\*\*params) -> str
-- client.api.v1.extract.sync(\*\*params) -> ExtractResponse
+- client.extract.async\_(\*\*params) -> ExtractResponse
+- client.extract.batch(\*\*params) -> BatchExtractResponse
+- client.extract.stream(\*\*params) -> str
+- client.extract.sync(\*\*params) -> ExtractResponse
-#### Results
+## Results
Types:
```python
-from docstrange.types.api.v1.extract import ResultListResponse
+from docstrange.types.extract import ExtractionListResponse, PaginationInfo
```
Methods:
-- client.api.v1.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
-- client.api.v1.extract.results.list(\*\*params) -> ResultListResponse
+- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
+- client.extract.results.list(\*\*params) -> ExtractionListResponse
-### Classify
+# Classify
Types:
```python
-from docstrange.types.api.v1 import (
+from docstrange.types import (
+ BatchClassifyRequestBody,
+ BatchClassifyResponse,
+ ClassifyRequestBody,
+ ClassifyResponse,
FileClassificationResult,
- ClassifyBatchResponse,
- ClassifySyncResponse,
+ PageClassification,
)
```
Methods:
-- client.api.v1.classify.batch(\*\*params) -> ClassifyBatchResponse
-- client.api.v1.classify.sync(\*\*params) -> ClassifySyncResponse
+- client.classify.batch(\*\*params) -> BatchClassifyResponse
+- client.classify.sync(\*\*params) -> ClassifyResponse
# Chat
+Types:
+
+```python
+from docstrange.types import ChatCompletionsRequest
+```
+
Methods:
- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index f7a66e4..4c5bcc4 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,9 +31,10 @@
)
if TYPE_CHECKING:
- from .resources import api, chat
+ from .resources import chat, extract, classify
from .resources.chat import ChatResource, AsyncChatResource
- from .resources.api.api import APIResource, AsyncAPIResource
+ from .resources.classify import ClassifyResource, AsyncClassifyResource
+ from .resources.extract.extract import ExtractResource, AsyncExtractResource
__all__ = [
"Timeout",
@@ -103,10 +104,16 @@ def __init__(
)
@cached_property
- def api(self) -> APIResource:
- from .resources.api import APIResource
+ def extract(self) -> ExtractResource:
+ from .resources.extract import ExtractResource
- return APIResource(self)
+ return ExtractResource(self)
+
+ @cached_property
+ def classify(self) -> ClassifyResource:
+ from .resources.classify import ClassifyResource
+
+ return ClassifyResource(self)
@cached_property
def chat(self) -> ChatResource:
@@ -283,10 +290,16 @@ def __init__(
)
@cached_property
- def api(self) -> AsyncAPIResource:
- from .resources.api import AsyncAPIResource
+ def extract(self) -> AsyncExtractResource:
+ from .resources.extract import AsyncExtractResource
- return AsyncAPIResource(self)
+ return AsyncExtractResource(self)
+
+ @cached_property
+ def classify(self) -> AsyncClassifyResource:
+ from .resources.classify import AsyncClassifyResource
+
+ return AsyncClassifyResource(self)
@cached_property
def chat(self) -> AsyncChatResource:
@@ -414,10 +427,16 @@ def __init__(self, client: Docstrange) -> None:
self._client = client
@cached_property
- def api(self) -> api.APIResourceWithRawResponse:
- from .resources.api import APIResourceWithRawResponse
+ def extract(self) -> extract.ExtractResourceWithRawResponse:
+ from .resources.extract import ExtractResourceWithRawResponse
+
+ return ExtractResourceWithRawResponse(self._client.extract)
+
+ @cached_property
+ def classify(self) -> classify.ClassifyResourceWithRawResponse:
+ from .resources.classify import ClassifyResourceWithRawResponse
- return APIResourceWithRawResponse(self._client.api)
+ return ClassifyResourceWithRawResponse(self._client.classify)
@cached_property
def chat(self) -> chat.ChatResourceWithRawResponse:
@@ -433,10 +452,16 @@ def __init__(self, client: AsyncDocstrange) -> None:
self._client = client
@cached_property
- def api(self) -> api.AsyncAPIResourceWithRawResponse:
- from .resources.api import AsyncAPIResourceWithRawResponse
+ def extract(self) -> extract.AsyncExtractResourceWithRawResponse:
+ from .resources.extract import AsyncExtractResourceWithRawResponse
- return AsyncAPIResourceWithRawResponse(self._client.api)
+ return AsyncExtractResourceWithRawResponse(self._client.extract)
+
+ @cached_property
+ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
+ from .resources.classify import AsyncClassifyResourceWithRawResponse
+
+ return AsyncClassifyResourceWithRawResponse(self._client.classify)
@cached_property
def chat(self) -> chat.AsyncChatResourceWithRawResponse:
@@ -452,10 +477,16 @@ def __init__(self, client: Docstrange) -> None:
self._client = client
@cached_property
- def api(self) -> api.APIResourceWithStreamingResponse:
- from .resources.api import APIResourceWithStreamingResponse
+ def extract(self) -> extract.ExtractResourceWithStreamingResponse:
+ from .resources.extract import ExtractResourceWithStreamingResponse
- return APIResourceWithStreamingResponse(self._client.api)
+ return ExtractResourceWithStreamingResponse(self._client.extract)
+
+ @cached_property
+ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
+ from .resources.classify import ClassifyResourceWithStreamingResponse
+
+ return ClassifyResourceWithStreamingResponse(self._client.classify)
@cached_property
def chat(self) -> chat.ChatResourceWithStreamingResponse:
@@ -471,10 +502,16 @@ def __init__(self, client: AsyncDocstrange) -> None:
self._client = client
@cached_property
- def api(self) -> api.AsyncAPIResourceWithStreamingResponse:
- from .resources.api import AsyncAPIResourceWithStreamingResponse
+ def extract(self) -> extract.AsyncExtractResourceWithStreamingResponse:
+ from .resources.extract import AsyncExtractResourceWithStreamingResponse
+
+ return AsyncExtractResourceWithStreamingResponse(self._client.extract)
+
+ @cached_property
+ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
+ from .resources.classify import AsyncClassifyResourceWithStreamingResponse
- return AsyncAPIResourceWithStreamingResponse(self._client.api)
+ return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
@cached_property
def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index a4f482d..a3172dd 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,13 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from .api import (
- APIResource,
- AsyncAPIResource,
- APIResourceWithRawResponse,
- AsyncAPIResourceWithRawResponse,
- APIResourceWithStreamingResponse,
- AsyncAPIResourceWithStreamingResponse,
-)
from .chat import (
ChatResource,
AsyncChatResource,
@@ -16,14 +8,36 @@
ChatResourceWithStreamingResponse,
AsyncChatResourceWithStreamingResponse,
)
+from .extract import (
+ ExtractResource,
+ AsyncExtractResource,
+ ExtractResourceWithRawResponse,
+ AsyncExtractResourceWithRawResponse,
+ ExtractResourceWithStreamingResponse,
+ AsyncExtractResourceWithStreamingResponse,
+)
+from .classify import (
+ ClassifyResource,
+ AsyncClassifyResource,
+ ClassifyResourceWithRawResponse,
+ AsyncClassifyResourceWithRawResponse,
+ ClassifyResourceWithStreamingResponse,
+ AsyncClassifyResourceWithStreamingResponse,
+)
__all__ = [
- "APIResource",
- "AsyncAPIResource",
- "APIResourceWithRawResponse",
- "AsyncAPIResourceWithRawResponse",
- "APIResourceWithStreamingResponse",
- "AsyncAPIResourceWithStreamingResponse",
+ "ExtractResource",
+ "AsyncExtractResource",
+ "ExtractResourceWithRawResponse",
+ "AsyncExtractResourceWithRawResponse",
+ "ExtractResourceWithStreamingResponse",
+ "AsyncExtractResourceWithStreamingResponse",
+ "ClassifyResource",
+ "AsyncClassifyResource",
+ "ClassifyResourceWithRawResponse",
+ "AsyncClassifyResourceWithRawResponse",
+ "ClassifyResourceWithStreamingResponse",
+ "AsyncClassifyResourceWithStreamingResponse",
"ChatResource",
"AsyncChatResource",
"ChatResourceWithRawResponse",
diff --git a/src/docstrange/resources/api/__init__.py b/src/docstrange/resources/api/__init__.py
deleted file mode 100644
index c0c6efa..0000000
--- a/src/docstrange/resources/api/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .v1 import (
- V1Resource,
- AsyncV1Resource,
- V1ResourceWithRawResponse,
- AsyncV1ResourceWithRawResponse,
- V1ResourceWithStreamingResponse,
- AsyncV1ResourceWithStreamingResponse,
-)
-from .api import (
- APIResource,
- AsyncAPIResource,
- APIResourceWithRawResponse,
- AsyncAPIResourceWithRawResponse,
- APIResourceWithStreamingResponse,
- AsyncAPIResourceWithStreamingResponse,
-)
-
-__all__ = [
- "V1Resource",
- "AsyncV1Resource",
- "V1ResourceWithRawResponse",
- "AsyncV1ResourceWithRawResponse",
- "V1ResourceWithStreamingResponse",
- "AsyncV1ResourceWithStreamingResponse",
- "APIResource",
- "AsyncAPIResource",
- "APIResourceWithRawResponse",
- "AsyncAPIResourceWithRawResponse",
- "APIResourceWithStreamingResponse",
- "AsyncAPIResourceWithStreamingResponse",
-]
diff --git a/src/docstrange/resources/api/api.py b/src/docstrange/resources/api/api.py
deleted file mode 100644
index b771b29..0000000
--- a/src/docstrange/resources/api/api.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from ... import _resource
-from .v1.v1 import (
- V1Resource,
- AsyncV1Resource,
- V1ResourceWithRawResponse,
- AsyncV1ResourceWithRawResponse,
- V1ResourceWithStreamingResponse,
- AsyncV1ResourceWithStreamingResponse,
-)
-from ..._compat import cached_property
-
-__all__ = ["APIResource", "AsyncAPIResource"]
-
-
-class APIResource(_resource.SyncAPIResource):
- @cached_property
- def v1(self) -> V1Resource:
- return V1Resource(self._client)
-
- @cached_property
- def with_raw_response(self) -> APIResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return APIResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> APIResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return APIResourceWithStreamingResponse(self)
-
-
-class AsyncAPIResource(_resource.AsyncAPIResource):
- @cached_property
- def v1(self) -> AsyncV1Resource:
- return AsyncV1Resource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncAPIResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncAPIResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncAPIResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncAPIResourceWithStreamingResponse(self)
-
-
-class APIResourceWithRawResponse:
- def __init__(self, api: APIResource) -> None:
- self._api = api
-
- @cached_property
- def v1(self) -> V1ResourceWithRawResponse:
- return V1ResourceWithRawResponse(self._api.v1)
-
-
-class AsyncAPIResourceWithRawResponse:
- def __init__(self, api: AsyncAPIResource) -> None:
- self._api = api
-
- @cached_property
- def v1(self) -> AsyncV1ResourceWithRawResponse:
- return AsyncV1ResourceWithRawResponse(self._api.v1)
-
-
-class APIResourceWithStreamingResponse:
- def __init__(self, api: APIResource) -> None:
- self._api = api
-
- @cached_property
- def v1(self) -> V1ResourceWithStreamingResponse:
- return V1ResourceWithStreamingResponse(self._api.v1)
-
-
-class AsyncAPIResourceWithStreamingResponse:
- def __init__(self, api: AsyncAPIResource) -> None:
- self._api = api
-
- @cached_property
- def v1(self) -> AsyncV1ResourceWithStreamingResponse:
- return AsyncV1ResourceWithStreamingResponse(self._api.v1)
diff --git a/src/docstrange/resources/api/v1/__init__.py b/src/docstrange/resources/api/v1/__init__.py
deleted file mode 100644
index 422780c..0000000
--- a/src/docstrange/resources/api/v1/__init__.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .v1 import (
- V1Resource,
- AsyncV1Resource,
- V1ResourceWithRawResponse,
- AsyncV1ResourceWithRawResponse,
- V1ResourceWithStreamingResponse,
- AsyncV1ResourceWithStreamingResponse,
-)
-from .extract import (
- ExtractResource,
- AsyncExtractResource,
- ExtractResourceWithRawResponse,
- AsyncExtractResourceWithRawResponse,
- ExtractResourceWithStreamingResponse,
- AsyncExtractResourceWithStreamingResponse,
-)
-from .classify import (
- ClassifyResource,
- AsyncClassifyResource,
- ClassifyResourceWithRawResponse,
- AsyncClassifyResourceWithRawResponse,
- ClassifyResourceWithStreamingResponse,
- AsyncClassifyResourceWithStreamingResponse,
-)
-
-__all__ = [
- "ExtractResource",
- "AsyncExtractResource",
- "ExtractResourceWithRawResponse",
- "AsyncExtractResourceWithRawResponse",
- "ExtractResourceWithStreamingResponse",
- "AsyncExtractResourceWithStreamingResponse",
- "ClassifyResource",
- "AsyncClassifyResource",
- "ClassifyResourceWithRawResponse",
- "AsyncClassifyResourceWithRawResponse",
- "ClassifyResourceWithStreamingResponse",
- "AsyncClassifyResourceWithStreamingResponse",
- "V1Resource",
- "AsyncV1Resource",
- "V1ResourceWithRawResponse",
- "AsyncV1ResourceWithRawResponse",
- "V1ResourceWithStreamingResponse",
- "AsyncV1ResourceWithStreamingResponse",
-]
diff --git a/src/docstrange/resources/api/v1/v1.py b/src/docstrange/resources/api/v1/v1.py
deleted file mode 100644
index 1dbb99b..0000000
--- a/src/docstrange/resources/api/v1/v1.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .classify import (
- ClassifyResource,
- AsyncClassifyResource,
- ClassifyResourceWithRawResponse,
- AsyncClassifyResourceWithRawResponse,
- ClassifyResourceWithStreamingResponse,
- AsyncClassifyResourceWithStreamingResponse,
-)
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from .extract.extract import (
- ExtractResource,
- AsyncExtractResource,
- ExtractResourceWithRawResponse,
- AsyncExtractResourceWithRawResponse,
- ExtractResourceWithStreamingResponse,
- AsyncExtractResourceWithStreamingResponse,
-)
-
-__all__ = ["V1Resource", "AsyncV1Resource"]
-
-
-class V1Resource(SyncAPIResource):
- @cached_property
- def extract(self) -> ExtractResource:
- return ExtractResource(self._client)
-
- @cached_property
- def classify(self) -> ClassifyResource:
- return ClassifyResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> V1ResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return V1ResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> V1ResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return V1ResourceWithStreamingResponse(self)
-
-
-class AsyncV1Resource(AsyncAPIResource):
- @cached_property
- def extract(self) -> AsyncExtractResource:
- return AsyncExtractResource(self._client)
-
- @cached_property
- def classify(self) -> AsyncClassifyResource:
- return AsyncClassifyResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncV1ResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncV1ResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncV1ResourceWithStreamingResponse(self)
-
-
-class V1ResourceWithRawResponse:
- def __init__(self, v1: V1Resource) -> None:
- self._v1 = v1
-
- @cached_property
- def extract(self) -> ExtractResourceWithRawResponse:
- return ExtractResourceWithRawResponse(self._v1.extract)
-
- @cached_property
- def classify(self) -> ClassifyResourceWithRawResponse:
- return ClassifyResourceWithRawResponse(self._v1.classify)
-
-
-class AsyncV1ResourceWithRawResponse:
- def __init__(self, v1: AsyncV1Resource) -> None:
- self._v1 = v1
-
- @cached_property
- def extract(self) -> AsyncExtractResourceWithRawResponse:
- return AsyncExtractResourceWithRawResponse(self._v1.extract)
-
- @cached_property
- def classify(self) -> AsyncClassifyResourceWithRawResponse:
- return AsyncClassifyResourceWithRawResponse(self._v1.classify)
-
-
-class V1ResourceWithStreamingResponse:
- def __init__(self, v1: V1Resource) -> None:
- self._v1 = v1
-
- @cached_property
- def extract(self) -> ExtractResourceWithStreamingResponse:
- return ExtractResourceWithStreamingResponse(self._v1.extract)
-
- @cached_property
- def classify(self) -> ClassifyResourceWithStreamingResponse:
- return ClassifyResourceWithStreamingResponse(self._v1.classify)
-
-
-class AsyncV1ResourceWithStreamingResponse:
- def __init__(self, v1: AsyncV1Resource) -> None:
- self._v1 = v1
-
- @cached_property
- def extract(self) -> AsyncExtractResourceWithStreamingResponse:
- return AsyncExtractResourceWithStreamingResponse(self._v1.extract)
-
- @cached_property
- def classify(self) -> AsyncClassifyResourceWithStreamingResponse:
- return AsyncClassifyResourceWithStreamingResponse(self._v1.classify)
diff --git a/src/docstrange/resources/api/v1/classify.py b/src/docstrange/resources/classify.py
similarity index 81%
rename from src/docstrange/resources/api/v1/classify.py
rename to src/docstrange/resources/classify.py
index fdd4c7a..5476a59 100644
--- a/src/docstrange/resources/api/v1/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,32 +2,22 @@
from __future__ import annotations
-from typing import Mapping, cast
-
import httpx
-from ...._types import (
- Body,
- Query,
- Headers,
- NotGiven,
- FileTypes,
- SequenceNotStr,
- not_given,
-)
-from ...._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
-from ...._compat import cached_property
-from ...._resource import SyncAPIResource, AsyncAPIResource
-from ...._response import (
+from ..types import classify_sync_params, classify_batch_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ...._base_client import make_request_options
-from ....types.api.v1 import classify_sync_params, classify_batch_params
-from ....types.api.v1.classify_sync_response import ClassifySyncResponse
-from ....types.api.v1.classify_batch_response import ClassifyBatchResponse
+from .._base_client import make_request_options
+from ..types.classify_response import ClassifyResponse
+from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -63,7 +53,7 @@ def batch(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ClassifyBatchResponse:
+ ) -> BatchClassifyResponse:
"""
Classify multiple documents asynchronously (max 50 files).
@@ -83,25 +73,23 @@ def batch(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "files": files,
- }
- )
- extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/batch",
- body=maybe_transform(body, classify_batch_params.ClassifyBatchParams),
- files=extracted_files,
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ClassifyBatchResponse,
+ cast_to=BatchClassifyResponse,
)
def sync(
@@ -115,7 +103,7 @@ def sync(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ClassifySyncResponse:
+ ) -> ClassifyResponse:
"""
Classify a single document into predefined categories synchronously.
@@ -137,25 +125,23 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ClassifySyncResponse,
+ cast_to=ClassifyResponse,
)
@@ -190,7 +176,7 @@ async def batch(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ClassifyBatchResponse:
+ ) -> BatchClassifyResponse:
"""
Classify multiple documents asynchronously (max 50 files).
@@ -210,25 +196,23 @@ async def batch(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "files": files,
- }
- )
- extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/batch",
- body=await async_maybe_transform(body, classify_batch_params.ClassifyBatchParams),
- files=extracted_files,
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ClassifyBatchResponse,
+ cast_to=BatchClassifyResponse,
)
async def sync(
@@ -242,7 +226,7 @@ async def sync(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ClassifySyncResponse:
+ ) -> ClassifyResponse:
"""
Classify a single document into predefined categories synchronously.
@@ -264,25 +248,23 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ClassifySyncResponse,
+ cast_to=ClassifyResponse,
)
diff --git a/src/docstrange/resources/api/v1/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
similarity index 100%
rename from src/docstrange/resources/api/v1/extract/__init__.py
rename to src/docstrange/resources/extract/__init__.py
diff --git a/src/docstrange/resources/api/v1/extract/extract.py b/src/docstrange/resources/extract/extract.py
similarity index 89%
rename from src/docstrange/resources/api/v1/extract/extract.py
rename to src/docstrange/resources/extract/extract.py
index 94ced26..bed3b08 100644
--- a/src/docstrange/resources/api/v1/extract/extract.py
+++ b/src/docstrange/resources/extract/extract.py
@@ -2,11 +2,11 @@
from __future__ import annotations
-from typing import Mapping, cast
from typing_extensions import Literal
import httpx
+from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
from .results import (
ResultsResource,
AsyncResultsResource,
@@ -15,7 +15,7 @@
ResultsResourceWithStreamingResponse,
AsyncResultsResourceWithStreamingResponse,
)
-from ....._types import (
+from ..._types import (
Body,
Omit,
Query,
@@ -26,21 +26,20 @@
omit,
not_given,
)
-from ....._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
-from ....._compat import cached_property
-from ....._resource import SyncAPIResource, AsyncAPIResource
-from ....._response import (
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ....._streaming import Stream, AsyncStream
-from ....._base_client import make_request_options
-from .....types.api.v1 import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
-from .....types.api.v1.extract_response import ExtractResponse
-from .....types.api.v1.extract_batch_response import ExtractBatchResponse
-from .....types.api.v1.extract_stream_response import ExtractStreamResponse
+from ..._streaming import Stream, AsyncStream
+from ..._base_client import make_request_options
+from ...types.extract_response import ExtractResponse
+from ...types.batch_extract_response import BatchExtractResponse
+from ...types.extract_stream_response import ExtractStreamResponse
__all__ = ["ExtractResource", "AsyncExtractResource"]
@@ -166,7 +165,7 @@ def batch(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractBatchResponse:
+ ) -> BatchExtractResponse:
"""Process multiple files asynchronously (max 50 files).
All files share the same
@@ -185,30 +184,28 @@ def batch(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/extract/batch",
- body=maybe_transform(body, extract_batch_params.ExtractBatchParams),
- files=extracted_files,
+ body=maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExtractBatchResponse,
+ cast_to=BatchExtractResponse,
)
def stream(
@@ -277,29 +274,27 @@ def stream(
timeout: Override the client-level default timeout for this request, in seconds
"""
extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- body = deepcopy_minimal(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/extract/stream",
- body=maybe_transform(body, extract_stream_params.ExtractStreamParams),
- files=files,
+ body=maybe_transform(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -511,7 +506,7 @@ async def batch(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractBatchResponse:
+ ) -> BatchExtractResponse:
"""Process multiple files asynchronously (max 50 files).
All files share the same
@@ -530,30 +525,28 @@ async def batch(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/extract/batch",
- body=await async_maybe_transform(body, extract_batch_params.ExtractBatchParams),
- files=extracted_files,
+ body=await async_maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExtractBatchResponse,
+ cast_to=BatchExtractResponse,
)
async def stream(
@@ -622,29 +615,27 @@ async def stream(
timeout: Override the client-level default timeout for this request, in seconds
"""
extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- body = deepcopy_minimal(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/extract/stream",
- body=await async_maybe_transform(body, extract_stream_params.ExtractStreamParams),
- files=files,
+ body=await async_maybe_transform(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/docstrange/resources/api/v1/extract/results.py b/src/docstrange/resources/extract/results.py
similarity index 93%
rename from src/docstrange/resources/api/v1/extract/results.py
rename to src/docstrange/resources/extract/results.py
index 51832fe..7f92467 100644
--- a/src/docstrange/resources/api/v1/extract/results.py
+++ b/src/docstrange/resources/extract/results.py
@@ -6,20 +6,20 @@
import httpx
-from ....._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ....._utils import maybe_transform, async_maybe_transform
-from ....._compat import cached_property
-from ....._resource import SyncAPIResource, AsyncAPIResource
-from ....._response import (
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ....._base_client import make_request_options
-from .....types.api.v1.extract import result_list_params, result_retrieve_params
-from .....types.api.v1.extract_response import ExtractResponse
-from .....types.api.v1.extract.result_list_response import ResultListResponse
+from ..._base_client import make_request_options
+from ...types.extract import result_list_params, result_retrieve_params
+from ...types.extract_response import ExtractResponse
+from ...types.extract.extraction_list_response import ExtractionListResponse
__all__ = ["ResultsResource", "AsyncResultsResource"]
@@ -100,7 +100,7 @@ def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ResultListResponse:
+ ) -> ExtractionListResponse:
"""
List all extraction jobs for the authenticated user (paginated).
@@ -130,7 +130,7 @@ def list(
result_list_params.ResultListParams,
),
),
- cast_to=ResultListResponse,
+ cast_to=ExtractionListResponse,
)
@@ -210,7 +210,7 @@ async def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ResultListResponse:
+ ) -> ExtractionListResponse:
"""
List all extraction jobs for the authenticated user (paginated).
@@ -240,7 +240,7 @@ async def list(
result_list_params.ResultListParams,
),
),
- cast_to=ResultListResponse,
+ cast_to=ExtractionListResponse,
)
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index fa4182c..a18a10a 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -2,4 +2,20 @@
from __future__ import annotations
+from .extract_response import ExtractResponse as ExtractResponse
+from .classify_response import ClassifyResponse as ClassifyResponse
+from .extraction_result import ExtractionResult as ExtractionResult
+from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
+from .extraction_metadata import ExtractionMetadata as ExtractionMetadata
+from .page_classification import PageClassification as PageClassification
+from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
+from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
+from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
+from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
+from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
+from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
+from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
+from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
+from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
+from .file_classification_result import FileClassificationResult as FileClassificationResult
from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/api/__init__.py b/src/docstrange/types/api/__init__.py
deleted file mode 100644
index f8ee8b1..0000000
--- a/src/docstrange/types/api/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
diff --git a/src/docstrange/types/api/v1/__init__.py b/src/docstrange/types/api/v1/__init__.py
deleted file mode 100644
index 45ae7db..0000000
--- a/src/docstrange/types/api/v1/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .extract_response import ExtractResponse as ExtractResponse
-from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
-from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
-from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
-from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
-from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
-from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
-from .classify_sync_response import ClassifySyncResponse as ClassifySyncResponse
-from .extract_batch_response import ExtractBatchResponse as ExtractBatchResponse
-from .classify_batch_response import ClassifyBatchResponse as ClassifyBatchResponse
-from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
-from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
-from .file_classification_result import FileClassificationResult as FileClassificationResult
diff --git a/src/docstrange/types/api/v1/extraction_format_result.py b/src/docstrange/types/api/v1/extraction_format_result.py
deleted file mode 100644
index a95327b..0000000
--- a/src/docstrange/types/api/v1/extraction_format_result.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Union, Optional
-
-from ...._models import BaseModel
-
-__all__ = ["ExtractionFormatResult", "Metadata"]
-
-
-class Metadata(BaseModel):
- bounding_boxes: Optional[object] = None
- """Element coordinates with page dimensions"""
-
- confidence_score: Optional[object] = None
- """Confidence scores per field"""
-
-
-class ExtractionFormatResult(BaseModel):
- content: Union[str, object]
- """Extracted content"""
-
- metadata: Optional[Metadata] = None
diff --git a/src/docstrange/types/api/v1/classify_batch_response.py b/src/docstrange/types/batch_classify_response.py
similarity index 76%
rename from src/docstrange/types/api/v1/classify_batch_response.py
rename to src/docstrange/types/batch_classify_response.py
index d6a6b1b..a36e5a8 100644
--- a/src/docstrange/types/api/v1/classify_batch_response.py
+++ b/src/docstrange/types/batch_classify_response.py
@@ -2,13 +2,13 @@
from typing import List
-from ...._models import BaseModel
+from .._models import BaseModel
from .file_classification_result import FileClassificationResult
-__all__ = ["ClassifyBatchResponse"]
+__all__ = ["BatchClassifyResponse"]
-class ClassifyBatchResponse(BaseModel):
+class BatchClassifyResponse(BaseModel):
batch_id: str
failed_files: int
diff --git a/src/docstrange/types/api/v1/extract_batch_response.py b/src/docstrange/types/batch_extract_response.py
similarity index 75%
rename from src/docstrange/types/api/v1/extract_batch_response.py
rename to src/docstrange/types/batch_extract_response.py
index 2e0bfd8..4e73773 100644
--- a/src/docstrange/types/api/v1/extract_batch_response.py
+++ b/src/docstrange/types/batch_extract_response.py
@@ -2,13 +2,13 @@
from typing import List
-from ...._models import BaseModel
+from .._models import BaseModel
from .extract_response import ExtractResponse
-__all__ = ["ExtractBatchResponse"]
+__all__ = ["BatchExtractResponse"]
-class ExtractBatchResponse(BaseModel):
+class BatchExtractResponse(BaseModel):
accepted_files: int
batch_id: str
diff --git a/src/docstrange/types/api/v1/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
similarity index 89%
rename from src/docstrange/types/api/v1/classify_batch_params.py
rename to src/docstrange/types/classify_batch_params.py
index 25f2754..5cac9e3 100644
--- a/src/docstrange/types/api/v1/classify_batch_params.py
+++ b/src/docstrange/types/classify_batch_params.py
@@ -4,7 +4,7 @@
from typing_extensions import Required, TypedDict
-from ...._types import FileTypes, SequenceNotStr
+from .._types import FileTypes, SequenceNotStr
__all__ = ["ClassifyBatchParams"]
diff --git a/src/docstrange/types/api/v1/classify_sync_response.py b/src/docstrange/types/classify_response.py
similarity index 71%
rename from src/docstrange/types/api/v1/classify_sync_response.py
rename to src/docstrange/types/classify_response.py
index 67383a7..fdebbb0 100644
--- a/src/docstrange/types/api/v1/classify_sync_response.py
+++ b/src/docstrange/types/classify_response.py
@@ -2,13 +2,13 @@
from typing import Optional
-from ...._models import BaseModel
+from .._models import BaseModel
from .file_classification_result import FileClassificationResult
-__all__ = ["ClassifySyncResponse"]
+__all__ = ["ClassifyResponse"]
-class ClassifySyncResponse(BaseModel):
+class ClassifyResponse(BaseModel):
message: str
success: bool
diff --git a/src/docstrange/types/api/v1/classify_sync_params.py b/src/docstrange/types/classify_sync_params.py
similarity index 93%
rename from src/docstrange/types/api/v1/classify_sync_params.py
rename to src/docstrange/types/classify_sync_params.py
index 7b2be33..772427d 100644
--- a/src/docstrange/types/api/v1/classify_sync_params.py
+++ b/src/docstrange/types/classify_sync_params.py
@@ -4,7 +4,7 @@
from typing_extensions import Required, TypedDict
-from ...._types import FileTypes
+from .._types import FileTypes
__all__ = ["ClassifySyncParams"]
diff --git a/src/docstrange/types/api/v1/extract/__init__.py b/src/docstrange/types/extract/__init__.py
similarity index 64%
rename from src/docstrange/types/api/v1/extract/__init__.py
rename to src/docstrange/types/extract/__init__.py
index 07fc82d..387a007 100644
--- a/src/docstrange/types/api/v1/extract/__init__.py
+++ b/src/docstrange/types/extract/__init__.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+from .pagination_info import PaginationInfo as PaginationInfo
from .result_list_params import ResultListParams as ResultListParams
-from .result_list_response import ResultListResponse as ResultListResponse
from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
+from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
new file mode 100644
index 0000000..26a12e7
--- /dev/null
+++ b/src/docstrange/types/extract/extraction_list_response.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from .pagination_info import PaginationInfo
+from ..extract_response import ExtractResponse
+
+__all__ = ["ExtractionListResponse"]
+
+
+class ExtractionListResponse(BaseModel):
+ pagination: PaginationInfo
+
+ results: List[ExtractResponse]
+
+ success: bool
diff --git a/src/docstrange/types/api/v1/extract/result_list_response.py b/src/docstrange/types/extract/pagination_info.py
similarity index 50%
rename from src/docstrange/types/api/v1/extract/result_list_response.py
rename to src/docstrange/types/extract/pagination_info.py
index 86bfdeb..7a678a9 100644
--- a/src/docstrange/types/api/v1/extract/result_list_response.py
+++ b/src/docstrange/types/extract/pagination_info.py
@@ -1,14 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List, Optional
+from typing import Optional
-from ....._models import BaseModel
-from ..extract_response import ExtractResponse
+from ..._models import BaseModel
-__all__ = ["ResultListResponse", "Pagination"]
+__all__ = ["PaginationInfo"]
-class Pagination(BaseModel):
+class PaginationInfo(BaseModel):
has_next: Optional[bool] = None
has_previous: Optional[bool] = None
@@ -20,11 +19,3 @@ class Pagination(BaseModel):
total_count: Optional[int] = None
total_pages: Optional[int] = None
-
-
-class ResultListResponse(BaseModel):
- pagination: Pagination
-
- results: List[ExtractResponse]
-
- success: bool
diff --git a/src/docstrange/types/api/v1/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
similarity index 100%
rename from src/docstrange/types/api/v1/extract/result_list_params.py
rename to src/docstrange/types/extract/result_list_params.py
diff --git a/src/docstrange/types/api/v1/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
similarity index 100%
rename from src/docstrange/types/api/v1/extract/result_retrieve_params.py
rename to src/docstrange/types/extract/result_retrieve_params.py
diff --git a/src/docstrange/types/api/v1/extract_async_params.py b/src/docstrange/types/extract_async_params.py
similarity index 97%
rename from src/docstrange/types/api/v1/extract_async_params.py
rename to src/docstrange/types/extract_async_params.py
index cb154f4..d638b09 100644
--- a/src/docstrange/types/api/v1/extract_async_params.py
+++ b/src/docstrange/types/extract_async_params.py
@@ -4,7 +4,7 @@
from typing_extensions import Literal, Required, TypedDict
-from ...._types import FileTypes
+from .._types import FileTypes
__all__ = ["ExtractAsyncParams"]
diff --git a/src/docstrange/types/api/v1/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
similarity index 92%
rename from src/docstrange/types/api/v1/extract_batch_params.py
rename to src/docstrange/types/extract_batch_params.py
index 566c7dc..bdc7b29 100644
--- a/src/docstrange/types/api/v1/extract_batch_params.py
+++ b/src/docstrange/types/extract_batch_params.py
@@ -4,7 +4,7 @@
from typing_extensions import Literal, Required, TypedDict
-from ...._types import FileTypes, SequenceNotStr
+from .._types import FileTypes, SequenceNotStr
__all__ = ["ExtractBatchParams"]
diff --git a/src/docstrange/types/api/v1/extract_response.py b/src/docstrange/types/extract_response.py
similarity index 57%
rename from src/docstrange/types/api/v1/extract_response.py
rename to src/docstrange/types/extract_response.py
index 875b357..9d93ead 100644
--- a/src/docstrange/types/api/v1/extract_response.py
+++ b/src/docstrange/types/extract_response.py
@@ -4,24 +4,10 @@
from datetime import datetime
from typing_extensions import Literal
-from pydantic import Field as FieldInfo
+from .._models import BaseModel
+from .extraction_result import ExtractionResult
-from ...._models import BaseModel
-from .extraction_format_result import ExtractionFormatResult
-
-__all__ = ["ExtractResponse", "Result"]
-
-
-class Result(BaseModel):
- """Results by format (only requested formats populated)"""
-
- csv: Optional[ExtractionFormatResult] = None
-
- html: Optional[ExtractionFormatResult] = None
-
- json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
-
- markdown: Optional[ExtractionFormatResult] = None
+__all__ = ["ExtractResponse"]
class ExtractResponse(BaseModel):
@@ -48,5 +34,5 @@ class ExtractResponse(BaseModel):
processing_time: Optional[float] = None
"""Time in seconds"""
- result: Optional[Result] = None
+ result: Optional[ExtractionResult] = None
"""Results by format (only requested formats populated)"""
diff --git a/src/docstrange/types/api/v1/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
similarity index 97%
rename from src/docstrange/types/api/v1/extract_stream_params.py
rename to src/docstrange/types/extract_stream_params.py
index 3d5a388..2a8e9e3 100644
--- a/src/docstrange/types/api/v1/extract_stream_params.py
+++ b/src/docstrange/types/extract_stream_params.py
@@ -4,7 +4,7 @@
from typing_extensions import Literal, Required, TypedDict
-from ...._types import FileTypes
+from .._types import FileTypes
__all__ = ["ExtractStreamParams"]
diff --git a/src/docstrange/types/api/v1/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
similarity index 100%
rename from src/docstrange/types/api/v1/extract_stream_response.py
rename to src/docstrange/types/extract_stream_response.py
diff --git a/src/docstrange/types/api/v1/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
similarity index 97%
rename from src/docstrange/types/api/v1/extract_sync_params.py
rename to src/docstrange/types/extract_sync_params.py
index 50cc59a..e3c4bea 100644
--- a/src/docstrange/types/api/v1/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -4,7 +4,7 @@
from typing_extensions import Literal, Required, TypedDict
-from ...._types import FileTypes
+from .._types import FileTypes
__all__ = ["ExtractSyncParams"]
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
new file mode 100644
index 0000000..579500c
--- /dev/null
+++ b/src/docstrange/types/extraction_format_result.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union, Optional
+
+from .._models import BaseModel
+from .extraction_metadata import ExtractionMetadata
+
+__all__ = ["ExtractionFormatResult"]
+
+
+class ExtractionFormatResult(BaseModel):
+ content: Union[str, object]
+ """Extracted content"""
+
+ metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/extraction_metadata.py b/src/docstrange/types/extraction_metadata.py
new file mode 100644
index 0000000..9792ba0
--- /dev/null
+++ b/src/docstrange/types/extraction_metadata.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["ExtractionMetadata"]
+
+
+class ExtractionMetadata(BaseModel):
+ bounding_boxes: Optional[object] = None
+ """Element coordinates with page dimensions"""
+
+ confidence_score: Optional[object] = None
+ """Confidence scores per field"""
diff --git a/src/docstrange/types/extraction_result.py b/src/docstrange/types/extraction_result.py
new file mode 100644
index 0000000..57b2928
--- /dev/null
+++ b/src/docstrange/types/extraction_result.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+from .extraction_format_result import ExtractionFormatResult
+
+__all__ = ["ExtractionResult"]
+
+
+class ExtractionResult(BaseModel):
+ """Results by format (only requested formats populated)"""
+
+ csv: Optional[ExtractionFormatResult] = None
+
+ html: Optional[ExtractionFormatResult] = None
+
+ json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
+
+ markdown: Optional[ExtractionFormatResult] = None
diff --git a/src/docstrange/types/file_classification_result.py b/src/docstrange/types/file_classification_result.py
new file mode 100644
index 0000000..397d924
--- /dev/null
+++ b/src/docstrange/types/file_classification_result.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+from .page_classification import PageClassification
+
+__all__ = ["FileClassificationResult"]
+
+
+class FileClassificationResult(BaseModel):
+ filename: str
+
+ pages: List[PageClassification]
+
+ total_pages: int
+
+ error: Optional[str] = None
+
+ processing_time: Optional[float] = None
+ """Time in seconds"""
+
+ record_id: Optional[str] = None
+ """Record ID for polling results"""
diff --git a/src/docstrange/types/api/v1/file_classification_result.py b/src/docstrange/types/page_classification.py
similarity index 56%
rename from src/docstrange/types/api/v1/file_classification_result.py
rename to src/docstrange/types/page_classification.py
index 2ec6b94..2099524 100644
--- a/src/docstrange/types/api/v1/file_classification_result.py
+++ b/src/docstrange/types/page_classification.py
@@ -1,13 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List, Optional
+from typing import Optional
-from ...._models import BaseModel
+from .._models import BaseModel
-__all__ = ["FileClassificationResult", "Page"]
+__all__ = ["PageClassification"]
-class Page(BaseModel):
+class PageClassification(BaseModel):
category: str
"""Matched category name or 'Other' if no match"""
@@ -25,19 +25,3 @@ class Page(BaseModel):
'Invoice_Amazon_Electronics'). Always provided - contains a more detailed
classification than the category.
"""
-
-
-class FileClassificationResult(BaseModel):
- filename: str
-
- pages: List[Page]
-
- total_pages: int
-
- error: Optional[str] = None
-
- processing_time: Optional[float] = None
- """Time in seconds"""
-
- record_id: Optional[str] = None
- """Record ID for polling results"""
diff --git a/tests/api_resources/api/v1/__init__.py b/tests/api_resources/api/v1/__init__.py
deleted file mode 100644
index fd8019a..0000000
--- a/tests/api_resources/api/v1/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/api/v1/extract/__init__.py b/tests/api_resources/api/v1/extract/__init__.py
deleted file mode 100644
index fd8019a..0000000
--- a/tests/api_resources/api/v1/extract/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/api/__init__.py b/tests/api_resources/extract/__init__.py
similarity index 100%
rename from tests/api_resources/api/__init__.py
rename to tests/api_resources/extract/__init__.py
diff --git a/tests/api_resources/api/v1/extract/test_results.py b/tests/api_resources/extract/test_results.py
similarity index 76%
rename from tests/api_resources/api/v1/extract/test_results.py
rename to tests/api_resources/extract/test_results.py
index 5c842cc..372de57 100644
--- a/tests/api_resources/api/v1/extract/test_results.py
+++ b/tests/api_resources/extract/test_results.py
@@ -9,8 +9,8 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types.api.v1 import ExtractResponse
-from docstrange.types.api.v1.extract import ResultListResponse
+from docstrange.types import ExtractResponse
+from docstrange.types.extract import ExtractionListResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -21,7 +21,7 @@ class TestResults:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_retrieve(self, client: Docstrange) -> None:
- result = client.api.v1.extract.results.retrieve(
+ result = client.extract.results.retrieve(
record_id="record_id",
)
assert_matches_type(ExtractResponse, result, path=["response"])
@@ -29,7 +29,7 @@ def test_method_retrieve(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
- result = client.api.v1.extract.results.retrieve(
+ result = client.extract.results.retrieve(
record_id="record_id",
include_content=True,
)
@@ -38,7 +38,7 @@ def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_retrieve(self, client: Docstrange) -> None:
- response = client.api.v1.extract.results.with_raw_response.retrieve(
+ response = client.extract.results.with_raw_response.retrieve(
record_id="record_id",
)
@@ -50,7 +50,7 @@ def test_raw_response_retrieve(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_retrieve(self, client: Docstrange) -> None:
- with client.api.v1.extract.results.with_streaming_response.retrieve(
+ with client.extract.results.with_streaming_response.retrieve(
record_id="record_id",
) as response:
assert not response.is_closed
@@ -65,46 +65,46 @@ def test_streaming_response_retrieve(self, client: Docstrange) -> None:
@parametrize
def test_path_params_retrieve(self, client: Docstrange) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- client.api.v1.extract.results.with_raw_response.retrieve(
+ client.extract.results.with_raw_response.retrieve(
record_id="",
)
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_list(self, client: Docstrange) -> None:
- result = client.api.v1.extract.results.list()
- assert_matches_type(ResultListResponse, result, path=["response"])
+ result = client.extract.results.list()
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_list_with_all_params(self, client: Docstrange) -> None:
- result = client.api.v1.extract.results.list(
+ result = client.extract.results.list(
page=1,
page_size=1,
sort_by="created_at",
sort_order="asc",
)
- assert_matches_type(ResultListResponse, result, path=["response"])
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_list(self, client: Docstrange) -> None:
- response = client.api.v1.extract.results.with_raw_response.list()
+ response = client.extract.results.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = response.parse()
- assert_matches_type(ResultListResponse, result, path=["response"])
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_list(self, client: Docstrange) -> None:
- with client.api.v1.extract.results.with_streaming_response.list() as response:
+ with client.extract.results.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = response.parse()
- assert_matches_type(ResultListResponse, result, path=["response"])
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -117,7 +117,7 @@ class TestAsyncResults:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.api.v1.extract.results.retrieve(
+ result = await async_client.extract.results.retrieve(
record_id="record_id",
)
assert_matches_type(ExtractResponse, result, path=["response"])
@@ -125,7 +125,7 @@ async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.api.v1.extract.results.retrieve(
+ result = await async_client.extract.results.retrieve(
record_id="record_id",
include_content=True,
)
@@ -134,7 +134,7 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstran
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.extract.results.with_raw_response.retrieve(
+ response = await async_client.extract.results.with_raw_response.retrieve(
record_id="record_id",
)
@@ -146,7 +146,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> Non
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.extract.results.with_streaming_response.retrieve(
+ async with async_client.extract.results.with_streaming_response.retrieve(
record_id="record_id",
) as response:
assert not response.is_closed
@@ -161,45 +161,45 @@ async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange)
@parametrize
async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- await async_client.api.v1.extract.results.with_raw_response.retrieve(
+ await async_client.extract.results.with_raw_response.retrieve(
record_id="",
)
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_list(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.api.v1.extract.results.list()
- assert_matches_type(ResultListResponse, result, path=["response"])
+ result = await async_client.extract.results.list()
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.api.v1.extract.results.list(
+ result = await async_client.extract.results.list(
page=1,
page_size=1,
sort_by="created_at",
sort_order="asc",
)
- assert_matches_type(ResultListResponse, result, path=["response"])
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.extract.results.with_raw_response.list()
+ response = await async_client.extract.results.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = await response.parse()
- assert_matches_type(ResultListResponse, result, path=["response"])
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.extract.results.with_streaming_response.list() as response:
+ async with async_client.extract.results.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = await response.parse()
- assert_matches_type(ResultListResponse, result, path=["response"])
+ assert_matches_type(ExtractionListResponse, result, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/api/v1/test_classify.py b/tests/api_resources/test_classify.py
similarity index 78%
rename from tests/api_resources/api/v1/test_classify.py
rename to tests/api_resources/test_classify.py
index c8a9b4c..b4377f6 100644
--- a/tests/api_resources/api/v1/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,10 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types.api.v1 import (
- ClassifySyncResponse,
- ClassifyBatchResponse,
-)
+from docstrange.types import ClassifyResponse, BatchClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -23,16 +20,16 @@ class TestClassify:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_batch(self, client: Docstrange) -> None:
- classify = client.api.v1.classify.batch(
+ classify = client.classify.batch(
categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
files=[b"raw file contents"],
)
- assert_matches_type(ClassifyBatchResponse, classify, path=["response"])
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.api.v1.classify.with_raw_response.batch(
+ response = client.classify.with_raw_response.batch(
categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
files=[b"raw file contents"],
)
@@ -40,12 +37,12 @@ def test_raw_response_batch(self, client: Docstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = response.parse()
- assert_matches_type(ClassifyBatchResponse, classify, path=["response"])
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.api.v1.classify.with_streaming_response.batch(
+ with client.classify.with_streaming_response.batch(
categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
files=[b"raw file contents"],
) as response:
@@ -53,23 +50,23 @@ def test_streaming_response_batch(self, client: Docstrange) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = response.parse()
- assert_matches_type(ClassifyBatchResponse, classify, path=["response"])
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
assert cast(Any, response.is_closed) is True
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
- classify = client.api.v1.classify.sync(
+ classify = client.classify.sync(
categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
- assert_matches_type(ClassifySyncResponse, classify, path=["response"])
+ assert_matches_type(ClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
- response = client.api.v1.classify.with_raw_response.sync(
+ response = client.classify.with_raw_response.sync(
categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
@@ -77,12 +74,12 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = response.parse()
- assert_matches_type(ClassifySyncResponse, classify, path=["response"])
+ assert_matches_type(ClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
- with client.api.v1.classify.with_streaming_response.sync(
+ with client.classify.with_streaming_response.sync(
categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
) as response:
@@ -90,7 +87,7 @@ def test_streaming_response_sync(self, client: Docstrange) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = response.parse()
- assert_matches_type(ClassifySyncResponse, classify, path=["response"])
+ assert_matches_type(ClassifyResponse, classify, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -103,16 +100,16 @@ class TestAsyncClassify:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- classify = await async_client.api.v1.classify.batch(
+ classify = await async_client.classify.batch(
categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
files=[b"raw file contents"],
)
- assert_matches_type(ClassifyBatchResponse, classify, path=["response"])
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.classify.with_raw_response.batch(
+ response = await async_client.classify.with_raw_response.batch(
categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
files=[b"raw file contents"],
)
@@ -120,12 +117,12 @@ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = await response.parse()
- assert_matches_type(ClassifyBatchResponse, classify, path=["response"])
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.classify.with_streaming_response.batch(
+ async with async_client.classify.with_streaming_response.batch(
categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
files=[b"raw file contents"],
) as response:
@@ -133,23 +130,23 @@ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) ->
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = await response.parse()
- assert_matches_type(ClassifyBatchResponse, classify, path=["response"])
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
assert cast(Any, response.is_closed) is True
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
- classify = await async_client.api.v1.classify.sync(
+ classify = await async_client.classify.sync(
categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
- assert_matches_type(ClassifySyncResponse, classify, path=["response"])
+ assert_matches_type(ClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.classify.with_raw_response.sync(
+ response = await async_client.classify.with_raw_response.sync(
categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
@@ -157,12 +154,12 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = await response.parse()
- assert_matches_type(ClassifySyncResponse, classify, path=["response"])
+ assert_matches_type(ClassifyResponse, classify, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.classify.with_streaming_response.sync(
+ async with async_client.classify.with_streaming_response.sync(
categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
) as response:
@@ -170,6 +167,6 @@ async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
classify = await response.parse()
- assert_matches_type(ClassifySyncResponse, classify, path=["response"])
+ assert_matches_type(ClassifyResponse, classify, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/api/v1/test_extract.py b/tests/api_resources/test_extract.py
similarity index 84%
rename from tests/api_resources/api/v1/test_extract.py
rename to tests/api_resources/test_extract.py
index a1a05ff..ffdac33 100644
--- a/tests/api_resources/api/v1/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,9 +9,9 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types.api.v1 import (
+from docstrange.types import (
ExtractResponse,
- ExtractBatchResponse,
+ BatchExtractResponse,
)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -23,7 +23,7 @@ class TestExtract:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_async(self, client: Docstrange) -> None:
- extract = client.api.v1.extract.async_(
+ extract = client.extract.async_(
output_format="markdown",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -31,7 +31,7 @@ def test_method_async(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_async_with_all_params(self, client: Docstrange) -> None:
- extract = client.api.v1.extract.async_(
+ extract = client.extract.async_(
output_format="markdown",
csv_options="",
custom_instructions="",
@@ -47,7 +47,7 @@ def test_method_async_with_all_params(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_async(self, client: Docstrange) -> None:
- response = client.api.v1.extract.with_raw_response.async_(
+ response = client.extract.with_raw_response.async_(
output_format="markdown",
)
@@ -59,7 +59,7 @@ def test_raw_response_async(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_async(self, client: Docstrange) -> None:
- with client.api.v1.extract.with_streaming_response.async_(
+ with client.extract.with_streaming_response.async_(
output_format="markdown",
) as response:
assert not response.is_closed
@@ -73,16 +73,16 @@ def test_streaming_response_async(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_batch(self, client: Docstrange) -> None:
- extract = client.api.v1.extract.batch(
+ extract = client.extract.batch(
files=[b"raw file contents"],
output_format="markdown",
)
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_batch_with_all_params(self, client: Docstrange) -> None:
- extract = client.api.v1.extract.batch(
+ extract = client.extract.batch(
files=[b"raw file contents"],
output_format="markdown",
csv_options="csv_options",
@@ -91,12 +91,12 @@ def test_method_batch_with_all_params(self, client: Docstrange) -> None:
json_options="json_options",
prompt_mode="append",
)
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.api.v1.extract.with_raw_response.batch(
+ response = client.extract.with_raw_response.batch(
files=[b"raw file contents"],
output_format="markdown",
)
@@ -104,12 +104,12 @@ def test_raw_response_batch(self, client: Docstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
extract = response.parse()
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.api.v1.extract.with_streaming_response.batch(
+ with client.extract.with_streaming_response.batch(
files=[b"raw file contents"],
output_format="markdown",
) as response:
@@ -117,14 +117,14 @@ def test_streaming_response_batch(self, client: Docstrange) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
extract = response.parse()
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
assert cast(Any, response.is_closed) is True
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
def test_method_stream(self, client: Docstrange) -> None:
- extract_stream = client.api.v1.extract.stream(
+ extract_stream = client.extract.stream(
output_format="markdown",
)
extract_stream.response.close()
@@ -132,7 +132,7 @@ def test_method_stream(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
def test_method_stream_with_all_params(self, client: Docstrange) -> None:
- extract_stream = client.api.v1.extract.stream(
+ extract_stream = client.extract.stream(
output_format="markdown",
csv_options="",
custom_instructions="",
@@ -149,7 +149,7 @@ def test_method_stream_with_all_params(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
def test_raw_response_stream(self, client: Docstrange) -> None:
- response = client.api.v1.extract.with_raw_response.stream(
+ response = client.extract.with_raw_response.stream(
output_format="markdown",
)
@@ -160,7 +160,7 @@ def test_raw_response_stream(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
def test_streaming_response_stream(self, client: Docstrange) -> None:
- with client.api.v1.extract.with_streaming_response.stream(
+ with client.extract.with_streaming_response.stream(
output_format="markdown",
) as response:
assert not response.is_closed
@@ -174,7 +174,7 @@ def test_streaming_response_stream(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
- extract = client.api.v1.extract.sync(
+ extract = client.extract.sync(
output_format="markdown",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -182,7 +182,7 @@ def test_method_sync(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync_with_all_params(self, client: Docstrange) -> None:
- extract = client.api.v1.extract.sync(
+ extract = client.extract.sync(
output_format="markdown",
csv_options="",
custom_instructions="",
@@ -198,7 +198,7 @@ def test_method_sync_with_all_params(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
- response = client.api.v1.extract.with_raw_response.sync(
+ response = client.extract.with_raw_response.sync(
output_format="markdown",
)
@@ -210,7 +210,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
- with client.api.v1.extract.with_streaming_response.sync(
+ with client.extract.with_streaming_response.sync(
output_format="markdown",
) as response:
assert not response.is_closed
@@ -230,7 +230,7 @@ class TestAsyncExtract:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_async(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.api.v1.extract.async_(
+ extract = await async_client.extract.async_(
output_format="markdown",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -238,7 +238,7 @@ async def test_method_async(self, async_client: AsyncDocstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.api.v1.extract.async_(
+ extract = await async_client.extract.async_(
output_format="markdown",
csv_options="",
custom_instructions="",
@@ -254,7 +254,7 @@ async def test_method_async_with_all_params(self, async_client: AsyncDocstrange)
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.extract.with_raw_response.async_(
+ response = await async_client.extract.with_raw_response.async_(
output_format="markdown",
)
@@ -266,7 +266,7 @@ async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.extract.with_streaming_response.async_(
+ async with async_client.extract.with_streaming_response.async_(
output_format="markdown",
) as response:
assert not response.is_closed
@@ -280,16 +280,16 @@ async def test_streaming_response_async(self, async_client: AsyncDocstrange) ->
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.api.v1.extract.batch(
+ extract = await async_client.extract.batch(
files=[b"raw file contents"],
output_format="markdown",
)
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.api.v1.extract.batch(
+ extract = await async_client.extract.batch(
files=[b"raw file contents"],
output_format="markdown",
csv_options="csv_options",
@@ -298,12 +298,12 @@ async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange)
json_options="json_options",
prompt_mode="append",
)
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.extract.with_raw_response.batch(
+ response = await async_client.extract.with_raw_response.batch(
files=[b"raw file contents"],
output_format="markdown",
)
@@ -311,12 +311,12 @@ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
extract = await response.parse()
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.extract.with_streaming_response.batch(
+ async with async_client.extract.with_streaming_response.batch(
files=[b"raw file contents"],
output_format="markdown",
) as response:
@@ -324,14 +324,14 @@ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) ->
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
extract = await response.parse()
- assert_matches_type(ExtractBatchResponse, extract, path=["response"])
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
assert cast(Any, response.is_closed) is True
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.api.v1.extract.stream(
+ extract_stream = await async_client.extract.stream(
output_format="markdown",
)
await extract_stream.response.aclose()
@@ -339,7 +339,7 @@ async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.api.v1.extract.stream(
+ extract_stream = await async_client.extract.stream(
output_format="markdown",
csv_options="",
custom_instructions="",
@@ -356,7 +356,7 @@ async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.extract.with_raw_response.stream(
+ response = await async_client.extract.with_raw_response.stream(
output_format="markdown",
)
@@ -367,7 +367,7 @@ async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
@pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
@parametrize
async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.extract.with_streaming_response.stream(
+ async with async_client.extract.with_streaming_response.stream(
output_format="markdown",
) as response:
assert not response.is_closed
@@ -381,7 +381,7 @@ async def test_streaming_response_stream(self, async_client: AsyncDocstrange) ->
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.api.v1.extract.sync(
+ extract = await async_client.extract.sync(
output_format="markdown",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -389,7 +389,7 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.api.v1.extract.sync(
+ extract = await async_client.extract.sync(
output_format="markdown",
csv_options="",
custom_instructions="",
@@ -405,7 +405,7 @@ async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange)
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.api.v1.extract.with_raw_response.sync(
+ response = await async_client.extract.with_raw_response.sync(
output_format="markdown",
)
@@ -417,7 +417,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
- async with async_client.api.v1.extract.with_streaming_response.sync(
+ async with async_client.extract.with_streaming_response.sync(
output_format="markdown",
) as response:
assert not response.is_closed
diff --git a/tests/test_client.py b/tests/test_client.py
index 89f274a..3d576f6 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -862,7 +862,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.api.v1.extract.with_streaming_response.sync(output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@@ -872,7 +872,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.api.v1.extract.with_streaming_response.sync(output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -901,7 +901,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.api.v1.extract.with_raw_response.sync(output_format="markdown")
+ response = client.extract.with_raw_response.sync(output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -925,7 +925,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.api.v1.extract.with_raw_response.sync(
+ response = client.extract.with_raw_response.sync(
output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
@@ -950,7 +950,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.api.v1.extract.with_raw_response.sync(
+ response = client.extract.with_raw_response.sync(
output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
@@ -1768,7 +1768,7 @@ async def test_retrying_timeout_errors_doesnt_leak(
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- await async_client.api.v1.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
+ await async_client.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1780,7 +1780,7 @@ async def test_retrying_status_errors_doesnt_leak(
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- await async_client.api.v1.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
+ await async_client.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
assert _get_open_connections(async_client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1809,7 +1809,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.api.v1.extract.with_raw_response.sync(output_format="markdown")
+ response = await client.extract.with_raw_response.sync(output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1833,7 +1833,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.api.v1.extract.with_raw_response.sync(
+ response = await client.extract.with_raw_response.sync(
output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
@@ -1858,7 +1858,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.api.v1.extract.with_raw_response.sync(
+ response = await client.extract.with_raw_response.sync(
output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
From 1ccd49469cb3b08b7df945cb54737572dd04097e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 07:10:35 +0000
Subject: [PATCH 07/26] Add pagination config, fix readme params
---
.stats.yml | 2 +-
src/docstrange/pagination.py | 48 ++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 src/docstrange/pagination.py
diff --git a/.stats.yml b/.stats.yml
index 1774d1c..d0e1c4a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 5095aef18b1e8c018bc58e39d6f4b23d
+config_hash: 618498b0a12e1535b716981b83e1f760
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
new file mode 100644
index 0000000..9c8dc87
--- /dev/null
+++ b/src/docstrange/pagination.py
@@ -0,0 +1,48 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Generic, TypeVar, Optional, cast
+from typing_extensions import override
+
+from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
+
+__all__ = ["SyncPageNumberPagination", "AsyncPageNumberPagination"]
+
+_T = TypeVar("_T")
+
+
+class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
+ items: List[_T]
+ total_count: Optional[int] = None
+ has_next: Optional[bool] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ items = self.items
+ if not items:
+ return []
+ return items
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ return PageInfo(params={"page": last_page + 1})
+
+
+class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
+ items: List[_T]
+ total_count: Optional[int] = None
+ has_next: Optional[bool] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ items = self.items
+ if not items:
+ return []
+ return items
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ return PageInfo(params={"page": last_page + 1})
From 4fc3af695ffd8664a21c22edb00a4c23cfdf7186 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 07:12:51 +0000
Subject: [PATCH 08/26] Fix pagination schema to match nested response
structure
---
.stats.yml | 2 +-
README.md | 61 +++++++++++++++++++++
api.md | 2 +-
src/docstrange/pagination.py | 45 ++++++++++-----
src/docstrange/resources/extract/results.py | 22 ++++----
tests/api_resources/extract/test_results.py | 18 +++---
6 files changed, 116 insertions(+), 34 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index d0e1c4a..e1a1b53 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 618498b0a12e1535b716981b83e1f760
+config_hash: de4c18021060af5ebd13aa207675d379
diff --git a/README.md b/README.md
index 9532911..917f116 100644
--- a/README.md
+++ b/README.md
@@ -112,6 +112,67 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
+## Pagination
+
+List methods in the Docstrange API are paginated.
+
+This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
+
+```python
+from docstrange import Docstrange
+
+client = Docstrange()
+
+all_results = []
+# Automatically fetches more pages as needed.
+for result in client.extract.results.list():
+ # Do something with result here
+ all_results.append(result)
+print(all_results)
+```
+
+Or, asynchronously:
+
+```python
+import asyncio
+from docstrange import AsyncDocstrange
+
+client = AsyncDocstrange()
+
+
+async def main() -> None:
+ all_results = []
+ # Iterate through items across all pages, issuing requests as needed.
+ async for result in client.extract.results.list():
+ all_results.append(result)
+ print(all_results)
+
+
+asyncio.run(main())
+```
+
+Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
+
+```python
+first_page = await client.extract.results.list()
+if first_page.has_next_page():
+ print(f"will fetch next page using these details: {first_page.next_page_info()}")
+ next_page = await first_page.get_next_page()
+ print(f"number of items we just fetched: {len(next_page.results)}")
+
+# Remove `await` for non-async usage.
+```
+
+Or just work directly with the returned data:
+
+```python
+first_page = await client.extract.results.list()
+for result in first_page.results:
+ print(result.record_id)
+
+# Remove `await` for non-async usage.
+```
+
## File uploads
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)`.
diff --git a/api.md b/api.md
index 2f2f496..7ccbce8 100644
--- a/api.md
+++ b/api.md
@@ -34,7 +34,7 @@ from docstrange.types.extract import ExtractionListResponse, PaginationInfo
Methods:
- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
-- client.extract.results.list(\*\*params) -> ExtractionListResponse
+- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[ExtractResponse]
# Classify
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
index 9c8dc87..e926095 100644
--- a/src/docstrange/pagination.py
+++ b/src/docstrange/pagination.py
@@ -3,46 +3,65 @@
from typing import List, Generic, TypeVar, Optional, cast
from typing_extensions import override
+from ._models import BaseModel
from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
-__all__ = ["SyncPageNumberPagination", "AsyncPageNumberPagination"]
+__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
_T = TypeVar("_T")
-class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
- items: List[_T]
- total_count: Optional[int] = None
+class PageNumberPaginationPagination(BaseModel):
has_next: Optional[bool] = None
+ total_count: Optional[int] = None
+
+
+class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
+
@override
def _get_page_items(self) -> List[_T]:
- items = self.items
- if not items:
+ results = self.results
+ if not results:
return []
- return items
+ return results
@override
def next_page_info(self) -> Optional[PageInfo]:
last_page = cast("int | None", self._options.params.get("page")) or 1
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
return PageInfo(params={"page": last_page + 1})
class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
- items: List[_T]
- total_count: Optional[int] = None
- has_next: Optional[bool] = None
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
@override
def _get_page_items(self) -> List[_T]:
- items = self.items
- if not items:
+ results = self.results
+ if not results:
return []
- return items
+ return results
@override
def next_page_info(self) -> Optional[PageInfo]:
last_page = cast("int | None", self._options.params.get("page")) or 1
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
return PageInfo(params={"page": last_page + 1})
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
index 7f92467..1533ac2 100644
--- a/src/docstrange/resources/extract/results.py
+++ b/src/docstrange/resources/extract/results.py
@@ -16,10 +16,10 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ..._base_client import make_request_options
+from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+from ..._base_client import AsyncPaginator, make_request_options
from ...types.extract import result_list_params, result_retrieve_params
from ...types.extract_response import ExtractResponse
-from ...types.extract.extraction_list_response import ExtractionListResponse
__all__ = ["ResultsResource", "AsyncResultsResource"]
@@ -100,7 +100,7 @@ def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractionListResponse:
+ ) -> SyncPageNumberPagination[ExtractResponse]:
"""
List all extraction jobs for the authenticated user (paginated).
@@ -113,8 +113,9 @@ def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return self._get(
+ return self._get_api_list(
"/api/v1/extract/results",
+ page=SyncPageNumberPagination[ExtractResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -130,7 +131,7 @@ def list(
result_list_params.ResultListParams,
),
),
- cast_to=ExtractionListResponse,
+ model=ExtractResponse,
)
@@ -196,7 +197,7 @@ async def retrieve(
cast_to=ExtractResponse,
)
- async def list(
+ def list(
self,
*,
page: int | Omit = omit,
@@ -210,7 +211,7 @@ async def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractionListResponse:
+ ) -> AsyncPaginator[ExtractResponse, AsyncPageNumberPagination[ExtractResponse]]:
"""
List all extraction jobs for the authenticated user (paginated).
@@ -223,14 +224,15 @@ async def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return await self._get(
+ return self._get_api_list(
"/api/v1/extract/results",
+ page=AsyncPageNumberPagination[ExtractResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=await async_maybe_transform(
+ query=maybe_transform(
{
"page": page,
"page_size": page_size,
@@ -240,7 +242,7 @@ async def list(
result_list_params.ResultListParams,
),
),
- cast_to=ExtractionListResponse,
+ model=ExtractResponse,
)
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
index 372de57..ee1d5f5 100644
--- a/tests/api_resources/extract/test_results.py
+++ b/tests/api_resources/extract/test_results.py
@@ -10,7 +10,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
from docstrange.types import ExtractResponse
-from docstrange.types.extract import ExtractionListResponse
+from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -73,7 +73,7 @@ def test_path_params_retrieve(self, client: Docstrange) -> None:
@parametrize
def test_method_list(self, client: Docstrange) -> None:
result = client.extract.results.list()
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
@@ -84,7 +84,7 @@ def test_method_list_with_all_params(self, client: Docstrange) -> None:
sort_by="created_at",
sort_order="asc",
)
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
@@ -94,7 +94,7 @@ def test_raw_response_list(self, client: Docstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = response.parse()
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
@@ -104,7 +104,7 @@ def test_streaming_response_list(self, client: Docstrange) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = response.parse()
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -169,7 +169,7 @@ async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None
@parametrize
async def test_method_list(self, async_client: AsyncDocstrange) -> None:
result = await async_client.extract.results.list()
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
@@ -180,7 +180,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncDocstrange)
sort_by="created_at",
sort_order="asc",
)
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
@@ -190,7 +190,7 @@ async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = await response.parse()
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
@@ -200,6 +200,6 @@ async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
result = await response.parse()
- assert_matches_type(ExtractionListResponse, result, path=["response"])
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
assert cast(Any, response.is_closed) is True
From 5b89e7feb42bbe9d637c4d60a021fde1291e9577 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 07:14:34 +0000
Subject: [PATCH 09/26] codegen metadata
---
.stats.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.stats.yml b/.stats.yml
index e1a1b53..bf2dc75 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: de4c18021060af5ebd13aa207675d379
+config_hash: 1baaa1d64ec6584ed1f597237a15f16d
From 43a5e850d97e9bed4b1dd1ec1d07a9073b9db21d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 08:09:54 +0000
Subject: [PATCH 10/26] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index bf2dc75..cf66929 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-bc5cce7d8bf43d1c05a2b9463a3ea8d64ab2fa909d074ddfc1a09665a61c3642.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 1baaa1d64ec6584ed1f597237a15f16d
+config_hash: b3698eed9a1747fbb26a5f19a066b037
From e1b836c1338d0c34eeae2156a19ae1a9a68b9269 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 13:22:54 +0000
Subject: [PATCH 11/26] chore(internal): fix lint error on Python 3.14
---
src/docstrange/_utils/_compat.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/docstrange/_utils/_compat.py b/src/docstrange/_utils/_compat.py
index dd70323..2c70b29 100644
--- a/src/docstrange/_utils/_compat.py
+++ b/src/docstrange/_utils/_compat.py
@@ -26,7 +26,7 @@ def is_union(tp: Optional[Type[Any]]) -> bool:
else:
import types
- return tp is Union or tp is types.UnionType
+ return tp is Union or tp is types.UnionType # type: ignore[comparison-overlap]
def is_typeddict(tp: Type[Any]) -> bool:
From d88ea559f0d053b2bac7d05b139c31533e8d4843 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 20:24:51 +0000
Subject: [PATCH 12/26] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index cf66929..1cf30c8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-bc5cce7d8bf43d1c05a2b9463a3ea8d64ab2fa909d074ddfc1a09665a61c3642.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-f82f6b5e52eaf62639b7ae43348bbf66363cc95592391797a0ae297d3c7f738f.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: b3698eed9a1747fbb26a5f19a066b037
+config_hash: 52d207e1bd85f0522c9cae6ea8805784
From 3d12679a9c3ff3c58563bc17c15fab514dd3aa36 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 21:25:23 +0000
Subject: [PATCH 13/26] feat(api): api update
---
.stats.yml | 8 +-
README.md | 71 +-
api.md | 52 +-
src/docstrange/_client.py | 41 +-
src/docstrange/pagination.py | 67 --
src/docstrange/resources/__init__.py | 14 -
src/docstrange/resources/chat.py | 218 -----
src/docstrange/resources/classify.py | 175 +---
src/docstrange/resources/extract.py | 199 +++++
src/docstrange/resources/extract/__init__.py | 33 -
src/docstrange/resources/extract/extract.py | 814 ------------------
src/docstrange/resources/extract/results.py | 294 -------
src/docstrange/types/__init__.py | 13 -
.../types/batch_classify_response.py | 24 -
.../types/batch_extract_response.py | 24 -
.../types/chat_create_completion_params.py | 45 -
src/docstrange/types/classify_batch_params.py | 17 -
src/docstrange/types/classify_response.py | 5 -
src/docstrange/types/classify_sync_params.py | 7 +-
src/docstrange/types/extract/__init__.py | 8 -
.../types/extract/extraction_list_response.py | 17 -
.../types/extract/pagination_info.py | 21 -
.../types/extract/result_list_params.py | 17 -
.../types/extract/result_retrieve_params.py | 12 -
src/docstrange/types/extract_async_params.py | 45 -
src/docstrange/types/extract_batch_params.py | 27 -
src/docstrange/types/extract_response.py | 25 +-
src/docstrange/types/extract_stream_params.py | 47 -
.../types/extract_stream_response.py | 7 -
src/docstrange/types/extract_sync_params.py | 38 +-
.../types/extraction_format_result.py | 15 -
src/docstrange/types/extraction_metadata.py | 15 -
src/docstrange/types/extraction_result.py | 22 -
.../types/file_classification_result.py | 24 -
src/docstrange/types/page_classification.py | 27 -
tests/api_resources/extract/__init__.py | 1 -
tests/api_resources/extract/test_results.py | 205 -----
tests/api_resources/test_chat.py | 183 ----
tests/api_resources/test_classify.py | 88 +-
tests/api_resources/test_extract.py | 353 +-------
tests/test_client.py | 28 +-
41 files changed, 291 insertions(+), 3055 deletions(-)
delete mode 100644 src/docstrange/pagination.py
delete mode 100644 src/docstrange/resources/chat.py
create mode 100644 src/docstrange/resources/extract.py
delete mode 100644 src/docstrange/resources/extract/__init__.py
delete mode 100644 src/docstrange/resources/extract/extract.py
delete mode 100644 src/docstrange/resources/extract/results.py
delete mode 100644 src/docstrange/types/batch_classify_response.py
delete mode 100644 src/docstrange/types/batch_extract_response.py
delete mode 100644 src/docstrange/types/chat_create_completion_params.py
delete mode 100644 src/docstrange/types/classify_batch_params.py
delete mode 100644 src/docstrange/types/extract/__init__.py
delete mode 100644 src/docstrange/types/extract/extraction_list_response.py
delete mode 100644 src/docstrange/types/extract/pagination_info.py
delete mode 100644 src/docstrange/types/extract/result_list_params.py
delete mode 100644 src/docstrange/types/extract/result_retrieve_params.py
delete mode 100644 src/docstrange/types/extract_async_params.py
delete mode 100644 src/docstrange/types/extract_batch_params.py
delete mode 100644 src/docstrange/types/extract_stream_params.py
delete mode 100644 src/docstrange/types/extract_stream_response.py
delete mode 100644 src/docstrange/types/extraction_format_result.py
delete mode 100644 src/docstrange/types/extraction_metadata.py
delete mode 100644 src/docstrange/types/extraction_result.py
delete mode 100644 src/docstrange/types/file_classification_result.py
delete mode 100644 src/docstrange/types/page_classification.py
delete mode 100644 tests/api_resources/extract/__init__.py
delete mode 100644 tests/api_resources/extract/test_results.py
delete mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index 1cf30c8..06a3238 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-f82f6b5e52eaf62639b7ae43348bbf66363cc95592391797a0ae297d3c7f738f.yml
-openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 52d207e1bd85f0522c9cae6ea8805784
+configured_endpoints: 2
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-00ea96039f73fd253b5042c3e5c1ae800ca6b3bbde585408d20a46f73ae87ecf.yml
+openapi_spec_hash: b4046d95714426b15edb8ac003f904c6
+config_hash: 6f0ab1fd6c4433590ee82d88ab5298a7
diff --git a/README.md b/README.md
index 917f116..622faec 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ client = Docstrange(
)
extract_response = client.extract.sync(
+ file=b"raw file contents",
output_format="markdown",
)
print(extract_response.record_id)
@@ -59,6 +60,7 @@ client = AsyncDocstrange(
async def main() -> None:
extract_response = await client.extract.sync(
+ file=b"raw file contents",
output_format="markdown",
)
print(extract_response.record_id)
@@ -95,6 +97,7 @@ async def main() -> None:
http_client=DefaultAioHttpClient(),
) as client:
extract_response = await client.extract.sync(
+ file=b"raw file contents",
output_format="markdown",
)
print(extract_response.record_id)
@@ -112,67 +115,6 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
-## Pagination
-
-List methods in the Docstrange API are paginated.
-
-This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
-
-```python
-from docstrange import Docstrange
-
-client = Docstrange()
-
-all_results = []
-# Automatically fetches more pages as needed.
-for result in client.extract.results.list():
- # Do something with result here
- all_results.append(result)
-print(all_results)
-```
-
-Or, asynchronously:
-
-```python
-import asyncio
-from docstrange import AsyncDocstrange
-
-client = AsyncDocstrange()
-
-
-async def main() -> None:
- all_results = []
- # Iterate through items across all pages, issuing requests as needed.
- async for result in client.extract.results.list():
- all_results.append(result)
- print(all_results)
-
-
-asyncio.run(main())
-```
-
-Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
-
-```python
-first_page = await client.extract.results.list()
-if first_page.has_next_page():
- print(f"will fetch next page using these details: {first_page.next_page_info()}")
- next_page = await first_page.get_next_page()
- print(f"number of items we just fetched: {len(next_page.results)}")
-
-# Remove `await` for non-async usage.
-```
-
-Or just work directly with the returned data:
-
-```python
-first_page = await client.extract.results.list()
-for result in first_page.results:
- print(result.record_id)
-
-# Remove `await` for non-async usage.
-```
-
## File uploads
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)`.
@@ -184,8 +126,8 @@ from docstrange import Docstrange
client = Docstrange()
client.extract.sync(
- output_format="markdown",
file=Path("/path/to/file"),
+ output_format="output_format",
)
```
@@ -208,6 +150,7 @@ client = Docstrange()
try:
client.extract.sync(
+ file=b"raw file contents",
output_format="markdown",
)
except docstrange.APIConnectionError as e:
@@ -253,6 +196,7 @@ client = Docstrange(
# Or, configure per-request:
client.with_options(max_retries=5).extract.sync(
+ file=b"raw file contents",
output_format="markdown",
)
```
@@ -278,6 +222,7 @@ client = Docstrange(
# Override per-request:
client.with_options(timeout=5.0).extract.sync(
+ file=b"raw file contents",
output_format="markdown",
)
```
@@ -321,6 +266,7 @@ from docstrange import Docstrange
client = Docstrange()
response = client.extract.with_raw_response.sync(
+ file=b"raw file contents",
output_format="markdown",
)
print(response.headers.get('X-My-Header'))
@@ -341,6 +287,7 @@ To stream the response body, use `.with_streaming_response` instead, which requi
```python
with client.extract.with_streaming_response.sync(
+ file=b"raw file contents",
output_format="markdown",
) as response:
print(response.headers.get("X-My-Header"))
diff --git a/api.md b/api.md
index 7ccbce8..0cac7c9 100644
--- a/api.md
+++ b/api.md
@@ -3,67 +3,21 @@
Types:
```python
-from docstrange.types import (
- BatchExtractRequestBody,
- BatchExtractResponse,
- ExtractRequestBody,
- ExtractResponse,
- ExtractionFormatResult,
- ExtractionMetadata,
- ExtractionResult,
- StreamExtractRequestBody,
- ExtractStreamResponse,
-)
+from docstrange.types import ExtractResponse
```
Methods:
-- client.extract.async\_(\*\*params) -> ExtractResponse
-- client.extract.batch(\*\*params) -> BatchExtractResponse
-- client.extract.stream(\*\*params) -> str
-- client.extract.sync(\*\*params) -> ExtractResponse
-
-## Results
-
-Types:
-
-```python
-from docstrange.types.extract import ExtractionListResponse, PaginationInfo
-```
-
-Methods:
-
-- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
-- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[ExtractResponse]
+- client.extract.sync(\*\*params) -> ExtractResponse
# Classify
Types:
```python
-from docstrange.types import (
- BatchClassifyRequestBody,
- BatchClassifyResponse,
- ClassifyRequestBody,
- ClassifyResponse,
- FileClassificationResult,
- PageClassification,
-)
+from docstrange.types import ClassifyResponse
```
Methods:
-- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
-
-# Chat
-
-Types:
-
-```python
-from docstrange.types import ChatCompletionsRequest
-```
-
-Methods:
-
-- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 4c5bcc4..42d282d 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,10 +31,9 @@
)
if TYPE_CHECKING:
- from .resources import chat, extract, classify
- from .resources.chat import ChatResource, AsyncChatResource
+ from .resources import extract, classify
+ from .resources.extract import ExtractResource, AsyncExtractResource
from .resources.classify import ClassifyResource, AsyncClassifyResource
- from .resources.extract.extract import ExtractResource, AsyncExtractResource
__all__ = [
"Timeout",
@@ -115,12 +114,6 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
- @cached_property
- def chat(self) -> ChatResource:
- from .resources.chat import ChatResource
-
- return ChatResource(self)
-
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -301,12 +294,6 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
- @cached_property
- def chat(self) -> AsyncChatResource:
- from .resources.chat import AsyncChatResource
-
- return AsyncChatResource(self)
-
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -438,12 +425,6 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithRawResponse:
- from .resources.chat import ChatResourceWithRawResponse
-
- return ChatResourceWithRawResponse(self._client.chat)
-
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -463,12 +444,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithRawResponse:
- from .resources.chat import AsyncChatResourceWithRawResponse
-
- return AsyncChatResourceWithRawResponse(self._client.chat)
-
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -488,12 +463,6 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithStreamingResponse:
- from .resources.chat import ChatResourceWithStreamingResponse
-
- return ChatResourceWithStreamingResponse(self._client.chat)
-
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -513,12 +482,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
- from .resources.chat import AsyncChatResourceWithStreamingResponse
-
- return AsyncChatResourceWithStreamingResponse(self._client.chat)
-
Client = Docstrange
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
deleted file mode 100644
index e926095..0000000
--- a/src/docstrange/pagination.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Generic, TypeVar, Optional, cast
-from typing_extensions import override
-
-from ._models import BaseModel
-from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
-
-__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
-
-_T = TypeVar("_T")
-
-
-class PageNumberPaginationPagination(BaseModel):
- has_next: Optional[bool] = None
-
- total_count: Optional[int] = None
-
-
-class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
- results: List[_T]
- pagination: Optional[PageNumberPaginationPagination] = None
-
- @override
- def _get_page_items(self) -> List[_T]:
- results = self.results
- if not results:
- return []
- return results
-
- @override
- def next_page_info(self) -> Optional[PageInfo]:
- last_page = cast("int | None", self._options.params.get("page")) or 1
-
- total_pages = None
- if self.pagination is not None:
- if self.pagination.total_count is not None:
- total_pages = self.pagination.total_count
- if total_pages is not None and last_page >= total_pages:
- return None
-
- return PageInfo(params={"page": last_page + 1})
-
-
-class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
- results: List[_T]
- pagination: Optional[PageNumberPaginationPagination] = None
-
- @override
- def _get_page_items(self) -> List[_T]:
- results = self.results
- if not results:
- return []
- return results
-
- @override
- def next_page_info(self) -> Optional[PageInfo]:
- last_page = cast("int | None", self._options.params.get("page")) or 1
-
- total_pages = None
- if self.pagination is not None:
- if self.pagination.total_count is not None:
- total_pages = self.pagination.total_count
- if total_pages is not None and last_page >= total_pages:
- return None
-
- return PageInfo(params={"page": last_page + 1})
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index a3172dd..6d7ff55 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,13 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from .chat import (
- ChatResource,
- AsyncChatResource,
- ChatResourceWithRawResponse,
- AsyncChatResourceWithRawResponse,
- ChatResourceWithStreamingResponse,
- AsyncChatResourceWithStreamingResponse,
-)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -38,10 +30,4 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
- "ChatResource",
- "AsyncChatResource",
- "ChatResourceWithRawResponse",
- "AsyncChatResourceWithRawResponse",
- "ChatResourceWithStreamingResponse",
- "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
deleted file mode 100644
index 0a892c1..0000000
--- a/src/docstrange/resources/chat.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-
-import httpx
-
-from ..types import chat_create_completion_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-
-__all__ = ["ChatResource", "AsyncChatResource"]
-
-
-class ChatResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ChatResourceWithStreamingResponse(self)
-
- def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """OpenAI-compatible chat completions endpoint.
-
- Supports text messages and
- file/image inputs via `image_url` or `file_url` parts.
-
- **Limits and behavior:**
-
- - The backend enforces a model context limit of ~20,000 tokens (text +
- multimodal tokens).
- - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
- and embedded as data URLs.
- - Inline data URLs are limited to ~64MB decoded size per item.
-
- For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
-
- Args:
- messages: Chat messages array
-
- model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
-
- stream: Enable SSE streaming
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._post(
- "/v1/chat/completions",
- body=maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class AsyncChatResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncChatResourceWithStreamingResponse(self)
-
- async def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """OpenAI-compatible chat completions endpoint.
-
- Supports text messages and
- file/image inputs via `image_url` or `file_url` parts.
-
- **Limits and behavior:**
-
- - The backend enforces a model context limit of ~20,000 tokens (text +
- multimodal tokens).
- - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
- and embedded as data URLs.
- - Inline data URLs are limited to ~64MB decoded size per item.
-
- For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
-
- Args:
- messages: Chat messages array
-
- model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
-
- stream: Enable SSE streaming
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return await self._post(
- "/v1/chat/completions",
- body=await async_maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class ChatResourceWithRawResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithRawResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class ChatResourceWithStreamingResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_streamed_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithStreamingResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_streamed_response_wrapper(
- chat.create_completion,
- )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index 5476a59..69045f4 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,11 +2,13 @@
from __future__ import annotations
+from typing import Mapping, cast
+
import httpx
-from ..types import classify_sync_params, classify_batch_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from ..types import classify_sync_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -17,7 +19,6 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
-from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -42,56 +43,6 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
- def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50 files).
-
- Files are queued for background processing. Use
- `GET /api/v1/extract/results/{record_id}` to poll results.
-
- Args:
- categories: JSON array of category objects (max 50 categories)
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/classify/batch",
- body=maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
def sync(
self,
*,
@@ -105,17 +56,12 @@ def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document into predefined categories synchronously.
-
- Each page is classified individually with category, confidence score (0-100),
- and reasoning.
+ Classify a single document.
Args:
- categories:
- JSON array of category objects: [{"name": "Category Name", "description":
- "Optional description"}]
+ categories: JSON array of categories
- file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
+ file: File to classify
extra_headers: Send extra headers
@@ -125,19 +71,21 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -165,56 +113,6 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
- async def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50 files).
-
- Files are queued for background processing. Use
- `GET /api/v1/extract/results/{record_id}` to poll results.
-
- Args:
- categories: JSON array of category objects (max 50 categories)
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/classify/batch",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
async def sync(
self,
*,
@@ -228,17 +126,12 @@ async def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document into predefined categories synchronously.
-
- Each page is classified individually with category, confidence score (0-100),
- and reasoning.
+ Classify a single document.
Args:
- categories:
- JSON array of category objects: [{"name": "Category Name", "description":
- "Optional description"}]
+ categories: JSON array of categories
- file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
+ file: File to classify
extra_headers: Send extra headers
@@ -248,19 +141,21 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -272,9 +167,6 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_raw_response_wrapper(
- classify.batch,
- )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -284,9 +176,6 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_raw_response_wrapper(
- classify.batch,
- )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -296,9 +185,6 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -308,9 +194,6 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract.py b/src/docstrange/resources/extract.py
new file mode 100644
index 0000000..88bef17
--- /dev/null
+++ b/src/docstrange/resources/extract.py
@@ -0,0 +1,199 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Mapping, cast
+
+import httpx
+
+from ..types import extract_sync_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+from ..types.extract_response import ExtractResponse
+
+__all__ = ["ExtractResource", "AsyncExtractResource"]
+
+
+class ExtractResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ExtractResourceWithStreamingResponse(self)
+
+ def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload
+
+ output_format: Output format
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "file": file,
+ "output_format": output_format,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/sync",
+ body=maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class AsyncExtractResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncExtractResourceWithStreamingResponse(self)
+
+ async def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload
+
+ output_format: Output format
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "file": file,
+ "output_format": output_format,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/sync",
+ body=await async_maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class ExtractResourceWithRawResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = to_raw_response_wrapper(
+ extract.sync,
+ )
+
+
+class AsyncExtractResourceWithRawResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = async_to_raw_response_wrapper(
+ extract.sync,
+ )
+
+
+class ExtractResourceWithStreamingResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+
+class AsyncExtractResourceWithStreamingResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = async_to_streamed_response_wrapper(
+ extract.sync,
+ )
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
deleted file mode 100644
index 22cd257..0000000
--- a/src/docstrange/resources/extract/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .extract import (
- ExtractResource,
- AsyncExtractResource,
- ExtractResourceWithRawResponse,
- AsyncExtractResourceWithRawResponse,
- ExtractResourceWithStreamingResponse,
- AsyncExtractResourceWithStreamingResponse,
-)
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
-
-__all__ = [
- "ResultsResource",
- "AsyncResultsResource",
- "ResultsResourceWithRawResponse",
- "AsyncResultsResourceWithRawResponse",
- "ResultsResourceWithStreamingResponse",
- "AsyncResultsResourceWithStreamingResponse",
- "ExtractResource",
- "AsyncExtractResource",
- "ExtractResourceWithRawResponse",
- "AsyncExtractResourceWithRawResponse",
- "ExtractResourceWithStreamingResponse",
- "AsyncExtractResourceWithStreamingResponse",
-]
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
deleted file mode 100644
index bed3b08..0000000
--- a/src/docstrange/resources/extract/extract.py
+++ /dev/null
@@ -1,814 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-import httpx
-
-from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
-from ..._types import (
- Body,
- Omit,
- Query,
- Headers,
- NotGiven,
- FileTypes,
- SequenceNotStr,
- omit,
- not_given,
-)
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ..._streaming import Stream, AsyncStream
-from ..._base_client import make_request_options
-from ...types.extract_response import ExtractResponse
-from ...types.batch_extract_response import BatchExtractResponse
-from ...types.extract_stream_response import ExtractStreamResponse
-
-__all__ = ["ExtractResource", "AsyncExtractResource"]
-
-
-class ExtractResource(SyncAPIResource):
- @cached_property
- def results(self) -> ResultsResource:
- return ResultsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> ExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ExtractResourceWithStreamingResponse(self)
-
- def async_(
- self,
- *,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file: FileTypes | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """Queue a document for background processing.
-
- Returns a `record_id` to poll
- results via `GET /api/v1/extract/results/{record_id}`.
-
- Recommended for large documents (>50 pages).
-
- Args:
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/async",
- body=maybe_transform(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """Process multiple files asynchronously (max 50 files).
-
- All files share the same
- extraction options.
-
- Args:
- files: Files to process (max 50)
-
- output_format: Output format(s) for all files
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/batch",
- body=maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
- )
-
- def stream(
- self,
- *,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file: FileTypes | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Stream[ExtractStreamResponse]:
- """
- Stream extraction results via Server-Sent Events (SSE) for real-time content
- delivery.
-
- **Event Types:**
-
- - `content`: Incremental content chunks (streaming mode)
- - `complete`: Full content at once (batch mode)
- - `done`: Final event with record_id and processing_time
- - `error`: Error information
- - `async_queued`: Large files queued for async processing
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
- multiple.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
- mode.
-
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/stream",
- body=maybe_transform(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=Stream[ExtractStreamResponse],
- )
-
- def sync(
- self,
- *,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file: FileTypes | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """Process a document and return extracted content immediately.
-
- (Works for files
- with 5 pages or less.)
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/sync",
- body=maybe_transform(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class AsyncExtractResource(AsyncAPIResource):
- @cached_property
- def results(self) -> AsyncResultsResource:
- return AsyncResultsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncExtractResourceWithStreamingResponse(self)
-
- async def async_(
- self,
- *,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file: FileTypes | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """Queue a document for background processing.
-
- Returns a `record_id` to poll
- results via `GET /api/v1/extract/results/{record_id}`.
-
- Recommended for large documents (>50 pages).
-
- Args:
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/async",
- body=await async_maybe_transform(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- async def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """Process multiple files asynchronously (max 50 files).
-
- All files share the same
- extraction options.
-
- Args:
- files: Files to process (max 50)
-
- output_format: Output format(s) for all files
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/batch",
- body=await async_maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
- )
-
- async def stream(
- self,
- *,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file: FileTypes | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncStream[ExtractStreamResponse]:
- """
- Stream extraction results via Server-Sent Events (SSE) for real-time content
- delivery.
-
- **Event Types:**
-
- - `content`: Incremental content chunks (streaming mode)
- - `complete`: Full content at once (batch mode)
- - `done`: Final event with record_id and processing_time
- - `error`: Error information
- - `async_queued`: Large files queued for async processing
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
- multiple.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
- mode.
-
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/stream",
- body=await async_maybe_transform(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=AsyncStream[ExtractStreamResponse],
- )
-
- async def sync(
- self,
- *,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file: FileTypes | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """Process a document and return extracted content immediately.
-
- (Works for files
- with 5 pages or less.)
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/sync",
- body=await async_maybe_transform(
- {
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file": file,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class ExtractResourceWithRawResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.async_ = to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = to_raw_response_wrapper(
- extract.stream,
- )
- self.sync = to_raw_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> ResultsResourceWithRawResponse:
- return ResultsResourceWithRawResponse(self._extract.results)
-
-
-class AsyncExtractResourceWithRawResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.async_ = async_to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_raw_response_wrapper(
- extract.stream,
- )
- self.sync = async_to_raw_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> AsyncResultsResourceWithRawResponse:
- return AsyncResultsResourceWithRawResponse(self._extract.results)
-
-
-class ExtractResourceWithStreamingResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.async_ = to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = to_streamed_response_wrapper(
- extract.stream,
- )
- self.sync = to_streamed_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> ResultsResourceWithStreamingResponse:
- return ResultsResourceWithStreamingResponse(self._extract.results)
-
-
-class AsyncExtractResourceWithStreamingResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.async_ = async_to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_streamed_response_wrapper(
- extract.stream,
- )
- self.sync = async_to_streamed_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> AsyncResultsResourceWithStreamingResponse:
- return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
deleted file mode 100644
index 1533ac2..0000000
--- a/src/docstrange/resources/extract/results.py
+++ /dev/null
@@ -1,294 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-from ..._base_client import AsyncPaginator, make_request_options
-from ...types.extract import result_list_params, result_retrieve_params
-from ...types.extract_response import ExtractResponse
-
-__all__ = ["ResultsResource", "AsyncResultsResource"]
-
-
-class ResultsResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ResultsResourceWithStreamingResponse(self)
-
- def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- include_content: Include full extracted content (default: true)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> SyncPageNumberPagination[ExtractResponse]:
- """
- List all extraction jobs for the authenticated user (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=SyncPageNumberPagination[ExtractResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=ExtractResponse,
- )
-
-
-class AsyncResultsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncResultsResourceWithStreamingResponse(self)
-
- async def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- include_content: Include full extracted content (default: true)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return await self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncPaginator[ExtractResponse, AsyncPageNumberPagination[ExtractResponse]]:
- """
- List all extraction jobs for the authenticated user (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=AsyncPageNumberPagination[ExtractResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=ExtractResponse,
- )
-
-
-class ResultsResourceWithRawResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = to_raw_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithRawResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_raw_response_wrapper(
- results.list,
- )
-
-
-class ResultsResourceWithStreamingResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = to_streamed_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithStreamingResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_streamed_response_wrapper(
- results.list,
- )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index a18a10a..fac3955 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -4,18 +4,5 @@
from .extract_response import ExtractResponse as ExtractResponse
from .classify_response import ClassifyResponse as ClassifyResponse
-from .extraction_result import ExtractionResult as ExtractionResult
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
-from .extraction_metadata import ExtractionMetadata as ExtractionMetadata
-from .page_classification import PageClassification as PageClassification
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
-from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
-from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
-from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
-from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
-from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
-from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
-from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
-from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
-from .file_classification_result import FileClassificationResult as FileClassificationResult
-from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
deleted file mode 100644
index a36e5a8..0000000
--- a/src/docstrange/types/batch_classify_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-from .file_classification_result import FileClassificationResult
-
-__all__ = ["BatchClassifyResponse"]
-
-
-class BatchClassifyResponse(BaseModel):
- batch_id: str
-
- failed_files: int
-
- message: str
-
- results: List[FileClassificationResult]
-
- success: bool
-
- successful_files: int
-
- total_files: int
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
deleted file mode 100644
index 4e73773..0000000
--- a/src/docstrange/types/batch_extract_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-from .extract_response import ExtractResponse
-
-__all__ = ["BatchExtractResponse"]
-
-
-class BatchExtractResponse(BaseModel):
- accepted_files: int
-
- batch_id: str
-
- message: str
-
- records: List[ExtractResponse]
-
- rejected_files: int
-
- success: bool
-
- total_files: int
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
deleted file mode 100644
index b7cde5c..0000000
--- a/src/docstrange/types/chat_create_completion_params.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-from typing_extensions import Required, TypedDict
-
-__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
-
-
-class ChatCreateCompletionParams(TypedDict, total=False):
- messages: Required[Iterable[Message]]
- """Chat messages array"""
-
- model: Required[str]
- """Model identifier (e.g., nanonets/Nanonets-OCR-s)"""
-
- stream: bool
- """Enable SSE streaming"""
-
-
-class MessageContentFileURL(TypedDict, total=False):
- url: str
-
-
-class MessageContentImageURL(TypedDict, total=False):
- url: str
-
-
-class MessageContent(TypedDict, total=False):
- file_url: MessageContentFileURL
-
- image_url: MessageContentImageURL
-
- text: str
-
- type: str
-
-
-class Message(TypedDict, total=False):
- content: Required[Iterable[MessageContent]]
- """Message content as an array of parts (text or file/image URLs)."""
-
- role: Required[str]
- """Message role (system, user, assistant)"""
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
deleted file mode 100644
index 5cac9e3..0000000
--- a/src/docstrange/types/classify_batch_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ClassifyBatchParams"]
-
-
-class ClassifyBatchParams(TypedDict, total=False):
- categories: Required[str]
- """JSON array of category objects (max 50 categories)"""
-
- files: Required[SequenceNotStr[FileTypes]]
- """Files to classify (max 50)"""
diff --git a/src/docstrange/types/classify_response.py b/src/docstrange/types/classify_response.py
index fdebbb0..5bab3de 100644
--- a/src/docstrange/types/classify_response.py
+++ b/src/docstrange/types/classify_response.py
@@ -1,9 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
-
from .._models import BaseModel
-from .file_classification_result import FileClassificationResult
__all__ = ["ClassifyResponse"]
@@ -12,5 +9,3 @@ class ClassifyResponse(BaseModel):
message: str
success: bool
-
- result: Optional[FileClassificationResult] = None
diff --git a/src/docstrange/types/classify_sync_params.py b/src/docstrange/types/classify_sync_params.py
index 772427d..ff11627 100644
--- a/src/docstrange/types/classify_sync_params.py
+++ b/src/docstrange/types/classify_sync_params.py
@@ -11,10 +11,7 @@
class ClassifySyncParams(TypedDict, total=False):
categories: Required[str]
- """
- JSON array of category objects: [{"name": "Category Name", "description":
- "Optional description"}]
- """
+ """JSON array of categories"""
file: Required[FileTypes]
- """File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)"""
+ """File to classify"""
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
deleted file mode 100644
index 387a007..0000000
--- a/src/docstrange/types/extract/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .pagination_info import PaginationInfo as PaginationInfo
-from .result_list_params import ResultListParams as ResultListParams
-from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
-from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
deleted file mode 100644
index 26a12e7..0000000
--- a/src/docstrange/types/extract/extraction_list_response.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from ..._models import BaseModel
-from .pagination_info import PaginationInfo
-from ..extract_response import ExtractResponse
-
-__all__ = ["ExtractionListResponse"]
-
-
-class ExtractionListResponse(BaseModel):
- pagination: PaginationInfo
-
- results: List[ExtractResponse]
-
- success: bool
diff --git a/src/docstrange/types/extract/pagination_info.py b/src/docstrange/types/extract/pagination_info.py
deleted file mode 100644
index 7a678a9..0000000
--- a/src/docstrange/types/extract/pagination_info.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from ..._models import BaseModel
-
-__all__ = ["PaginationInfo"]
-
-
-class PaginationInfo(BaseModel):
- has_next: Optional[bool] = None
-
- has_previous: Optional[bool] = None
-
- page: Optional[int] = None
-
- page_size: Optional[int] = None
-
- total_count: Optional[int] = None
-
- total_pages: Optional[int] = None
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
deleted file mode 100644
index 7dfe38a..0000000
--- a/src/docstrange/types/extract/result_list_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypedDict
-
-__all__ = ["ResultListParams"]
-
-
-class ResultListParams(TypedDict, total=False):
- page: int
-
- page_size: int
-
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
-
- sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
deleted file mode 100644
index 539b80d..0000000
--- a/src/docstrange/types/extract/result_retrieve_params.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import TypedDict
-
-__all__ = ["ResultRetrieveParams"]
-
-
-class ResultRetrieveParams(TypedDict, total=False):
- include_content: bool
- """Include full extracted content (default: true)"""
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
deleted file mode 100644
index d638b09..0000000
--- a/src/docstrange/types/extract_async_params.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractAsyncParams"]
-
-
-class ExtractAsyncParams(TypedDict, total=False):
- output_format: Required[str]
- """Output format(s): `markdown`, `html`, `json`, `csv`.
-
- Comma-separate for multiple (e.g., `markdown,json`).
- """
-
- csv_options: str
- """CSV extraction options (e.g., `table`)"""
-
- custom_instructions: str
- """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
-
- file: FileTypes
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
-
- json_options: str
- """JSON extraction options.
-
- Values: `hierarchy_output`, `table-of-contents`, field list
- `["field1", "field2"]`, or JSON schema `{...}`
- """
-
- prompt_mode: Literal["append", "replace"]
- """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
deleted file mode 100644
index bdc7b29..0000000
--- a/src/docstrange/types/extract_batch_params.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ExtractBatchParams"]
-
-
-class ExtractBatchParams(TypedDict, total=False):
- files: Required[SequenceNotStr[FileTypes]]
- """Files to process (max 50)"""
-
- output_format: Required[str]
- """Output format(s) for all files"""
-
- csv_options: str
-
- custom_instructions: str
-
- include_metadata: str
-
- json_options: str
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_response.py b/src/docstrange/types/extract_response.py
index 9d93ead..ba021e0 100644
--- a/src/docstrange/types/extract_response.py
+++ b/src/docstrange/types/extract_response.py
@@ -1,38 +1,17 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
-from datetime import datetime
-from typing_extensions import Literal
from .._models import BaseModel
-from .extraction_result import ExtractionResult
__all__ = ["ExtractResponse"]
class ExtractResponse(BaseModel):
- message: str
-
record_id: str
- """Job ID for retrieving results"""
- status: Literal["completed", "processing", "failed"]
+ status: str
success: bool
- created_at: Optional[datetime] = None
-
- file_size: Optional[int] = None
- """Size in bytes"""
-
- filename: Optional[str] = None
-
- output_format: Optional[str] = None
-
- pages_processed: Optional[int] = None
-
- processing_time: Optional[float] = None
- """Time in seconds"""
-
- result: Optional[ExtractionResult] = None
- """Results by format (only requested formats populated)"""
+ message: Optional[str] = None
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
deleted file mode 100644
index 2a8e9e3..0000000
--- a/src/docstrange/types/extract_stream_params.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractStreamParams"]
-
-
-class ExtractStreamParams(TypedDict, total=False):
- output_format: Required[str]
- """Output format(s): `markdown`, `html`, `json`, `csv`.
-
- Comma-separate for multiple.
- """
-
- csv_options: str
- """CSV extraction options"""
-
- custom_instructions: str
- """Custom extraction instructions"""
-
- enable_streaming: bool
- """Enable real-time streaming.
-
- If false, returns complete content via SSE batch mode.
- """
-
- file: FileTypes
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
-
- json_options: str
- """JSON extraction options"""
-
- prompt_mode: Literal["append", "replace"]
- """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
deleted file mode 100644
index 333ff97..0000000
--- a/src/docstrange/types/extract_stream_response.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import TypeAlias
-
-__all__ = ["ExtractStreamResponse"]
-
-ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index e3c4bea..242ce95 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
from .._types import FileTypes
@@ -10,36 +10,8 @@
class ExtractSyncParams(TypedDict, total=False):
- output_format: Required[str]
- """Output format(s): `markdown`, `html`, `json`, `csv`.
-
- Comma-separate for multiple (e.g., `markdown,json`).
- """
-
- csv_options: str
- """CSV extraction options (e.g., `table`)"""
-
- custom_instructions: str
- """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
-
- file: FileTypes
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
- file_base64: str
- """Base64-encoded file content"""
+ file: Required[FileTypes]
+ """File to upload"""
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
-
- json_options: str
- """JSON extraction options.
-
- Values: `hierarchy_output`, `table-of-contents`, field list
- `["field1", "field2"]`, or JSON schema `{...}`
- """
-
- prompt_mode: Literal["append", "replace"]
- """`append`: add to base prompt, `replace`: use only custom instructions"""
+ output_format: Required[str]
+ """Output format"""
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
deleted file mode 100644
index 579500c..0000000
--- a/src/docstrange/types/extraction_format_result.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Union, Optional
-
-from .._models import BaseModel
-from .extraction_metadata import ExtractionMetadata
-
-__all__ = ["ExtractionFormatResult"]
-
-
-class ExtractionFormatResult(BaseModel):
- content: Union[str, object]
- """Extracted content"""
-
- metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/extraction_metadata.py b/src/docstrange/types/extraction_metadata.py
deleted file mode 100644
index 9792ba0..0000000
--- a/src/docstrange/types/extraction_metadata.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from .._models import BaseModel
-
-__all__ = ["ExtractionMetadata"]
-
-
-class ExtractionMetadata(BaseModel):
- bounding_boxes: Optional[object] = None
- """Element coordinates with page dimensions"""
-
- confidence_score: Optional[object] = None
- """Confidence scores per field"""
diff --git a/src/docstrange/types/extraction_result.py b/src/docstrange/types/extraction_result.py
deleted file mode 100644
index 57b2928..0000000
--- a/src/docstrange/types/extraction_result.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-from .extraction_format_result import ExtractionFormatResult
-
-__all__ = ["ExtractionResult"]
-
-
-class ExtractionResult(BaseModel):
- """Results by format (only requested formats populated)"""
-
- csv: Optional[ExtractionFormatResult] = None
-
- html: Optional[ExtractionFormatResult] = None
-
- json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
-
- markdown: Optional[ExtractionFormatResult] = None
diff --git a/src/docstrange/types/file_classification_result.py b/src/docstrange/types/file_classification_result.py
deleted file mode 100644
index 397d924..0000000
--- a/src/docstrange/types/file_classification_result.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from .._models import BaseModel
-from .page_classification import PageClassification
-
-__all__ = ["FileClassificationResult"]
-
-
-class FileClassificationResult(BaseModel):
- filename: str
-
- pages: List[PageClassification]
-
- total_pages: int
-
- error: Optional[str] = None
-
- processing_time: Optional[float] = None
- """Time in seconds"""
-
- record_id: Optional[str] = None
- """Record ID for polling results"""
diff --git a/src/docstrange/types/page_classification.py b/src/docstrange/types/page_classification.py
deleted file mode 100644
index 2099524..0000000
--- a/src/docstrange/types/page_classification.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from .._models import BaseModel
-
-__all__ = ["PageClassification"]
-
-
-class PageClassification(BaseModel):
- category: str
- """Matched category name or 'Other' if no match"""
-
- confidence: int
- """Confidence score (0-100)"""
-
- page_number: int
-
- reasoning: str
- """Explanation for the classification"""
-
- identified_category: Optional[str] = None
- """
- Specific document type identified by the model (e.g.,
- 'Invoice_Amazon_Electronics'). Always provided - contains a more detailed
- classification than the category.
- """
diff --git a/tests/api_resources/extract/__init__.py b/tests/api_resources/extract/__init__.py
deleted file mode 100644
index fd8019a..0000000
--- a/tests/api_resources/extract/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
deleted file mode 100644
index ee1d5f5..0000000
--- a/tests/api_resources/extract/test_results.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
-from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestResults:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_retrieve(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_retrieve(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_retrieve(self, client: Docstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list(self, client: Docstrange) -> None:
- result = client.extract.results.list()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncResults:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- await async_client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
deleted file mode 100644
index cbcd7c3..0000000
--- a/tests/api_resources/test_chat.py
+++ /dev/null
@@ -1,183 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestChat:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [{}, {}],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "https://example.com/doc.pdf"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "file_url",
- },
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "Extract the text from the document.",
- "type": "text",
- },
- ],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- stream=False,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_create_completion(self, client: Docstrange) -> None:
- response = client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}, {}],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_create_completion(self, client: Docstrange) -> None:
- with client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}, {}],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncChat:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [{}, {}],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "https://example.com/doc.pdf"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "file_url",
- },
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "Extract the text from the document.",
- "type": "text",
- },
- ],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- stream=False,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}, {}],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- async with async_client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}, {}],
- "role": "user",
- }
- ],
- model="nanonets/Nanonets-OCR-s",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index b4377f6..63539df 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse, BatchClassifyResponse
+from docstrange.types import ClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,48 +17,11 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- classify = client.classify.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.classify.with_raw_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.classify.with_streaming_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
classify = client.classify.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -67,7 +30,7 @@ def test_method_sync(self, client: Docstrange) -> None:
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.classify.with_raw_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
@@ -80,7 +43,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.classify.with_streaming_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
) as response:
assert not response.is_closed
@@ -97,48 +60,11 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- classify = await async_client.classify.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.classify.with_raw_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.classify.with_streaming_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
classify = await async_client.classify.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -147,7 +73,7 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.classify.with_raw_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
@@ -160,7 +86,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.classify.with_streaming_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index ffdac33..d8117c2 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,10 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import (
- ExtractResponse,
- BatchExtractResponse,
-)
+from docstrange.types import ExtractResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -20,178 +17,12 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- file=b"raw file contents",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_async(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.async_(
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_async(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.async_(
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- output_format="markdown",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream_with_all_params(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- enable_streaming=True,
- file=b"raw file contents",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_raw_response_stream(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.stream(
- output_format="markdown",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = response.parse()
- stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_streaming_response_stream(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.stream(
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = response.parse()
- stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
extract = client.extract.sync(
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_sync_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.sync(
- output_format="markdown",
- csv_options="",
- custom_instructions="",
file=b"raw file contents",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
+ output_format="output_format",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -199,7 +30,8 @@ def test_method_sync_with_all_params(self, client: Docstrange) -> None:
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.sync(
- output_format="markdown",
+ file=b"raw file contents",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -211,7 +43,8 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.sync(
- output_format="markdown",
+ file=b"raw file contents",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -227,178 +60,12 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- file=b"raw file contents",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.async_(
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.async_(
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- output_format="markdown",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- enable_streaming=True,
- file=b"raw file contents",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.stream(
- output_format="markdown",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = await response.parse()
- await stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.stream(
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = await response.parse()
- await stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.sync(
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.sync(
- output_format="markdown",
- csv_options="",
- custom_instructions="",
file=b"raw file contents",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
+ output_format="output_format",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -406,7 +73,8 @@ async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange)
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.sync(
- output_format="markdown",
+ file=b"raw file contents",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -418,7 +86,8 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.sync(
- output_format="markdown",
+ file=b"raw file contents",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/test_client.py b/tests/test_client.py
index 3d576f6..2756693 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -862,7 +862,9 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.extract.with_streaming_response.sync(output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(
+ file=b"raw file contents", output_format="output_format"
+ ).__enter__()
assert _get_open_connections(client) == 0
@@ -872,7 +874,9 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.extract.with_streaming_response.sync(output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(
+ file=b"raw file contents", output_format="output_format"
+ ).__enter__()
assert _get_open_connections(client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -901,7 +905,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.extract.with_raw_response.sync(output_format="markdown")
+ response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -926,7 +930,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -951,7 +955,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1768,7 +1772,9 @@ async def test_retrying_timeout_errors_doesnt_leak(
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- await async_client.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
+ await async_client.extract.with_streaming_response.sync(
+ file=b"raw file contents", output_format="output_format"
+ ).__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1780,7 +1786,9 @@ async def test_retrying_status_errors_doesnt_leak(
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- await async_client.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
+ await async_client.extract.with_streaming_response.sync(
+ file=b"raw file contents", output_format="output_format"
+ ).__aenter__()
assert _get_open_connections(async_client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1809,7 +1817,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.extract.with_raw_response.sync(output_format="markdown")
+ response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1834,7 +1842,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -1859,7 +1867,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
From a1ada95fffb116ab7c5a59f5d69eb24fa69f5827 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 21:29:19 +0000
Subject: [PATCH 14/26] feat(api): api update
---
.stats.yml | 8 +-
README.md | 63 +-
api.md | 52 +-
src/docstrange/_client.py | 41 +-
src/docstrange/pagination.py | 67 ++
src/docstrange/resources/__init__.py | 14 +
src/docstrange/resources/chat.py | 218 +++++
src/docstrange/resources/classify.py | 175 +++-
src/docstrange/resources/extract.py | 199 -----
src/docstrange/resources/extract/__init__.py | 33 +
src/docstrange/resources/extract/extract.py | 814 ++++++++++++++++++
src/docstrange/resources/extract/results.py | 294 +++++++
src/docstrange/types/__init__.py | 13 +
.../types/batch_classify_response.py | 24 +
.../types/batch_extract_response.py | 24 +
.../types/chat_create_completion_params.py | 45 +
src/docstrange/types/classify_batch_params.py | 17 +
src/docstrange/types/classify_response.py | 5 +
src/docstrange/types/classify_sync_params.py | 7 +-
src/docstrange/types/extract/__init__.py | 8 +
.../types/extract/extraction_list_response.py | 17 +
.../types/extract/pagination_info.py | 21 +
.../types/extract/result_list_params.py | 17 +
.../types/extract/result_retrieve_params.py | 12 +
src/docstrange/types/extract_async_params.py | 45 +
src/docstrange/types/extract_batch_params.py | 27 +
src/docstrange/types/extract_response.py | 25 +-
src/docstrange/types/extract_stream_params.py | 47 +
.../types/extract_stream_response.py | 7 +
src/docstrange/types/extract_sync_params.py | 34 +-
.../types/extraction_format_result.py | 15 +
src/docstrange/types/extraction_metadata.py | 15 +
src/docstrange/types/extraction_result.py | 22 +
.../types/file_classification_result.py | 24 +
src/docstrange/types/page_classification.py | 27 +
tests/api_resources/extract/__init__.py | 1 +
tests/api_resources/extract/test_results.py | 205 +++++
tests/api_resources/test_chat.py | 183 ++++
tests/api_resources/test_classify.py | 88 +-
tests/api_resources/test_extract.py | 363 +++++++-
tests/test_client.py | 24 +-
41 files changed, 3067 insertions(+), 273 deletions(-)
create mode 100644 src/docstrange/pagination.py
create mode 100644 src/docstrange/resources/chat.py
delete mode 100644 src/docstrange/resources/extract.py
create mode 100644 src/docstrange/resources/extract/__init__.py
create mode 100644 src/docstrange/resources/extract/extract.py
create mode 100644 src/docstrange/resources/extract/results.py
create mode 100644 src/docstrange/types/batch_classify_response.py
create mode 100644 src/docstrange/types/batch_extract_response.py
create mode 100644 src/docstrange/types/chat_create_completion_params.py
create mode 100644 src/docstrange/types/classify_batch_params.py
create mode 100644 src/docstrange/types/extract/__init__.py
create mode 100644 src/docstrange/types/extract/extraction_list_response.py
create mode 100644 src/docstrange/types/extract/pagination_info.py
create mode 100644 src/docstrange/types/extract/result_list_params.py
create mode 100644 src/docstrange/types/extract/result_retrieve_params.py
create mode 100644 src/docstrange/types/extract_async_params.py
create mode 100644 src/docstrange/types/extract_batch_params.py
create mode 100644 src/docstrange/types/extract_stream_params.py
create mode 100644 src/docstrange/types/extract_stream_response.py
create mode 100644 src/docstrange/types/extraction_format_result.py
create mode 100644 src/docstrange/types/extraction_metadata.py
create mode 100644 src/docstrange/types/extraction_result.py
create mode 100644 src/docstrange/types/file_classification_result.py
create mode 100644 src/docstrange/types/page_classification.py
create mode 100644 tests/api_resources/extract/__init__.py
create mode 100644 tests/api_resources/extract/test_results.py
create mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index 06a3238..a5ffc81 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 2
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-00ea96039f73fd253b5042c3e5c1ae800ca6b3bbde585408d20a46f73ae87ecf.yml
-openapi_spec_hash: b4046d95714426b15edb8ac003f904c6
-config_hash: 6f0ab1fd6c4433590ee82d88ab5298a7
+configured_endpoints: 9
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-1f31f87d4c6e168ffcccab94b8967a095195cac1ea2518bbddbeaf4611e02f05.yml
+openapi_spec_hash: 18bec87d90926b0bc0cd98ce1d066d1f
+config_hash: c02183ee58f815311de9278705163d1a
diff --git a/README.md b/README.md
index 622faec..991dcba 100644
--- a/README.md
+++ b/README.md
@@ -115,6 +115,67 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
+## Pagination
+
+List methods in the Docstrange API are paginated.
+
+This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
+
+```python
+from docstrange import Docstrange
+
+client = Docstrange()
+
+all_results = []
+# Automatically fetches more pages as needed.
+for result in client.extract.results.list():
+ # Do something with result here
+ all_results.append(result)
+print(all_results)
+```
+
+Or, asynchronously:
+
+```python
+import asyncio
+from docstrange import AsyncDocstrange
+
+client = AsyncDocstrange()
+
+
+async def main() -> None:
+ all_results = []
+ # Iterate through items across all pages, issuing requests as needed.
+ async for result in client.extract.results.list():
+ all_results.append(result)
+ print(all_results)
+
+
+asyncio.run(main())
+```
+
+Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
+
+```python
+first_page = await client.extract.results.list()
+if first_page.has_next_page():
+ print(f"will fetch next page using these details: {first_page.next_page_info()}")
+ next_page = await first_page.get_next_page()
+ print(f"number of items we just fetched: {len(next_page.results)}")
+
+# Remove `await` for non-async usage.
+```
+
+Or just work directly with the returned data:
+
+```python
+first_page = await client.extract.results.list()
+for result in first_page.results:
+ print(result.record_id)
+
+# Remove `await` for non-async usage.
+```
+
## File uploads
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)`.
@@ -127,7 +188,7 @@ client = Docstrange()
client.extract.sync(
file=Path("/path/to/file"),
- output_format="output_format",
+ output_format="markdown",
)
```
diff --git a/api.md b/api.md
index 0cac7c9..7ccbce8 100644
--- a/api.md
+++ b/api.md
@@ -3,21 +3,67 @@
Types:
```python
-from docstrange.types import ExtractResponse
+from docstrange.types import (
+ BatchExtractRequestBody,
+ BatchExtractResponse,
+ ExtractRequestBody,
+ ExtractResponse,
+ ExtractionFormatResult,
+ ExtractionMetadata,
+ ExtractionResult,
+ StreamExtractRequestBody,
+ ExtractStreamResponse,
+)
```
Methods:
-- client.extract.sync(\*\*params) -> ExtractResponse
+- client.extract.async\_(\*\*params) -> ExtractResponse
+- client.extract.batch(\*\*params) -> BatchExtractResponse
+- client.extract.stream(\*\*params) -> str
+- client.extract.sync(\*\*params) -> ExtractResponse
+
+## Results
+
+Types:
+
+```python
+from docstrange.types.extract import ExtractionListResponse, PaginationInfo
+```
+
+Methods:
+
+- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
+- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[ExtractResponse]
# Classify
Types:
```python
-from docstrange.types import ClassifyResponse
+from docstrange.types import (
+ BatchClassifyRequestBody,
+ BatchClassifyResponse,
+ ClassifyRequestBody,
+ ClassifyResponse,
+ FileClassificationResult,
+ PageClassification,
+)
```
Methods:
+- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
+
+# Chat
+
+Types:
+
+```python
+from docstrange.types import ChatCompletionsRequest
+```
+
+Methods:
+
+- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 42d282d..4c5bcc4 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,9 +31,10 @@
)
if TYPE_CHECKING:
- from .resources import extract, classify
- from .resources.extract import ExtractResource, AsyncExtractResource
+ from .resources import chat, extract, classify
+ from .resources.chat import ChatResource, AsyncChatResource
from .resources.classify import ClassifyResource, AsyncClassifyResource
+ from .resources.extract.extract import ExtractResource, AsyncExtractResource
__all__ = [
"Timeout",
@@ -114,6 +115,12 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
+ @cached_property
+ def chat(self) -> ChatResource:
+ from .resources.chat import ChatResource
+
+ return ChatResource(self)
+
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -294,6 +301,12 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
+ @cached_property
+ def chat(self) -> AsyncChatResource:
+ from .resources.chat import AsyncChatResource
+
+ return AsyncChatResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -425,6 +438,12 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithRawResponse:
+ from .resources.chat import ChatResourceWithRawResponse
+
+ return ChatResourceWithRawResponse(self._client.chat)
+
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -444,6 +463,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithRawResponse:
+ from .resources.chat import AsyncChatResourceWithRawResponse
+
+ return AsyncChatResourceWithRawResponse(self._client.chat)
+
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -463,6 +488,12 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithStreamingResponse:
+ from .resources.chat import ChatResourceWithStreamingResponse
+
+ return ChatResourceWithStreamingResponse(self._client.chat)
+
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -482,6 +513,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
+ from .resources.chat import AsyncChatResourceWithStreamingResponse
+
+ return AsyncChatResourceWithStreamingResponse(self._client.chat)
+
Client = Docstrange
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
new file mode 100644
index 0000000..e926095
--- /dev/null
+++ b/src/docstrange/pagination.py
@@ -0,0 +1,67 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Generic, TypeVar, Optional, cast
+from typing_extensions import override
+
+from ._models import BaseModel
+from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
+
+__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
+
+_T = TypeVar("_T")
+
+
+class PageNumberPaginationPagination(BaseModel):
+ has_next: Optional[bool] = None
+
+ total_count: Optional[int] = None
+
+
+class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ results = self.results
+ if not results:
+ return []
+ return results
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
+ return PageInfo(params={"page": last_page + 1})
+
+
+class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ results = self.results
+ if not results:
+ return []
+ return results
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
+ return PageInfo(params={"page": last_page + 1})
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index 6d7ff55..a3172dd 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,5 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .chat import (
+ ChatResource,
+ AsyncChatResource,
+ ChatResourceWithRawResponse,
+ AsyncChatResourceWithRawResponse,
+ ChatResourceWithStreamingResponse,
+ AsyncChatResourceWithStreamingResponse,
+)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -30,4 +38,10 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
+ "ChatResource",
+ "AsyncChatResource",
+ "ChatResourceWithRawResponse",
+ "AsyncChatResourceWithRawResponse",
+ "ChatResourceWithStreamingResponse",
+ "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
new file mode 100644
index 0000000..0a892c1
--- /dev/null
+++ b/src/docstrange/resources/chat.py
@@ -0,0 +1,218 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+
+import httpx
+
+from ..types import chat_create_completion_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+
+__all__ = ["ChatResource", "AsyncChatResource"]
+
+
+class ChatResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ChatResourceWithStreamingResponse(self)
+
+ def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """OpenAI-compatible chat completions endpoint.
+
+ Supports text messages and
+ file/image inputs via `image_url` or `file_url` parts.
+
+ **Limits and behavior:**
+
+ - The backend enforces a model context limit of ~20,000 tokens (text +
+ multimodal tokens).
+ - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
+ and embedded as data URLs.
+ - Inline data URLs are limited to ~64MB decoded size per item.
+
+ For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
+
+ Args:
+ messages: Chat messages array
+
+ model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
+
+ stream: Enable SSE streaming
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._post(
+ "/v1/chat/completions",
+ body=maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class AsyncChatResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncChatResourceWithStreamingResponse(self)
+
+ async def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """OpenAI-compatible chat completions endpoint.
+
+ Supports text messages and
+ file/image inputs via `image_url` or `file_url` parts.
+
+ **Limits and behavior:**
+
+ - The backend enforces a model context limit of ~20,000 tokens (text +
+ multimodal tokens).
+ - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
+ and embedded as data URLs.
+ - Inline data URLs are limited to ~64MB decoded size per item.
+
+ For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
+
+ Args:
+ messages: Chat messages array
+
+ model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
+
+ stream: Enable SSE streaming
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._post(
+ "/v1/chat/completions",
+ body=await async_maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class ChatResourceWithRawResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithRawResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class ChatResourceWithStreamingResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_streamed_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithStreamingResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_streamed_response_wrapper(
+ chat.create_completion,
+ )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index 69045f4..5476a59 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,13 +2,11 @@
from __future__ import annotations
-from typing import Mapping, cast
-
import httpx
-from ..types import classify_sync_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from ..types import classify_sync_params, classify_batch_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -19,6 +17,7 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
+from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -43,6 +42,56 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
+ def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50 files).
+
+ Files are queued for background processing. Use
+ `GET /api/v1/extract/results/{record_id}` to poll results.
+
+ Args:
+ categories: JSON array of category objects (max 50 categories)
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/classify/batch",
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
def sync(
self,
*,
@@ -56,12 +105,17 @@ def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document.
+ Classify a single document into predefined categories synchronously.
+
+ Each page is classified individually with category, confidence score (0-100),
+ and reasoning.
Args:
- categories: JSON array of categories
+ categories:
+ JSON array of category objects: [{"name": "Category Name", "description":
+ "Optional description"}]
- file: File to classify
+ file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
extra_headers: Send extra headers
@@ -71,21 +125,19 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -113,6 +165,56 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
+ async def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50 files).
+
+ Files are queued for background processing. Use
+ `GET /api/v1/extract/results/{record_id}` to poll results.
+
+ Args:
+ categories: JSON array of category objects (max 50 categories)
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/classify/batch",
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
async def sync(
self,
*,
@@ -126,12 +228,17 @@ async def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document.
+ Classify a single document into predefined categories synchronously.
+
+ Each page is classified individually with category, confidence score (0-100),
+ and reasoning.
Args:
- categories: JSON array of categories
+ categories:
+ JSON array of category objects: [{"name": "Category Name", "description":
+ "Optional description"}]
- file: File to classify
+ file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
extra_headers: Send extra headers
@@ -141,21 +248,19 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -167,6 +272,9 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -176,6 +284,9 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -185,6 +296,9 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -194,6 +308,9 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract.py b/src/docstrange/resources/extract.py
deleted file mode 100644
index 88bef17..0000000
--- a/src/docstrange/resources/extract.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Mapping, cast
-
-import httpx
-
-from ..types import extract_sync_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-from ..types.extract_response import ExtractResponse
-
-__all__ = ["ExtractResource", "AsyncExtractResource"]
-
-
-class ExtractResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ExtractResourceWithStreamingResponse(self)
-
- def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload
-
- output_format: Output format
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- body = deepcopy_minimal(
- {
- "file": file,
- "output_format": output_format,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/sync",
- body=maybe_transform(body, extract_sync_params.ExtractSyncParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class AsyncExtractResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncExtractResourceWithStreamingResponse(self)
-
- async def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload
-
- output_format: Output format
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- body = deepcopy_minimal(
- {
- "file": file,
- "output_format": output_format,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/sync",
- body=await async_maybe_transform(body, extract_sync_params.ExtractSyncParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class ExtractResourceWithRawResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.sync = to_raw_response_wrapper(
- extract.sync,
- )
-
-
-class AsyncExtractResourceWithRawResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.sync = async_to_raw_response_wrapper(
- extract.sync,
- )
-
-
-class ExtractResourceWithStreamingResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.sync = to_streamed_response_wrapper(
- extract.sync,
- )
-
-
-class AsyncExtractResourceWithStreamingResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.sync = async_to_streamed_response_wrapper(
- extract.sync,
- )
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
new file mode 100644
index 0000000..22cd257
--- /dev/null
+++ b/src/docstrange/resources/extract/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .extract import (
+ ExtractResource,
+ AsyncExtractResource,
+ ExtractResourceWithRawResponse,
+ AsyncExtractResourceWithRawResponse,
+ ExtractResourceWithStreamingResponse,
+ AsyncExtractResourceWithStreamingResponse,
+)
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ResultsResource",
+ "AsyncResultsResource",
+ "ResultsResourceWithRawResponse",
+ "AsyncResultsResourceWithRawResponse",
+ "ResultsResourceWithStreamingResponse",
+ "AsyncResultsResourceWithStreamingResponse",
+ "ExtractResource",
+ "AsyncExtractResource",
+ "ExtractResourceWithRawResponse",
+ "AsyncExtractResourceWithRawResponse",
+ "ExtractResourceWithStreamingResponse",
+ "AsyncExtractResourceWithStreamingResponse",
+]
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
new file mode 100644
index 0000000..1cca021
--- /dev/null
+++ b/src/docstrange/resources/extract/extract.py
@@ -0,0 +1,814 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
+from ..._types import (
+ Body,
+ Omit,
+ Query,
+ Headers,
+ NotGiven,
+ FileTypes,
+ SequenceNotStr,
+ omit,
+ not_given,
+)
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..._streaming import Stream, AsyncStream
+from ..._base_client import make_request_options
+from ...types.extract_response import ExtractResponse
+from ...types.batch_extract_response import BatchExtractResponse
+from ...types.extract_stream_response import ExtractStreamResponse
+
+__all__ = ["ExtractResource", "AsyncExtractResource"]
+
+
+class ExtractResource(SyncAPIResource):
+ @cached_property
+ def results(self) -> ResultsResource:
+ return ResultsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> ExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ExtractResourceWithStreamingResponse(self)
+
+ def async_(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """Queue a document for background processing.
+
+ Returns a `record_id` to poll
+ results via `GET /api/v1/extract/results/{record_id}`.
+
+ Recommended for large documents (>50 pages).
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/async",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_async_params.ExtractAsyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """Process multiple files asynchronously (max 50 files).
+
+ All files share the same
+ extraction options.
+
+ Args:
+ files: Files to process (max 50)
+
+ output_format: Output format(s) for all files
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/batch",
+ body=maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ def stream(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> Stream[ExtractStreamResponse]:
+ """
+ Stream extraction results via Server-Sent Events (SSE) for real-time content
+ delivery.
+
+ **Event Types:**
+
+ - `content`: Incremental content chunks (streaming mode)
+ - `complete`: Full content at once (batch mode)
+ - `done`: Final event with record_id and processing_time
+ - `error`: Error information
+ - `async_queued`: Large files queued for async processing
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
+ multiple.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
+ mode.
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/stream",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=str,
+ stream=True,
+ stream_cls=Stream[ExtractStreamResponse],
+ )
+
+ def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """Process a document and return extracted content immediately.
+
+ (Works for files
+ with 5 pages or less.)
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/sync",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_sync_params.ExtractSyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class AsyncExtractResource(AsyncAPIResource):
+ @cached_property
+ def results(self) -> AsyncResultsResource:
+ return AsyncResultsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncExtractResourceWithStreamingResponse(self)
+
+ async def async_(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """Queue a document for background processing.
+
+ Returns a `record_id` to poll
+ results via `GET /api/v1/extract/results/{record_id}`.
+
+ Recommended for large documents (>50 pages).
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/async",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_async_params.ExtractAsyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ async def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """Process multiple files asynchronously (max 50 files).
+
+ All files share the same
+ extraction options.
+
+ Args:
+ files: Files to process (max 50)
+
+ output_format: Output format(s) for all files
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/batch",
+ body=await async_maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ async def stream(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncStream[ExtractStreamResponse]:
+ """
+ Stream extraction results via Server-Sent Events (SSE) for real-time content
+ delivery.
+
+ **Event Types:**
+
+ - `content`: Incremental content chunks (streaming mode)
+ - `complete`: Full content at once (batch mode)
+ - `done`: Final event with record_id and processing_time
+ - `error`: Error information
+ - `async_queued`: Large files queued for async processing
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
+ multiple.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
+ mode.
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/stream",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=str,
+ stream=True,
+ stream_cls=AsyncStream[ExtractStreamResponse],
+ )
+
+ async def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """Process a document and return extracted content immediately.
+
+ (Works for files
+ with 5 pages or less.)
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/sync",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_sync_params.ExtractSyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class ExtractResourceWithRawResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_raw_response_wrapper(
+ extract.stream,
+ )
+ self.sync = to_raw_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> ResultsResourceWithRawResponse:
+ return ResultsResourceWithRawResponse(self._extract.results)
+
+
+class AsyncExtractResourceWithRawResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = async_to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_raw_response_wrapper(
+ extract.stream,
+ )
+ self.sync = async_to_raw_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithRawResponse:
+ return AsyncResultsResourceWithRawResponse(self._extract.results)
+
+
+class ExtractResourceWithStreamingResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_streamed_response_wrapper(
+ extract.stream,
+ )
+ self.sync = to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> ResultsResourceWithStreamingResponse:
+ return ResultsResourceWithStreamingResponse(self._extract.results)
+
+
+class AsyncExtractResourceWithStreamingResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = async_to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_streamed_response_wrapper(
+ extract.stream,
+ )
+ self.sync = async_to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithStreamingResponse:
+ return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
new file mode 100644
index 0000000..1533ac2
--- /dev/null
+++ b/src/docstrange/resources/extract/results.py
@@ -0,0 +1,294 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+from ..._base_client import AsyncPaginator, make_request_options
+from ...types.extract import result_list_params, result_retrieve_params
+from ...types.extract_response import ExtractResponse
+
+__all__ = ["ResultsResource", "AsyncResultsResource"]
+
+
+class ResultsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ResultsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ include_content: Include full extracted content (default: true)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> SyncPageNumberPagination[ExtractResponse]:
+ """
+ List all extraction jobs for the authenticated user (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=SyncPageNumberPagination[ExtractResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=ExtractResponse,
+ )
+
+
+class AsyncResultsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncResultsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ include_content: Include full extracted content (default: true)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return await self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncPaginator[ExtractResponse, AsyncPageNumberPagination[ExtractResponse]]:
+ """
+ List all extraction jobs for the authenticated user (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=AsyncPageNumberPagination[ExtractResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=ExtractResponse,
+ )
+
+
+class ResultsResourceWithRawResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithRawResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class ResultsResourceWithStreamingResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithStreamingResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ results.list,
+ )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index fac3955..a18a10a 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -4,5 +4,18 @@
from .extract_response import ExtractResponse as ExtractResponse
from .classify_response import ClassifyResponse as ClassifyResponse
+from .extraction_result import ExtractionResult as ExtractionResult
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
+from .extraction_metadata import ExtractionMetadata as ExtractionMetadata
+from .page_classification import PageClassification as PageClassification
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
+from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
+from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
+from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
+from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
+from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
+from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
+from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
+from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
+from .file_classification_result import FileClassificationResult as FileClassificationResult
+from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
new file mode 100644
index 0000000..a36e5a8
--- /dev/null
+++ b/src/docstrange/types/batch_classify_response.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .file_classification_result import FileClassificationResult
+
+__all__ = ["BatchClassifyResponse"]
+
+
+class BatchClassifyResponse(BaseModel):
+ batch_id: str
+
+ failed_files: int
+
+ message: str
+
+ results: List[FileClassificationResult]
+
+ success: bool
+
+ successful_files: int
+
+ total_files: int
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
new file mode 100644
index 0000000..4e73773
--- /dev/null
+++ b/src/docstrange/types/batch_extract_response.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .extract_response import ExtractResponse
+
+__all__ = ["BatchExtractResponse"]
+
+
+class BatchExtractResponse(BaseModel):
+ accepted_files: int
+
+ batch_id: str
+
+ message: str
+
+ records: List[ExtractResponse]
+
+ rejected_files: int
+
+ success: bool
+
+ total_files: int
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
new file mode 100644
index 0000000..b7cde5c
--- /dev/null
+++ b/src/docstrange/types/chat_create_completion_params.py
@@ -0,0 +1,45 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
+
+
+class ChatCreateCompletionParams(TypedDict, total=False):
+ messages: Required[Iterable[Message]]
+ """Chat messages array"""
+
+ model: Required[str]
+ """Model identifier (e.g., nanonets/Nanonets-OCR-s)"""
+
+ stream: bool
+ """Enable SSE streaming"""
+
+
+class MessageContentFileURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContentImageURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContent(TypedDict, total=False):
+ file_url: MessageContentFileURL
+
+ image_url: MessageContentImageURL
+
+ text: str
+
+ type: str
+
+
+class Message(TypedDict, total=False):
+ content: Required[Iterable[MessageContent]]
+ """Message content as an array of parts (text or file/image URLs)."""
+
+ role: Required[str]
+ """Message role (system, user, assistant)"""
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
new file mode 100644
index 0000000..5cac9e3
--- /dev/null
+++ b/src/docstrange/types/classify_batch_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ClassifyBatchParams"]
+
+
+class ClassifyBatchParams(TypedDict, total=False):
+ categories: Required[str]
+ """JSON array of category objects (max 50 categories)"""
+
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to classify (max 50)"""
diff --git a/src/docstrange/types/classify_response.py b/src/docstrange/types/classify_response.py
index 5bab3de..fdebbb0 100644
--- a/src/docstrange/types/classify_response.py
+++ b/src/docstrange/types/classify_response.py
@@ -1,6 +1,9 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from typing import Optional
+
from .._models import BaseModel
+from .file_classification_result import FileClassificationResult
__all__ = ["ClassifyResponse"]
@@ -9,3 +12,5 @@ class ClassifyResponse(BaseModel):
message: str
success: bool
+
+ result: Optional[FileClassificationResult] = None
diff --git a/src/docstrange/types/classify_sync_params.py b/src/docstrange/types/classify_sync_params.py
index ff11627..772427d 100644
--- a/src/docstrange/types/classify_sync_params.py
+++ b/src/docstrange/types/classify_sync_params.py
@@ -11,7 +11,10 @@
class ClassifySyncParams(TypedDict, total=False):
categories: Required[str]
- """JSON array of categories"""
+ """
+ JSON array of category objects: [{"name": "Category Name", "description":
+ "Optional description"}]
+ """
file: Required[FileTypes]
- """File to classify"""
+ """File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)"""
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
new file mode 100644
index 0000000..387a007
--- /dev/null
+++ b/src/docstrange/types/extract/__init__.py
@@ -0,0 +1,8 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .pagination_info import PaginationInfo as PaginationInfo
+from .result_list_params import ResultListParams as ResultListParams
+from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
+from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
new file mode 100644
index 0000000..26a12e7
--- /dev/null
+++ b/src/docstrange/types/extract/extraction_list_response.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from .pagination_info import PaginationInfo
+from ..extract_response import ExtractResponse
+
+__all__ = ["ExtractionListResponse"]
+
+
+class ExtractionListResponse(BaseModel):
+ pagination: PaginationInfo
+
+ results: List[ExtractResponse]
+
+ success: bool
diff --git a/src/docstrange/types/extract/pagination_info.py b/src/docstrange/types/extract/pagination_info.py
new file mode 100644
index 0000000..7a678a9
--- /dev/null
+++ b/src/docstrange/types/extract/pagination_info.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["PaginationInfo"]
+
+
+class PaginationInfo(BaseModel):
+ has_next: Optional[bool] = None
+
+ has_previous: Optional[bool] = None
+
+ page: Optional[int] = None
+
+ page_size: Optional[int] = None
+
+ total_count: Optional[int] = None
+
+ total_pages: Optional[int] = None
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
new file mode 100644
index 0000000..7dfe38a
--- /dev/null
+++ b/src/docstrange/types/extract/result_list_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["ResultListParams"]
+
+
+class ResultListParams(TypedDict, total=False):
+ page: int
+
+ page_size: int
+
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+
+ sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
new file mode 100644
index 0000000..539b80d
--- /dev/null
+++ b/src/docstrange/types/extract/result_retrieve_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["ResultRetrieveParams"]
+
+
+class ResultRetrieveParams(TypedDict, total=False):
+ include_content: bool
+ """Include full extracted content (default: true)"""
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
new file mode 100644
index 0000000..428e085
--- /dev/null
+++ b/src/docstrange/types/extract_async_params.py
@@ -0,0 +1,45 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractAsyncParams"]
+
+
+class ExtractAsyncParams(TypedDict, total=False):
+ file: Required[FileTypes]
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+
+ output_format: Required[str]
+ """Output format(s): `markdown`, `html`, `json`, `csv`.
+
+ Comma-separate for multiple (e.g., `markdown,json`).
+ """
+
+ csv_options: str
+ """CSV extraction options (e.g., `table`)"""
+
+ custom_instructions: str
+ """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
+
+ json_options: str
+ """JSON extraction options.
+
+ Values: `hierarchy_output`, `table-of-contents`, field list
+ `["field1", "field2"]`, or JSON schema `{...}`
+ """
+
+ prompt_mode: Literal["append", "replace"]
+ """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
new file mode 100644
index 0000000..bdc7b29
--- /dev/null
+++ b/src/docstrange/types/extract_batch_params.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ExtractBatchParams"]
+
+
+class ExtractBatchParams(TypedDict, total=False):
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to process (max 50)"""
+
+ output_format: Required[str]
+ """Output format(s) for all files"""
+
+ csv_options: str
+
+ custom_instructions: str
+
+ include_metadata: str
+
+ json_options: str
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_response.py b/src/docstrange/types/extract_response.py
index ba021e0..9d93ead 100644
--- a/src/docstrange/types/extract_response.py
+++ b/src/docstrange/types/extract_response.py
@@ -1,17 +1,38 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
+from .extraction_result import ExtractionResult
__all__ = ["ExtractResponse"]
class ExtractResponse(BaseModel):
+ message: str
+
record_id: str
+ """Job ID for retrieving results"""
- status: str
+ status: Literal["completed", "processing", "failed"]
success: bool
- message: Optional[str] = None
+ created_at: Optional[datetime] = None
+
+ file_size: Optional[int] = None
+ """Size in bytes"""
+
+ filename: Optional[str] = None
+
+ output_format: Optional[str] = None
+
+ pages_processed: Optional[int] = None
+
+ processing_time: Optional[float] = None
+ """Time in seconds"""
+
+ result: Optional[ExtractionResult] = None
+ """Results by format (only requested formats populated)"""
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
new file mode 100644
index 0000000..087ebc1
--- /dev/null
+++ b/src/docstrange/types/extract_stream_params.py
@@ -0,0 +1,47 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractStreamParams"]
+
+
+class ExtractStreamParams(TypedDict, total=False):
+ file: Required[FileTypes]
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+
+ output_format: Required[str]
+ """Output format(s): `markdown`, `html`, `json`, `csv`.
+
+ Comma-separate for multiple.
+ """
+
+ csv_options: str
+ """CSV extraction options"""
+
+ custom_instructions: str
+ """Custom extraction instructions"""
+
+ enable_streaming: bool
+ """Enable real-time streaming.
+
+ If false, returns complete content via SSE batch mode.
+ """
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
+
+ json_options: str
+ """JSON extraction options"""
+
+ prompt_mode: Literal["append", "replace"]
+ """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
new file mode 100644
index 0000000..333ff97
--- /dev/null
+++ b/src/docstrange/types/extract_stream_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["ExtractStreamResponse"]
+
+ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 242ce95..909fcea 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing_extensions import Required, TypedDict
+from typing_extensions import Literal, Required, TypedDict
from .._types import FileTypes
@@ -11,7 +11,35 @@
class ExtractSyncParams(TypedDict, total=False):
file: Required[FileTypes]
- """File to upload"""
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
output_format: Required[str]
- """Output format"""
+ """Output format(s): `markdown`, `html`, `json`, `csv`.
+
+ Comma-separate for multiple (e.g., `markdown,json`).
+ """
+
+ csv_options: str
+ """CSV extraction options (e.g., `table`)"""
+
+ custom_instructions: str
+ """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
+
+ json_options: str
+ """JSON extraction options.
+
+ Values: `hierarchy_output`, `table-of-contents`, field list
+ `["field1", "field2"]`, or JSON schema `{...}`
+ """
+
+ prompt_mode: Literal["append", "replace"]
+ """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
new file mode 100644
index 0000000..579500c
--- /dev/null
+++ b/src/docstrange/types/extraction_format_result.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union, Optional
+
+from .._models import BaseModel
+from .extraction_metadata import ExtractionMetadata
+
+__all__ = ["ExtractionFormatResult"]
+
+
+class ExtractionFormatResult(BaseModel):
+ content: Union[str, object]
+ """Extracted content"""
+
+ metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/extraction_metadata.py b/src/docstrange/types/extraction_metadata.py
new file mode 100644
index 0000000..9792ba0
--- /dev/null
+++ b/src/docstrange/types/extraction_metadata.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["ExtractionMetadata"]
+
+
+class ExtractionMetadata(BaseModel):
+ bounding_boxes: Optional[object] = None
+ """Element coordinates with page dimensions"""
+
+ confidence_score: Optional[object] = None
+ """Confidence scores per field"""
diff --git a/src/docstrange/types/extraction_result.py b/src/docstrange/types/extraction_result.py
new file mode 100644
index 0000000..57b2928
--- /dev/null
+++ b/src/docstrange/types/extraction_result.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+from .extraction_format_result import ExtractionFormatResult
+
+__all__ = ["ExtractionResult"]
+
+
+class ExtractionResult(BaseModel):
+ """Results by format (only requested formats populated)"""
+
+ csv: Optional[ExtractionFormatResult] = None
+
+ html: Optional[ExtractionFormatResult] = None
+
+ json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
+
+ markdown: Optional[ExtractionFormatResult] = None
diff --git a/src/docstrange/types/file_classification_result.py b/src/docstrange/types/file_classification_result.py
new file mode 100644
index 0000000..397d924
--- /dev/null
+++ b/src/docstrange/types/file_classification_result.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+from .page_classification import PageClassification
+
+__all__ = ["FileClassificationResult"]
+
+
+class FileClassificationResult(BaseModel):
+ filename: str
+
+ pages: List[PageClassification]
+
+ total_pages: int
+
+ error: Optional[str] = None
+
+ processing_time: Optional[float] = None
+ """Time in seconds"""
+
+ record_id: Optional[str] = None
+ """Record ID for polling results"""
diff --git a/src/docstrange/types/page_classification.py b/src/docstrange/types/page_classification.py
new file mode 100644
index 0000000..2099524
--- /dev/null
+++ b/src/docstrange/types/page_classification.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["PageClassification"]
+
+
+class PageClassification(BaseModel):
+ category: str
+ """Matched category name or 'Other' if no match"""
+
+ confidence: int
+ """Confidence score (0-100)"""
+
+ page_number: int
+
+ reasoning: str
+ """Explanation for the classification"""
+
+ identified_category: Optional[str] = None
+ """
+ Specific document type identified by the model (e.g.,
+ 'Invoice_Amazon_Electronics'). Always provided - contains a more detailed
+ classification than the category.
+ """
diff --git a/tests/api_resources/extract/__init__.py b/tests/api_resources/extract/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/extract/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
new file mode 100644
index 0000000..ee1d5f5
--- /dev/null
+++ b/tests/api_resources/extract/test_results.py
@@ -0,0 +1,205 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+from docstrange.types import ExtractResponse
+from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestResults:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Docstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Docstrange) -> None:
+ result = client.extract.results.list()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncResults:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ await async_client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
new file mode 100644
index 0000000..cbcd7c3
--- /dev/null
+++ b/tests/api_resources/test_chat.py
@@ -0,0 +1,183 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestChat:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "https://example.com/doc.pdf"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "file_url",
+ },
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "Extract the text from the document.",
+ "type": "text",
+ },
+ ],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ stream=False,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_create_completion(self, client: Docstrange) -> None:
+ response = client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_create_completion(self, client: Docstrange) -> None:
+ with client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncChat:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "https://example.com/doc.pdf"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "file_url",
+ },
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "Extract the text from the document.",
+ "type": "text",
+ },
+ ],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ stream=False,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index 63539df..b4377f6 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse
+from docstrange.types import ClassifyResponse, BatchClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,11 +17,48 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ classify = client.classify.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.classify.with_raw_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.classify.with_streaming_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
classify = client.classify.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -30,7 +67,7 @@ def test_method_sync(self, client: Docstrange) -> None:
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.classify.with_raw_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
@@ -43,7 +80,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.classify.with_streaming_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
) as response:
assert not response.is_closed
@@ -60,11 +97,48 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ classify = await async_client.classify.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.classify.with_raw_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.classify.with_streaming_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
classify = await async_client.classify.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -73,7 +147,7 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.classify.with_raw_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
@@ -86,7 +160,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.classify.with_streaming_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index d8117c2..bd13f30 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,7 +9,10 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
+from docstrange.types import (
+ ExtractResponse,
+ BatchExtractResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,12 +20,185 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_async(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_async(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream_with_all_params(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_raw_response_stream(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = response.parse()
+ stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_streaming_response_stream(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = response.parse()
+ stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
extract = client.extract.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_sync_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.sync(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -31,7 +207,7 @@ def test_method_sync(self, client: Docstrange) -> None:
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
)
assert response.is_closed is True
@@ -44,7 +220,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -60,12 +236,185 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = await response.parse()
+ await stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = await response.parse()
+ await stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.sync(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -74,7 +423,7 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
)
assert response.is_closed is True
@@ -87,7 +436,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/test_client.py b/tests/test_client.py
index 2756693..719c826 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -862,9 +862,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
- ).__enter__()
+ client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@@ -874,9 +872,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
- ).__enter__()
+ client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -905,7 +901,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
+ response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -930,7 +926,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -955,7 +951,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1773,7 +1769,7 @@ async def test_retrying_timeout_errors_doesnt_leak(
with pytest.raises(APITimeoutError):
await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
+ file=b"raw file contents", output_format="markdown"
).__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1787,7 +1783,7 @@ async def test_retrying_status_errors_doesnt_leak(
with pytest.raises(APIStatusError):
await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
+ file=b"raw file contents", output_format="markdown"
).__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1817,7 +1813,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
+ response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1842,7 +1838,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -1867,7 +1863,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
From a3d7c23e4f6027cb4eabb422a08aae1f1f4db511 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 21:32:12 +0000
Subject: [PATCH 15/26] feat(api): api update
---
.stats.yml | 4 +-
src/docstrange/resources/extract/extract.py | 44 ++++----------------
src/docstrange/types/extract_async_params.py | 11 ++---
src/docstrange/types/extract_sync_params.py | 11 ++---
tests/api_resources/test_extract.py | 8 ----
5 files changed, 18 insertions(+), 60 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index a5ffc81..ccaf55e 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-1f31f87d4c6e168ffcccab94b8967a095195cac1ea2518bbddbeaf4611e02f05.yml
-openapi_spec_hash: 18bec87d90926b0bc0cd98ce1d066d1f
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-7f3f662020a40e0dbf7b19b724cf5c3e69f82246659477c1d71521c0c3cf62a0.yml
+openapi_spec_hash: 53a8f7e0325845d16306ff7cb4272510
config_hash: c02183ee58f815311de9278705163d1a
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
index 1cca021..b83e01b 100644
--- a/src/docstrange/resources/extract/extract.py
+++ b/src/docstrange/resources/extract/extract.py
@@ -75,8 +75,6 @@ def async_(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -95,7 +93,8 @@ def async_(
Recommended for large documents (>50 pages).
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
+ file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
+ file_url or file_base64.
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -104,10 +103,6 @@ def async_(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
@@ -135,8 +130,6 @@ def async_(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
@@ -310,8 +303,6 @@ def sync(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -330,7 +321,8 @@ def sync(
Provide exactly one of: `file`, `file_url`, or `file_base64`.
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
+ file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
+ file_url or file_base64.
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -339,10 +331,6 @@ def sync(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
@@ -370,8 +358,6 @@ def sync(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
@@ -416,8 +402,6 @@ async def async_(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -436,7 +420,8 @@ async def async_(
Recommended for large documents (>50 pages).
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
+ file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
+ file_url or file_base64.
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -445,10 +430,6 @@ async def async_(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
@@ -476,8 +457,6 @@ async def async_(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
@@ -651,8 +630,6 @@ async def sync(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -671,7 +648,8 @@ async def sync(
Provide exactly one of: `file`, `file_url`, or `file_base64`.
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
+ file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
+ file_url or file_base64.
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -680,10 +658,6 @@ async def sync(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
@@ -711,8 +685,6 @@ async def sync(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
index 428e085..fd3f1b4 100644
--- a/src/docstrange/types/extract_async_params.py
+++ b/src/docstrange/types/extract_async_params.py
@@ -11,7 +11,10 @@
class ExtractAsyncParams(TypedDict, total=False):
file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+ """File to upload (PDF, Word, Excel, PowerPoint, images).
+
+ Alternatively use file_url or file_base64.
+ """
output_format: Required[str]
"""Output format(s): `markdown`, `html`, `json`, `csv`.
@@ -25,12 +28,6 @@ class ExtractAsyncParams(TypedDict, total=False):
custom_instructions: str
"""Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
include_metadata: str
"""Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 909fcea..9ad55d7 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -11,7 +11,10 @@
class ExtractSyncParams(TypedDict, total=False):
file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+ """File to upload (PDF, Word, Excel, PowerPoint, images).
+
+ Alternatively use file_url or file_base64.
+ """
output_format: Required[str]
"""Output format(s): `markdown`, `html`, `json`, `csv`.
@@ -25,12 +28,6 @@ class ExtractSyncParams(TypedDict, total=False):
custom_instructions: str
"""Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
include_metadata: str
"""Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index bd13f30..2046ac4 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -37,8 +37,6 @@ def test_method_async_with_all_params(self, client: Docstrange) -> None:
output_format="markdown",
csv_options="",
custom_instructions="",
- file_base64="",
- file_url="",
include_metadata="",
json_options="",
prompt_mode="append",
@@ -194,8 +192,6 @@ def test_method_sync_with_all_params(self, client: Docstrange) -> None:
output_format="markdown",
csv_options="",
custom_instructions="",
- file_base64="",
- file_url="",
include_metadata="",
json_options="",
prompt_mode="append",
@@ -253,8 +249,6 @@ async def test_method_async_with_all_params(self, async_client: AsyncDocstrange)
output_format="markdown",
csv_options="",
custom_instructions="",
- file_base64="",
- file_url="",
include_metadata="",
json_options="",
prompt_mode="append",
@@ -410,8 +404,6 @@ async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange)
output_format="markdown",
csv_options="",
custom_instructions="",
- file_base64="",
- file_url="",
include_metadata="",
json_options="",
prompt_mode="append",
From 9da26d4a173539f2a94608833b3002c5bf4d7f37 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:18:15 +0000
Subject: [PATCH 16/26] feat(api): api update
---
.stats.yml | 6 +-
README.md | 2 +-
src/docstrange/resources/chat.py | 32 +----
src/docstrange/resources/extract/extract.py | 78 ++++++-----
.../types/chat_create_completion_params.py | 2 +-
src/docstrange/types/extract_async_params.py | 17 ++-
src/docstrange/types/extract_stream_params.py | 5 +-
src/docstrange/types/extract_sync_params.py | 17 ++-
.../types/extraction_format_result.py | 6 +-
src/docstrange/types/page_classification.py | 6 +-
tests/api_resources/test_chat.py | 72 ++++------
tests/api_resources/test_classify.py | 24 ++--
tests/api_resources/test_extract.py | 128 ++++++++++--------
tests/test_client.py | 24 ++--
14 files changed, 196 insertions(+), 223 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index ccaf55e..0b3b4fc 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-7f3f662020a40e0dbf7b19b724cf5c3e69f82246659477c1d71521c0c3cf62a0.yml
-openapi_spec_hash: 53a8f7e0325845d16306ff7cb4272510
-config_hash: c02183ee58f815311de9278705163d1a
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-d1e63191b34778603117f266822b2f6f73acbc657307949f2ed9bdb546ab1d88.yml
+openapi_spec_hash: 06568800f2585c2fe3c6069cc9139d16
+config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
diff --git a/README.md b/README.md
index 991dcba..994b399 100644
--- a/README.md
+++ b/README.md
@@ -188,7 +188,7 @@ client = Docstrange()
client.extract.sync(
file=Path("/path/to/file"),
- output_format="markdown",
+ output_format="output_format",
)
```
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
index 0a892c1..bd99e59 100644
--- a/src/docstrange/resources/chat.py
+++ b/src/docstrange/resources/chat.py
@@ -55,20 +55,8 @@ def create_completion(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> object:
- """OpenAI-compatible chat completions endpoint.
-
- Supports text messages and
- file/image inputs via `image_url` or `file_url` parts.
-
- **Limits and behavior:**
-
- - The backend enforces a model context limit of ~20,000 tokens (text +
- multimodal tokens).
- - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
- and embedded as data URLs.
- - Inline data URLs are limited to ~64MB decoded size per item.
-
- For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
+ """
+ OpenAI-compatible chat completions endpoint.
Args:
messages: Chat messages array
@@ -135,20 +123,8 @@ async def create_completion(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> object:
- """OpenAI-compatible chat completions endpoint.
-
- Supports text messages and
- file/image inputs via `image_url` or `file_url` parts.
-
- **Limits and behavior:**
-
- - The backend enforces a model context limit of ~20,000 tokens (text +
- multimodal tokens).
- - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
- and embedded as data URLs.
- - Inline data URLs are limited to ~64MB decoded size per item.
-
- For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
+ """
+ OpenAI-compatible chat completions endpoint.
Args:
messages: Chat messages array
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
index b83e01b..46810ed 100644
--- a/src/docstrange/resources/extract/extract.py
+++ b/src/docstrange/resources/extract/extract.py
@@ -75,6 +75,8 @@ def async_(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -93,8 +95,7 @@ def async_(
Recommended for large documents (>50 pages).
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
- file_url or file_base64.
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -103,10 +104,13 @@ def async_(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
+ json_options: JSON extraction options.
prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
@@ -130,6 +134,8 @@ def async_(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
@@ -225,14 +231,6 @@ def stream(
Stream extraction results via Server-Sent Events (SSE) for real-time content
delivery.
- **Event Types:**
-
- - `content`: Incremental content chunks (streaming mode)
- - `complete`: Full content at once (batch mode)
- - `done`: Final event with record_id and processing_time
- - `error`: Error information
- - `async_queued`: Large files queued for async processing
-
Provide exactly one of: `file`, `file_url`, or `file_base64`.
Args:
@@ -245,8 +243,7 @@ def stream(
custom_instructions: Custom extraction instructions
- enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
- mode.
+ enable_streaming: Enable real-time streaming.
file_base64: Base64-encoded file content
@@ -303,6 +300,8 @@ def sync(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -321,8 +320,7 @@ def sync(
Provide exactly one of: `file`, `file_url`, or `file_base64`.
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
- file_url or file_base64.
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -331,10 +329,13 @@ def sync(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
+ json_options: JSON extraction options.
prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
@@ -358,6 +359,8 @@ def sync(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
@@ -402,6 +405,8 @@ async def async_(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -420,8 +425,7 @@ async def async_(
Recommended for large documents (>50 pages).
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
- file_url or file_base64.
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -430,10 +434,13 @@ async def async_(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
+ json_options: JSON extraction options.
prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
@@ -457,6 +464,8 @@ async def async_(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
@@ -552,14 +561,6 @@ async def stream(
Stream extraction results via Server-Sent Events (SSE) for real-time content
delivery.
- **Event Types:**
-
- - `content`: Incremental content chunks (streaming mode)
- - `complete`: Full content at once (batch mode)
- - `done`: Final event with record_id and processing_time
- - `error`: Error information
- - `async_queued`: Large files queued for async processing
-
Provide exactly one of: `file`, `file_url`, or `file_base64`.
Args:
@@ -572,8 +573,7 @@ async def stream(
custom_instructions: Custom extraction instructions
- enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
- mode.
+ enable_streaming: Enable real-time streaming.
file_base64: Base64-encoded file content
@@ -630,6 +630,8 @@ async def sync(
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
json_options: str | Omit = omit,
prompt_mode: Literal["append", "replace"] | Omit = omit,
@@ -648,8 +650,7 @@ async def sync(
Provide exactly one of: `file`, `file_url`, or `file_base64`.
Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images). Alternatively use
- file_url or file_base64.
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
(e.g., `markdown,json`).
@@ -658,10 +659,13 @@ async def sync(
custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
- json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
- list `["field1", "field2"]`, or JSON schema `{...}`
+ json_options: JSON extraction options.
prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
@@ -685,6 +689,8 @@ async def sync(
"output_format": output_format,
"csv_options": csv_options,
"custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
"include_metadata": include_metadata,
"json_options": json_options,
"prompt_mode": prompt_mode,
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
index b7cde5c..a4a15e7 100644
--- a/src/docstrange/types/chat_create_completion_params.py
+++ b/src/docstrange/types/chat_create_completion_params.py
@@ -39,7 +39,7 @@ class MessageContent(TypedDict, total=False):
class Message(TypedDict, total=False):
content: Required[Iterable[MessageContent]]
- """Message content as an array of parts (text or file/image URLs)."""
+ """Message content as an array of parts."""
role: Required[str]
"""Message role (system, user, assistant)"""
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
index fd3f1b4..364ee01 100644
--- a/src/docstrange/types/extract_async_params.py
+++ b/src/docstrange/types/extract_async_params.py
@@ -11,10 +11,7 @@
class ExtractAsyncParams(TypedDict, total=False):
file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images).
-
- Alternatively use file_url or file_base64.
- """
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
output_format: Required[str]
"""Output format(s): `markdown`, `html`, `json`, `csv`.
@@ -28,15 +25,17 @@ class ExtractAsyncParams(TypedDict, total=False):
custom_instructions: str
"""Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
include_metadata: str
"""Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
json_options: str
- """JSON extraction options.
-
- Values: `hierarchy_output`, `table-of-contents`, field list
- `["field1", "field2"]`, or JSON schema `{...}`
- """
+ """JSON extraction options."""
prompt_mode: Literal["append", "replace"]
"""`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
index 087ebc1..68ee9a6 100644
--- a/src/docstrange/types/extract_stream_params.py
+++ b/src/docstrange/types/extract_stream_params.py
@@ -26,10 +26,7 @@ class ExtractStreamParams(TypedDict, total=False):
"""Custom extraction instructions"""
enable_streaming: bool
- """Enable real-time streaming.
-
- If false, returns complete content via SSE batch mode.
- """
+ """Enable real-time streaming."""
file_base64: str
"""Base64-encoded file content"""
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 9ad55d7..78813f6 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -11,10 +11,7 @@
class ExtractSyncParams(TypedDict, total=False):
file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images).
-
- Alternatively use file_url or file_base64.
- """
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
output_format: Required[str]
"""Output format(s): `markdown`, `html`, `json`, `csv`.
@@ -28,15 +25,17 @@ class ExtractSyncParams(TypedDict, total=False):
custom_instructions: str
"""Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
include_metadata: str
"""Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
json_options: str
- """JSON extraction options.
-
- Values: `hierarchy_output`, `table-of-contents`, field list
- `["field1", "field2"]`, or JSON schema `{...}`
- """
+ """JSON extraction options."""
prompt_mode: Literal["append", "replace"]
"""`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
index 579500c..bfa97a9 100644
--- a/src/docstrange/types/extraction_format_result.py
+++ b/src/docstrange/types/extraction_format_result.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Union, Optional
+from typing import Optional
from .._models import BaseModel
from .extraction_metadata import ExtractionMetadata
@@ -9,7 +9,7 @@
class ExtractionFormatResult(BaseModel):
- content: Union[str, object]
- """Extracted content"""
+ content: object
+ """Extracted content (string or object)"""
metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/page_classification.py b/src/docstrange/types/page_classification.py
index 2099524..62a2338 100644
--- a/src/docstrange/types/page_classification.py
+++ b/src/docstrange/types/page_classification.py
@@ -20,8 +20,4 @@ class PageClassification(BaseModel):
"""Explanation for the classification"""
identified_category: Optional[str] = None
- """
- Specific document type identified by the model (e.g.,
- 'Invoice_Amazon_Electronics'). Always provided - contains a more detailed
- classification than the category.
- """
+ """Specific document type identified by the model."""
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index cbcd7c3..84bfced 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -22,11 +22,11 @@ def test_method_create_completion(self, client: Docstrange) -> None:
chat = client.chat.create_completion(
messages=[
{
- "content": [{}, {}],
- "role": "user",
+ "content": [{}],
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
+ model="model",
)
assert_matches_type(object, chat, path=["response"])
@@ -37,24 +37,18 @@ def test_method_create_completion_with_all_params(self, client: Docstrange) -> N
messages=[
{
"content": [
- {
- "file_url": {"url": "https://example.com/doc.pdf"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "file_url",
- },
{
"file_url": {"url": "url"},
"image_url": {"url": "url"},
- "text": "Extract the text from the document.",
- "type": "text",
- },
+ "text": "text",
+ "type": "type",
+ }
],
- "role": "user",
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
- stream=False,
+ model="model",
+ stream=True,
)
assert_matches_type(object, chat, path=["response"])
@@ -64,11 +58,11 @@ def test_raw_response_create_completion(self, client: Docstrange) -> None:
response = client.chat.with_raw_response.create_completion(
messages=[
{
- "content": [{}, {}],
- "role": "user",
+ "content": [{}],
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
+ model="model",
)
assert response.is_closed is True
@@ -82,11 +76,11 @@ def test_streaming_response_create_completion(self, client: Docstrange) -> None:
with client.chat.with_streaming_response.create_completion(
messages=[
{
- "content": [{}, {}],
- "role": "user",
+ "content": [{}],
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
+ model="model",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -108,11 +102,11 @@ async def test_method_create_completion(self, async_client: AsyncDocstrange) ->
chat = await async_client.chat.create_completion(
messages=[
{
- "content": [{}, {}],
- "role": "user",
+ "content": [{}],
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
+ model="model",
)
assert_matches_type(object, chat, path=["response"])
@@ -123,24 +117,18 @@ async def test_method_create_completion_with_all_params(self, async_client: Asyn
messages=[
{
"content": [
- {
- "file_url": {"url": "https://example.com/doc.pdf"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "file_url",
- },
{
"file_url": {"url": "url"},
"image_url": {"url": "url"},
- "text": "Extract the text from the document.",
- "type": "text",
- },
+ "text": "text",
+ "type": "type",
+ }
],
- "role": "user",
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
- stream=False,
+ model="model",
+ stream=True,
)
assert_matches_type(object, chat, path=["response"])
@@ -150,11 +138,11 @@ async def test_raw_response_create_completion(self, async_client: AsyncDocstrang
response = await async_client.chat.with_raw_response.create_completion(
messages=[
{
- "content": [{}, {}],
- "role": "user",
+ "content": [{}],
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
+ model="model",
)
assert response.is_closed is True
@@ -168,11 +156,11 @@ async def test_streaming_response_create_completion(self, async_client: AsyncDoc
async with async_client.chat.with_streaming_response.create_completion(
messages=[
{
- "content": [{}, {}],
- "role": "user",
+ "content": [{}],
+ "role": "role",
}
],
- model="nanonets/Nanonets-OCR-s",
+ model="model",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index b4377f6..d40e1fa 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -21,7 +21,7 @@ class TestClassify:
@parametrize
def test_method_batch(self, client: Docstrange) -> None:
classify = client.classify.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ categories="categories",
files=[b"raw file contents"],
)
assert_matches_type(BatchClassifyResponse, classify, path=["response"])
@@ -30,7 +30,7 @@ def test_method_batch(self, client: Docstrange) -> None:
@parametrize
def test_raw_response_batch(self, client: Docstrange) -> None:
response = client.classify.with_raw_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ categories="categories",
files=[b"raw file contents"],
)
@@ -43,7 +43,7 @@ def test_raw_response_batch(self, client: Docstrange) -> None:
@parametrize
def test_streaming_response_batch(self, client: Docstrange) -> None:
with client.classify.with_streaming_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ categories="categories",
files=[b"raw file contents"],
) as response:
assert not response.is_closed
@@ -58,7 +58,7 @@ def test_streaming_response_batch(self, client: Docstrange) -> None:
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
classify = client.classify.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -67,7 +67,7 @@ def test_method_sync(self, client: Docstrange) -> None:
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.classify.with_raw_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
@@ -80,7 +80,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.classify.with_streaming_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
) as response:
assert not response.is_closed
@@ -101,7 +101,7 @@ class TestAsyncClassify:
@parametrize
async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
classify = await async_client.classify.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ categories="categories",
files=[b"raw file contents"],
)
assert_matches_type(BatchClassifyResponse, classify, path=["response"])
@@ -110,7 +110,7 @@ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
response = await async_client.classify.with_raw_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ categories="categories",
files=[b"raw file contents"],
)
@@ -123,7 +123,7 @@ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
async with async_client.classify.with_streaming_response.batch(
- categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ categories="categories",
files=[b"raw file contents"],
) as response:
assert not response.is_closed
@@ -138,7 +138,7 @@ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) ->
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
classify = await async_client.classify.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -147,7 +147,7 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.classify.with_raw_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
)
@@ -160,7 +160,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.classify.with_streaming_response.sync(
- categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
+ categories="categories",
file=b"raw file contents",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index 2046ac4..4f68b18 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -25,7 +25,7 @@ class TestExtract:
def test_method_async(self, client: Docstrange) -> None:
extract = client.extract.async_(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -34,11 +34,13 @@ def test_method_async(self, client: Docstrange) -> None:
def test_method_async_with_all_params(self, client: Docstrange) -> None:
extract = client.extract.async_(
file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- include_metadata="",
- json_options="",
+ output_format="output_format",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ file_base64="file_base64",
+ file_url="file_url",
+ include_metadata="include_metadata",
+ json_options="json_options",
prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -48,7 +50,7 @@ def test_method_async_with_all_params(self, client: Docstrange) -> None:
def test_raw_response_async(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.async_(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -61,7 +63,7 @@ def test_raw_response_async(self, client: Docstrange) -> None:
def test_streaming_response_async(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.async_(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -76,7 +78,7 @@ def test_streaming_response_async(self, client: Docstrange) -> None:
def test_method_batch(self, client: Docstrange) -> None:
extract = client.extract.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
)
assert_matches_type(BatchExtractResponse, extract, path=["response"])
@@ -85,7 +87,7 @@ def test_method_batch(self, client: Docstrange) -> None:
def test_method_batch_with_all_params(self, client: Docstrange) -> None:
extract = client.extract.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
csv_options="csv_options",
custom_instructions="custom_instructions",
include_metadata="include_metadata",
@@ -99,7 +101,7 @@ def test_method_batch_with_all_params(self, client: Docstrange) -> None:
def test_raw_response_batch(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -112,7 +114,7 @@ def test_raw_response_batch(self, client: Docstrange) -> None:
def test_streaming_response_batch(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -127,7 +129,7 @@ def test_streaming_response_batch(self, client: Docstrange) -> None:
def test_method_stream(self, client: Docstrange) -> None:
extract_stream = client.extract.stream(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
extract_stream.response.close()
@@ -136,14 +138,14 @@ def test_method_stream(self, client: Docstrange) -> None:
def test_method_stream_with_all_params(self, client: Docstrange) -> None:
extract_stream = client.extract.stream(
file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
+ output_format="output_format",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
enable_streaming=True,
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
+ file_base64="file_base64",
+ file_url="file_url",
+ include_metadata="include_metadata",
+ json_options="json_options",
prompt_mode="append",
)
extract_stream.response.close()
@@ -153,7 +155,7 @@ def test_method_stream_with_all_params(self, client: Docstrange) -> None:
def test_raw_response_stream(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.stream(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -165,7 +167,7 @@ def test_raw_response_stream(self, client: Docstrange) -> None:
def test_streaming_response_stream(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.stream(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -180,7 +182,7 @@ def test_streaming_response_stream(self, client: Docstrange) -> None:
def test_method_sync(self, client: Docstrange) -> None:
extract = client.extract.sync(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -189,11 +191,13 @@ def test_method_sync(self, client: Docstrange) -> None:
def test_method_sync_with_all_params(self, client: Docstrange) -> None:
extract = client.extract.sync(
file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- include_metadata="",
- json_options="",
+ output_format="output_format",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ file_base64="file_base64",
+ file_url="file_url",
+ include_metadata="include_metadata",
+ json_options="json_options",
prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -203,7 +207,7 @@ def test_method_sync_with_all_params(self, client: Docstrange) -> None:
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.sync(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -216,7 +220,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.sync(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -237,7 +241,7 @@ class TestAsyncExtract:
async def test_method_async(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.async_(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -246,11 +250,13 @@ async def test_method_async(self, async_client: AsyncDocstrange) -> None:
async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.async_(
file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- include_metadata="",
- json_options="",
+ output_format="output_format",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ file_base64="file_base64",
+ file_url="file_url",
+ include_metadata="include_metadata",
+ json_options="json_options",
prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -260,7 +266,7 @@ async def test_method_async_with_all_params(self, async_client: AsyncDocstrange)
async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.async_(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -273,7 +279,7 @@ async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.async_(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -288,7 +294,7 @@ async def test_streaming_response_async(self, async_client: AsyncDocstrange) ->
async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
)
assert_matches_type(BatchExtractResponse, extract, path=["response"])
@@ -297,7 +303,7 @@ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
csv_options="csv_options",
custom_instructions="custom_instructions",
include_metadata="include_metadata",
@@ -311,7 +317,7 @@ async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange)
async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -324,7 +330,7 @@ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.batch(
files=[b"raw file contents"],
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -339,7 +345,7 @@ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) ->
async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
extract_stream = await async_client.extract.stream(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
await extract_stream.response.aclose()
@@ -348,14 +354,14 @@ async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
extract_stream = await async_client.extract.stream(
file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
+ output_format="output_format",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
enable_streaming=True,
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
+ file_base64="file_base64",
+ file_url="file_url",
+ include_metadata="include_metadata",
+ json_options="json_options",
prompt_mode="append",
)
await extract_stream.response.aclose()
@@ -365,7 +371,7 @@ async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange
async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.stream(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -377,7 +383,7 @@ async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.stream(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -392,7 +398,7 @@ async def test_streaming_response_stream(self, async_client: AsyncDocstrange) ->
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.sync(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -401,11 +407,13 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.sync(
file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- include_metadata="",
- json_options="",
+ output_format="output_format",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ file_base64="file_base64",
+ file_url="file_url",
+ include_metadata="include_metadata",
+ json_options="json_options",
prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -415,7 +423,7 @@ async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange)
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.sync(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
)
assert response.is_closed is True
@@ -428,7 +436,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.sync(
file=b"raw file contents",
- output_format="markdown",
+ output_format="output_format",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/test_client.py b/tests/test_client.py
index 719c826..2756693 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -862,7 +862,9 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(
+ file=b"raw file contents", output_format="output_format"
+ ).__enter__()
assert _get_open_connections(client) == 0
@@ -872,7 +874,9 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(
+ file=b"raw file contents", output_format="output_format"
+ ).__enter__()
assert _get_open_connections(client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -901,7 +905,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
+ response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -926,7 +930,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -951,7 +955,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1769,7 +1773,7 @@ async def test_retrying_timeout_errors_doesnt_leak(
with pytest.raises(APITimeoutError):
await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="markdown"
+ file=b"raw file contents", output_format="output_format"
).__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1783,7 +1787,7 @@ async def test_retrying_status_errors_doesnt_leak(
with pytest.raises(APIStatusError):
await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="markdown"
+ file=b"raw file contents", output_format="output_format"
).__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1813,7 +1817,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
+ response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1838,7 +1842,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -1863,7 +1867,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
From 9cfaf51d7c188ab63fc6352d6a689e5c0a8dbe58 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:20:46 +0000
Subject: [PATCH 17/26] feat(api): api update
---
.stats.yml | 6 +-
README.md | 61 --
api.md | 50 +-
src/docstrange/_client.py | 39 +-
src/docstrange/resources/__init__.py | 14 -
src/docstrange/resources/chat.py | 194 ------
src/docstrange/resources/classify.py | 175 +----
src/docstrange/resources/extract/__init__.py | 14 -
src/docstrange/resources/extract/extract.py | 649 +-----------------
src/docstrange/resources/extract/results.py | 294 --------
src/docstrange/types/__init__.py | 13 -
.../types/batch_classify_response.py | 24 -
.../types/batch_extract_response.py | 24 -
.../types/chat_create_completion_params.py | 45 --
src/docstrange/types/classify_batch_params.py | 17 -
src/docstrange/types/classify_response.py | 5 -
src/docstrange/types/classify_sync_params.py | 7 +-
src/docstrange/types/extract/__init__.py | 5 -
.../types/extract/extraction_list_response.py | 17 -
.../types/extract/pagination_info.py | 21 -
.../types/extract/result_list_params.py | 17 -
.../types/extract/result_retrieve_params.py | 12 -
src/docstrange/types/extract_async_params.py | 41 --
src/docstrange/types/extract_batch_params.py | 27 -
src/docstrange/types/extract_response.py | 25 +-
src/docstrange/types/extract_stream_params.py | 44 --
.../types/extract_stream_response.py | 7 -
src/docstrange/types/extract_sync_params.py | 30 +-
.../types/extraction_format_result.py | 15 -
src/docstrange/types/extraction_metadata.py | 15 -
src/docstrange/types/extraction_result.py | 22 -
.../types/file_classification_result.py | 24 -
src/docstrange/types/page_classification.py | 23 -
tests/api_resources/extract/test_results.py | 205 ------
tests/api_resources/test_chat.py | 171 -----
tests/api_resources/test_classify.py | 76 +-
tests/api_resources/test_extract.py | 351 +---------
37 files changed, 72 insertions(+), 2707 deletions(-)
delete mode 100644 src/docstrange/resources/chat.py
delete mode 100644 src/docstrange/resources/extract/results.py
delete mode 100644 src/docstrange/types/batch_classify_response.py
delete mode 100644 src/docstrange/types/batch_extract_response.py
delete mode 100644 src/docstrange/types/chat_create_completion_params.py
delete mode 100644 src/docstrange/types/classify_batch_params.py
delete mode 100644 src/docstrange/types/extract/extraction_list_response.py
delete mode 100644 src/docstrange/types/extract/pagination_info.py
delete mode 100644 src/docstrange/types/extract/result_list_params.py
delete mode 100644 src/docstrange/types/extract/result_retrieve_params.py
delete mode 100644 src/docstrange/types/extract_async_params.py
delete mode 100644 src/docstrange/types/extract_batch_params.py
delete mode 100644 src/docstrange/types/extract_stream_params.py
delete mode 100644 src/docstrange/types/extract_stream_response.py
delete mode 100644 src/docstrange/types/extraction_format_result.py
delete mode 100644 src/docstrange/types/extraction_metadata.py
delete mode 100644 src/docstrange/types/extraction_result.py
delete mode 100644 src/docstrange/types/file_classification_result.py
delete mode 100644 src/docstrange/types/page_classification.py
delete mode 100644 tests/api_resources/extract/test_results.py
delete mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index 0b3b4fc..1d97927 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-d1e63191b34778603117f266822b2f6f73acbc657307949f2ed9bdb546ab1d88.yml
-openapi_spec_hash: 06568800f2585c2fe3c6069cc9139d16
+configured_endpoints: 2
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-3843cc83cc328a1c86126018a4309fbcd13aac4df5fd9afefd652e21e59530ab.yml
+openapi_spec_hash: b4046d95714426b15edb8ac003f904c6
config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
diff --git a/README.md b/README.md
index 994b399..622faec 100644
--- a/README.md
+++ b/README.md
@@ -115,67 +115,6 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
-## Pagination
-
-List methods in the Docstrange API are paginated.
-
-This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
-
-```python
-from docstrange import Docstrange
-
-client = Docstrange()
-
-all_results = []
-# Automatically fetches more pages as needed.
-for result in client.extract.results.list():
- # Do something with result here
- all_results.append(result)
-print(all_results)
-```
-
-Or, asynchronously:
-
-```python
-import asyncio
-from docstrange import AsyncDocstrange
-
-client = AsyncDocstrange()
-
-
-async def main() -> None:
- all_results = []
- # Iterate through items across all pages, issuing requests as needed.
- async for result in client.extract.results.list():
- all_results.append(result)
- print(all_results)
-
-
-asyncio.run(main())
-```
-
-Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
-
-```python
-first_page = await client.extract.results.list()
-if first_page.has_next_page():
- print(f"will fetch next page using these details: {first_page.next_page_info()}")
- next_page = await first_page.get_next_page()
- print(f"number of items we just fetched: {len(next_page.results)}")
-
-# Remove `await` for non-async usage.
-```
-
-Or just work directly with the returned data:
-
-```python
-first_page = await client.extract.results.list()
-for result in first_page.results:
- print(result.record_id)
-
-# Remove `await` for non-async usage.
-```
-
## File uploads
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)`.
diff --git a/api.md b/api.md
index 7ccbce8..90358a6 100644
--- a/api.md
+++ b/api.md
@@ -3,67 +3,21 @@
Types:
```python
-from docstrange.types import (
- BatchExtractRequestBody,
- BatchExtractResponse,
- ExtractRequestBody,
- ExtractResponse,
- ExtractionFormatResult,
- ExtractionMetadata,
- ExtractionResult,
- StreamExtractRequestBody,
- ExtractStreamResponse,
-)
+from docstrange.types import ExtractResponse
```
Methods:
-- client.extract.async\_(\*\*params) -> ExtractResponse
-- client.extract.batch(\*\*params) -> BatchExtractResponse
-- client.extract.stream(\*\*params) -> str
- client.extract.sync(\*\*params) -> ExtractResponse
-## Results
-
-Types:
-
-```python
-from docstrange.types.extract import ExtractionListResponse, PaginationInfo
-```
-
-Methods:
-
-- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
-- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[ExtractResponse]
-
# Classify
Types:
```python
-from docstrange.types import (
- BatchClassifyRequestBody,
- BatchClassifyResponse,
- ClassifyRequestBody,
- ClassifyResponse,
- FileClassificationResult,
- PageClassification,
-)
+from docstrange.types import ClassifyResponse
```
Methods:
-- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
-
-# Chat
-
-Types:
-
-```python
-from docstrange.types import ChatCompletionsRequest
-```
-
-Methods:
-
-- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 4c5bcc4..271a014 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,8 +31,7 @@
)
if TYPE_CHECKING:
- from .resources import chat, extract, classify
- from .resources.chat import ChatResource, AsyncChatResource
+ from .resources import extract, classify
from .resources.classify import ClassifyResource, AsyncClassifyResource
from .resources.extract.extract import ExtractResource, AsyncExtractResource
@@ -115,12 +114,6 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
- @cached_property
- def chat(self) -> ChatResource:
- from .resources.chat import ChatResource
-
- return ChatResource(self)
-
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -301,12 +294,6 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
- @cached_property
- def chat(self) -> AsyncChatResource:
- from .resources.chat import AsyncChatResource
-
- return AsyncChatResource(self)
-
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -438,12 +425,6 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithRawResponse:
- from .resources.chat import ChatResourceWithRawResponse
-
- return ChatResourceWithRawResponse(self._client.chat)
-
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -463,12 +444,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithRawResponse:
- from .resources.chat import AsyncChatResourceWithRawResponse
-
- return AsyncChatResourceWithRawResponse(self._client.chat)
-
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -488,12 +463,6 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithStreamingResponse:
- from .resources.chat import ChatResourceWithStreamingResponse
-
- return ChatResourceWithStreamingResponse(self._client.chat)
-
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -513,12 +482,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
- from .resources.chat import AsyncChatResourceWithStreamingResponse
-
- return AsyncChatResourceWithStreamingResponse(self._client.chat)
-
Client = Docstrange
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index a3172dd..6d7ff55 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,13 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from .chat import (
- ChatResource,
- AsyncChatResource,
- ChatResourceWithRawResponse,
- AsyncChatResourceWithRawResponse,
- ChatResourceWithStreamingResponse,
- AsyncChatResourceWithStreamingResponse,
-)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -38,10 +30,4 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
- "ChatResource",
- "AsyncChatResource",
- "ChatResourceWithRawResponse",
- "AsyncChatResourceWithRawResponse",
- "ChatResourceWithStreamingResponse",
- "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
deleted file mode 100644
index bd99e59..0000000
--- a/src/docstrange/resources/chat.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-
-import httpx
-
-from ..types import chat_create_completion_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-
-__all__ = ["ChatResource", "AsyncChatResource"]
-
-
-class ChatResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ChatResourceWithStreamingResponse(self)
-
- def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- OpenAI-compatible chat completions endpoint.
-
- Args:
- messages: Chat messages array
-
- model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
-
- stream: Enable SSE streaming
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._post(
- "/v1/chat/completions",
- body=maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class AsyncChatResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncChatResourceWithStreamingResponse(self)
-
- async def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- OpenAI-compatible chat completions endpoint.
-
- Args:
- messages: Chat messages array
-
- model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
-
- stream: Enable SSE streaming
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return await self._post(
- "/v1/chat/completions",
- body=await async_maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class ChatResourceWithRawResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithRawResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class ChatResourceWithStreamingResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_streamed_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithStreamingResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_streamed_response_wrapper(
- chat.create_completion,
- )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index 5476a59..69045f4 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,11 +2,13 @@
from __future__ import annotations
+from typing import Mapping, cast
+
import httpx
-from ..types import classify_sync_params, classify_batch_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from ..types import classify_sync_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -17,7 +19,6 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
-from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -42,56 +43,6 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
- def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50 files).
-
- Files are queued for background processing. Use
- `GET /api/v1/extract/results/{record_id}` to poll results.
-
- Args:
- categories: JSON array of category objects (max 50 categories)
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/classify/batch",
- body=maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
def sync(
self,
*,
@@ -105,17 +56,12 @@ def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document into predefined categories synchronously.
-
- Each page is classified individually with category, confidence score (0-100),
- and reasoning.
+ Classify a single document.
Args:
- categories:
- JSON array of category objects: [{"name": "Category Name", "description":
- "Optional description"}]
+ categories: JSON array of categories
- file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
+ file: File to classify
extra_headers: Send extra headers
@@ -125,19 +71,21 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -165,56 +113,6 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
- async def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50 files).
-
- Files are queued for background processing. Use
- `GET /api/v1/extract/results/{record_id}` to poll results.
-
- Args:
- categories: JSON array of category objects (max 50 categories)
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/classify/batch",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
async def sync(
self,
*,
@@ -228,17 +126,12 @@ async def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document into predefined categories synchronously.
-
- Each page is classified individually with category, confidence score (0-100),
- and reasoning.
+ Classify a single document.
Args:
- categories:
- JSON array of category objects: [{"name": "Category Name", "description":
- "Optional description"}]
+ categories: JSON array of categories
- file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
+ file: File to classify
extra_headers: Send extra headers
@@ -248,19 +141,21 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -272,9 +167,6 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_raw_response_wrapper(
- classify.batch,
- )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -284,9 +176,6 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_raw_response_wrapper(
- classify.batch,
- )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -296,9 +185,6 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -308,9 +194,6 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
index 22cd257..a0fee27 100644
--- a/src/docstrange/resources/extract/__init__.py
+++ b/src/docstrange/resources/extract/__init__.py
@@ -8,22 +8,8 @@
ExtractResourceWithStreamingResponse,
AsyncExtractResourceWithStreamingResponse,
)
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
__all__ = [
- "ResultsResource",
- "AsyncResultsResource",
- "ResultsResourceWithRawResponse",
- "AsyncResultsResourceWithRawResponse",
- "ResultsResourceWithStreamingResponse",
- "AsyncResultsResourceWithStreamingResponse",
"ExtractResource",
"AsyncExtractResource",
"ExtractResourceWithRawResponse",
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
index 46810ed..0fe0d14 100644
--- a/src/docstrange/resources/extract/extract.py
+++ b/src/docstrange/resources/extract/extract.py
@@ -2,31 +2,13 @@
from __future__ import annotations
-from typing_extensions import Literal
+from typing import Mapping, cast
import httpx
-from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
-from ..._types import (
- Body,
- Omit,
- Query,
- Headers,
- NotGiven,
- FileTypes,
- SequenceNotStr,
- omit,
- not_given,
-)
-from ..._utils import maybe_transform, async_maybe_transform
+from ...types import extract_sync_params
+from ..._types import Body, Query, Headers, NotGiven, FileTypes, not_given
+from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -35,20 +17,13 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ..._streaming import Stream, AsyncStream
from ..._base_client import make_request_options
from ...types.extract_response import ExtractResponse
-from ...types.batch_extract_response import BatchExtractResponse
-from ...types.extract_stream_response import ExtractStreamResponse
__all__ = ["ExtractResource", "AsyncExtractResource"]
class ExtractResource(SyncAPIResource):
- @cached_property
- def results(self) -> ResultsResource:
- return ResultsResource(self._client)
-
@cached_property
def with_raw_response(self) -> ExtractResourceWithRawResponse:
"""
@@ -68,18 +43,11 @@ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
"""
return ExtractResourceWithStreamingResponse(self)
- def async_(
+ def sync(
self,
*,
file: FileTypes,
output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -87,93 +55,13 @@ def async_(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ExtractResponse:
- """Queue a document for background processing.
-
- Returns a `record_id` to poll
- results via `GET /api/v1/extract/results/{record_id}`.
-
- Recommended for large documents (>50 pages).
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options.
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
"""
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/async",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """Process multiple files asynchronously (max 50 files).
-
- All files share the same
- extraction options.
+ Process a document and return extracted content immediately.
Args:
- files: Files to process (max 50)
+ file: File to upload
- output_format: Output format(s) for all files
+ output_format: Output format
extra_headers: Send extra headers
@@ -183,190 +71,21 @@ def batch(
timeout: Override the client-level default timeout for this request, in seconds
"""
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/batch",
- body=maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
+ body = deepcopy_minimal(
+ {
+ "file": file,
+ "output_format": output_format,
+ }
)
-
- def stream(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Stream[ExtractStreamResponse]:
- """
- Stream extraction results via Server-Sent Events (SSE) for real-time content
- delivery.
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
- multiple.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- enable_streaming: Enable real-time streaming.
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/stream",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=Stream[ExtractStreamResponse],
- )
-
- def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """Process a document and return extracted content immediately.
-
- (Works for files
- with 5 pages or less.)
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options.
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/extract/sync",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
- ),
+ body=maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -375,10 +94,6 @@ def sync(
class AsyncExtractResource(AsyncAPIResource):
- @cached_property
- def results(self) -> AsyncResultsResource:
- return AsyncResultsResource(self._client)
-
@cached_property
def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
"""
@@ -398,18 +113,11 @@ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
"""
return AsyncExtractResourceWithStreamingResponse(self)
- async def async_(
+ async def sync(
self,
*,
file: FileTypes,
output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -417,93 +125,13 @@ async def async_(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ExtractResponse:
- """Queue a document for background processing.
-
- Returns a `record_id` to poll
- results via `GET /api/v1/extract/results/{record_id}`.
-
- Recommended for large documents (>50 pages).
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options.
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
"""
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/async",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- async def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """Process multiple files asynchronously (max 50 files).
-
- All files share the same
- extraction options.
+ Process a document and return extracted content immediately.
Args:
- files: Files to process (max 50)
+ file: File to upload
- output_format: Output format(s) for all files
+ output_format: Output format
extra_headers: Send extra headers
@@ -513,190 +141,21 @@ async def batch(
timeout: Override the client-level default timeout for this request, in seconds
"""
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/batch",
- body=await async_maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
+ body = deepcopy_minimal(
+ {
+ "file": file,
+ "output_format": output_format,
+ }
)
-
- async def stream(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncStream[ExtractStreamResponse]:
- """
- Stream extraction results via Server-Sent Events (SSE) for real-time content
- delivery.
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
- multiple.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- enable_streaming: Enable real-time streaming.
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/stream",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=AsyncStream[ExtractStreamResponse],
- )
-
- async def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """Process a document and return extracted content immediately.
-
- (Works for files
- with 5 pages or less.)
-
- Provide exactly one of: `file`, `file_url`, or `file_base64`.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
- (e.g., `markdown,json`).
-
- csv_options: CSV extraction options (e.g., `table`)
-
- custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
-
- json_options: JSON extraction options.
-
- prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/extract/sync",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
- ),
+ body=await async_maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -708,85 +167,33 @@ class ExtractResourceWithRawResponse:
def __init__(self, extract: ExtractResource) -> None:
self._extract = extract
- self.async_ = to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = to_raw_response_wrapper(
- extract.stream,
- )
self.sync = to_raw_response_wrapper(
extract.sync,
)
- @cached_property
- def results(self) -> ResultsResourceWithRawResponse:
- return ResultsResourceWithRawResponse(self._extract.results)
-
class AsyncExtractResourceWithRawResponse:
def __init__(self, extract: AsyncExtractResource) -> None:
self._extract = extract
- self.async_ = async_to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_raw_response_wrapper(
- extract.stream,
- )
self.sync = async_to_raw_response_wrapper(
extract.sync,
)
- @cached_property
- def results(self) -> AsyncResultsResourceWithRawResponse:
- return AsyncResultsResourceWithRawResponse(self._extract.results)
-
class ExtractResourceWithStreamingResponse:
def __init__(self, extract: ExtractResource) -> None:
self._extract = extract
- self.async_ = to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = to_streamed_response_wrapper(
- extract.stream,
- )
self.sync = to_streamed_response_wrapper(
extract.sync,
)
- @cached_property
- def results(self) -> ResultsResourceWithStreamingResponse:
- return ResultsResourceWithStreamingResponse(self._extract.results)
-
class AsyncExtractResourceWithStreamingResponse:
def __init__(self, extract: AsyncExtractResource) -> None:
self._extract = extract
- self.async_ = async_to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_streamed_response_wrapper(
- extract.stream,
- )
self.sync = async_to_streamed_response_wrapper(
extract.sync,
)
-
- @cached_property
- def results(self) -> AsyncResultsResourceWithStreamingResponse:
- return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
deleted file mode 100644
index 1533ac2..0000000
--- a/src/docstrange/resources/extract/results.py
+++ /dev/null
@@ -1,294 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-from ..._base_client import AsyncPaginator, make_request_options
-from ...types.extract import result_list_params, result_retrieve_params
-from ...types.extract_response import ExtractResponse
-
-__all__ = ["ResultsResource", "AsyncResultsResource"]
-
-
-class ResultsResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ResultsResourceWithStreamingResponse(self)
-
- def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- include_content: Include full extracted content (default: true)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> SyncPageNumberPagination[ExtractResponse]:
- """
- List all extraction jobs for the authenticated user (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=SyncPageNumberPagination[ExtractResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=ExtractResponse,
- )
-
-
-class AsyncResultsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncResultsResourceWithStreamingResponse(self)
-
- async def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- include_content: Include full extracted content (default: true)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return await self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncPaginator[ExtractResponse, AsyncPageNumberPagination[ExtractResponse]]:
- """
- List all extraction jobs for the authenticated user (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=AsyncPageNumberPagination[ExtractResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=ExtractResponse,
- )
-
-
-class ResultsResourceWithRawResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = to_raw_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithRawResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_raw_response_wrapper(
- results.list,
- )
-
-
-class ResultsResourceWithStreamingResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = to_streamed_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithStreamingResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_streamed_response_wrapper(
- results.list,
- )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index a18a10a..fac3955 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -4,18 +4,5 @@
from .extract_response import ExtractResponse as ExtractResponse
from .classify_response import ClassifyResponse as ClassifyResponse
-from .extraction_result import ExtractionResult as ExtractionResult
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
-from .extraction_metadata import ExtractionMetadata as ExtractionMetadata
-from .page_classification import PageClassification as PageClassification
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
-from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
-from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
-from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
-from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
-from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
-from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
-from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
-from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
-from .file_classification_result import FileClassificationResult as FileClassificationResult
-from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
deleted file mode 100644
index a36e5a8..0000000
--- a/src/docstrange/types/batch_classify_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-from .file_classification_result import FileClassificationResult
-
-__all__ = ["BatchClassifyResponse"]
-
-
-class BatchClassifyResponse(BaseModel):
- batch_id: str
-
- failed_files: int
-
- message: str
-
- results: List[FileClassificationResult]
-
- success: bool
-
- successful_files: int
-
- total_files: int
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
deleted file mode 100644
index 4e73773..0000000
--- a/src/docstrange/types/batch_extract_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-from .extract_response import ExtractResponse
-
-__all__ = ["BatchExtractResponse"]
-
-
-class BatchExtractResponse(BaseModel):
- accepted_files: int
-
- batch_id: str
-
- message: str
-
- records: List[ExtractResponse]
-
- rejected_files: int
-
- success: bool
-
- total_files: int
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
deleted file mode 100644
index a4a15e7..0000000
--- a/src/docstrange/types/chat_create_completion_params.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-from typing_extensions import Required, TypedDict
-
-__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
-
-
-class ChatCreateCompletionParams(TypedDict, total=False):
- messages: Required[Iterable[Message]]
- """Chat messages array"""
-
- model: Required[str]
- """Model identifier (e.g., nanonets/Nanonets-OCR-s)"""
-
- stream: bool
- """Enable SSE streaming"""
-
-
-class MessageContentFileURL(TypedDict, total=False):
- url: str
-
-
-class MessageContentImageURL(TypedDict, total=False):
- url: str
-
-
-class MessageContent(TypedDict, total=False):
- file_url: MessageContentFileURL
-
- image_url: MessageContentImageURL
-
- text: str
-
- type: str
-
-
-class Message(TypedDict, total=False):
- content: Required[Iterable[MessageContent]]
- """Message content as an array of parts."""
-
- role: Required[str]
- """Message role (system, user, assistant)"""
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
deleted file mode 100644
index 5cac9e3..0000000
--- a/src/docstrange/types/classify_batch_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ClassifyBatchParams"]
-
-
-class ClassifyBatchParams(TypedDict, total=False):
- categories: Required[str]
- """JSON array of category objects (max 50 categories)"""
-
- files: Required[SequenceNotStr[FileTypes]]
- """Files to classify (max 50)"""
diff --git a/src/docstrange/types/classify_response.py b/src/docstrange/types/classify_response.py
index fdebbb0..5bab3de 100644
--- a/src/docstrange/types/classify_response.py
+++ b/src/docstrange/types/classify_response.py
@@ -1,9 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
-
from .._models import BaseModel
-from .file_classification_result import FileClassificationResult
__all__ = ["ClassifyResponse"]
@@ -12,5 +9,3 @@ class ClassifyResponse(BaseModel):
message: str
success: bool
-
- result: Optional[FileClassificationResult] = None
diff --git a/src/docstrange/types/classify_sync_params.py b/src/docstrange/types/classify_sync_params.py
index 772427d..ff11627 100644
--- a/src/docstrange/types/classify_sync_params.py
+++ b/src/docstrange/types/classify_sync_params.py
@@ -11,10 +11,7 @@
class ClassifySyncParams(TypedDict, total=False):
categories: Required[str]
- """
- JSON array of category objects: [{"name": "Category Name", "description":
- "Optional description"}]
- """
+ """JSON array of categories"""
file: Required[FileTypes]
- """File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)"""
+ """File to classify"""
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
index 387a007..f8ee8b1 100644
--- a/src/docstrange/types/extract/__init__.py
+++ b/src/docstrange/types/extract/__init__.py
@@ -1,8 +1,3 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from __future__ import annotations
-
-from .pagination_info import PaginationInfo as PaginationInfo
-from .result_list_params import ResultListParams as ResultListParams
-from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
-from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
deleted file mode 100644
index 26a12e7..0000000
--- a/src/docstrange/types/extract/extraction_list_response.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from ..._models import BaseModel
-from .pagination_info import PaginationInfo
-from ..extract_response import ExtractResponse
-
-__all__ = ["ExtractionListResponse"]
-
-
-class ExtractionListResponse(BaseModel):
- pagination: PaginationInfo
-
- results: List[ExtractResponse]
-
- success: bool
diff --git a/src/docstrange/types/extract/pagination_info.py b/src/docstrange/types/extract/pagination_info.py
deleted file mode 100644
index 7a678a9..0000000
--- a/src/docstrange/types/extract/pagination_info.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from ..._models import BaseModel
-
-__all__ = ["PaginationInfo"]
-
-
-class PaginationInfo(BaseModel):
- has_next: Optional[bool] = None
-
- has_previous: Optional[bool] = None
-
- page: Optional[int] = None
-
- page_size: Optional[int] = None
-
- total_count: Optional[int] = None
-
- total_pages: Optional[int] = None
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
deleted file mode 100644
index 7dfe38a..0000000
--- a/src/docstrange/types/extract/result_list_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypedDict
-
-__all__ = ["ResultListParams"]
-
-
-class ResultListParams(TypedDict, total=False):
- page: int
-
- page_size: int
-
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
-
- sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
deleted file mode 100644
index 539b80d..0000000
--- a/src/docstrange/types/extract/result_retrieve_params.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import TypedDict
-
-__all__ = ["ResultRetrieveParams"]
-
-
-class ResultRetrieveParams(TypedDict, total=False):
- include_content: bool
- """Include full extracted content (default: true)"""
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
deleted file mode 100644
index 364ee01..0000000
--- a/src/docstrange/types/extract_async_params.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractAsyncParams"]
-
-
-class ExtractAsyncParams(TypedDict, total=False):
- file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
- output_format: Required[str]
- """Output format(s): `markdown`, `html`, `json`, `csv`.
-
- Comma-separate for multiple (e.g., `markdown,json`).
- """
-
- csv_options: str
- """CSV extraction options (e.g., `table`)"""
-
- custom_instructions: str
- """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
-
- json_options: str
- """JSON extraction options."""
-
- prompt_mode: Literal["append", "replace"]
- """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
deleted file mode 100644
index bdc7b29..0000000
--- a/src/docstrange/types/extract_batch_params.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ExtractBatchParams"]
-
-
-class ExtractBatchParams(TypedDict, total=False):
- files: Required[SequenceNotStr[FileTypes]]
- """Files to process (max 50)"""
-
- output_format: Required[str]
- """Output format(s) for all files"""
-
- csv_options: str
-
- custom_instructions: str
-
- include_metadata: str
-
- json_options: str
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_response.py b/src/docstrange/types/extract_response.py
index 9d93ead..ba021e0 100644
--- a/src/docstrange/types/extract_response.py
+++ b/src/docstrange/types/extract_response.py
@@ -1,38 +1,17 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
-from datetime import datetime
-from typing_extensions import Literal
from .._models import BaseModel
-from .extraction_result import ExtractionResult
__all__ = ["ExtractResponse"]
class ExtractResponse(BaseModel):
- message: str
-
record_id: str
- """Job ID for retrieving results"""
- status: Literal["completed", "processing", "failed"]
+ status: str
success: bool
- created_at: Optional[datetime] = None
-
- file_size: Optional[int] = None
- """Size in bytes"""
-
- filename: Optional[str] = None
-
- output_format: Optional[str] = None
-
- pages_processed: Optional[int] = None
-
- processing_time: Optional[float] = None
- """Time in seconds"""
-
- result: Optional[ExtractionResult] = None
- """Results by format (only requested formats populated)"""
+ message: Optional[str] = None
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
deleted file mode 100644
index 68ee9a6..0000000
--- a/src/docstrange/types/extract_stream_params.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractStreamParams"]
-
-
-class ExtractStreamParams(TypedDict, total=False):
- file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
- output_format: Required[str]
- """Output format(s): `markdown`, `html`, `json`, `csv`.
-
- Comma-separate for multiple.
- """
-
- csv_options: str
- """CSV extraction options"""
-
- custom_instructions: str
- """Custom extraction instructions"""
-
- enable_streaming: bool
- """Enable real-time streaming."""
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
-
- json_options: str
- """JSON extraction options"""
-
- prompt_mode: Literal["append", "replace"]
- """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
deleted file mode 100644
index 333ff97..0000000
--- a/src/docstrange/types/extract_stream_response.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import TypeAlias
-
-__all__ = ["ExtractStreamResponse"]
-
-ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 78813f6..242ce95 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing_extensions import Literal, Required, TypedDict
+from typing_extensions import Required, TypedDict
from .._types import FileTypes
@@ -11,31 +11,7 @@
class ExtractSyncParams(TypedDict, total=False):
file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+ """File to upload"""
output_format: Required[str]
- """Output format(s): `markdown`, `html`, `json`, `csv`.
-
- Comma-separate for multiple (e.g., `markdown,json`).
- """
-
- csv_options: str
- """CSV extraction options (e.g., `table`)"""
-
- custom_instructions: str
- """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
-
- json_options: str
- """JSON extraction options."""
-
- prompt_mode: Literal["append", "replace"]
- """`append`: add to base prompt, `replace`: use only custom instructions"""
+ """Output format"""
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
deleted file mode 100644
index bfa97a9..0000000
--- a/src/docstrange/types/extraction_format_result.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from .._models import BaseModel
-from .extraction_metadata import ExtractionMetadata
-
-__all__ = ["ExtractionFormatResult"]
-
-
-class ExtractionFormatResult(BaseModel):
- content: object
- """Extracted content (string or object)"""
-
- metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/extraction_metadata.py b/src/docstrange/types/extraction_metadata.py
deleted file mode 100644
index 9792ba0..0000000
--- a/src/docstrange/types/extraction_metadata.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from .._models import BaseModel
-
-__all__ = ["ExtractionMetadata"]
-
-
-class ExtractionMetadata(BaseModel):
- bounding_boxes: Optional[object] = None
- """Element coordinates with page dimensions"""
-
- confidence_score: Optional[object] = None
- """Confidence scores per field"""
diff --git a/src/docstrange/types/extraction_result.py b/src/docstrange/types/extraction_result.py
deleted file mode 100644
index 57b2928..0000000
--- a/src/docstrange/types/extraction_result.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-from .extraction_format_result import ExtractionFormatResult
-
-__all__ = ["ExtractionResult"]
-
-
-class ExtractionResult(BaseModel):
- """Results by format (only requested formats populated)"""
-
- csv: Optional[ExtractionFormatResult] = None
-
- html: Optional[ExtractionFormatResult] = None
-
- json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
-
- markdown: Optional[ExtractionFormatResult] = None
diff --git a/src/docstrange/types/file_classification_result.py b/src/docstrange/types/file_classification_result.py
deleted file mode 100644
index 397d924..0000000
--- a/src/docstrange/types/file_classification_result.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from .._models import BaseModel
-from .page_classification import PageClassification
-
-__all__ = ["FileClassificationResult"]
-
-
-class FileClassificationResult(BaseModel):
- filename: str
-
- pages: List[PageClassification]
-
- total_pages: int
-
- error: Optional[str] = None
-
- processing_time: Optional[float] = None
- """Time in seconds"""
-
- record_id: Optional[str] = None
- """Record ID for polling results"""
diff --git a/src/docstrange/types/page_classification.py b/src/docstrange/types/page_classification.py
deleted file mode 100644
index 62a2338..0000000
--- a/src/docstrange/types/page_classification.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from .._models import BaseModel
-
-__all__ = ["PageClassification"]
-
-
-class PageClassification(BaseModel):
- category: str
- """Matched category name or 'Other' if no match"""
-
- confidence: int
- """Confidence score (0-100)"""
-
- page_number: int
-
- reasoning: str
- """Explanation for the classification"""
-
- identified_category: Optional[str] = None
- """Specific document type identified by the model."""
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
deleted file mode 100644
index ee1d5f5..0000000
--- a/tests/api_resources/extract/test_results.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
-from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestResults:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_retrieve(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_retrieve(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_retrieve(self, client: Docstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list(self, client: Docstrange) -> None:
- result = client.extract.results.list()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncResults:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- await async_client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
deleted file mode 100644
index 84bfced..0000000
--- a/tests/api_resources/test_chat.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestChat:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "type",
- }
- ],
- "role": "role",
- }
- ],
- model="model",
- stream=True,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_create_completion(self, client: Docstrange) -> None:
- response = client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_create_completion(self, client: Docstrange) -> None:
- with client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncChat:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "type",
- }
- ],
- "role": "role",
- }
- ],
- model="model",
- stream=True,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- async with async_client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index d40e1fa..63539df 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse, BatchClassifyResponse
+from docstrange.types import ClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,43 +17,6 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- classify = client.classify.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.classify.with_raw_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.classify.with_streaming_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -97,43 +60,6 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- classify = await async_client.classify.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.classify.with_raw_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.classify.with_streaming_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index 4f68b18..d8117c2 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,10 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import (
- ExtractResponse,
- BatchExtractResponse,
-)
+from docstrange.types import ExtractResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -20,163 +17,6 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- file=b"raw file contents",
- output_format="output_format",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- file=b"raw file contents",
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- file_base64="file_base64",
- file_url="file_url",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_async(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.async_(
- file=b"raw file contents",
- output_format="output_format",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_async(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.async_(
- file=b"raw file contents",
- output_format="output_format",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- file=b"raw file contents",
- output_format="output_format",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream_with_all_params(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- file=b"raw file contents",
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- enable_streaming=True,
- file_base64="file_base64",
- file_url="file_url",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_raw_response_stream(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.stream(
- file=b"raw file contents",
- output_format="output_format",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = response.parse()
- stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_streaming_response_stream(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.stream(
- file=b"raw file contents",
- output_format="output_format",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = response.parse()
- stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -186,22 +26,6 @@ def test_method_sync(self, client: Docstrange) -> None:
)
assert_matches_type(ExtractResponse, extract, path=["response"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_sync_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.sync(
- file=b"raw file contents",
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- file_base64="file_base64",
- file_url="file_url",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
@@ -236,163 +60,6 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- file=b"raw file contents",
- output_format="output_format",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- file=b"raw file contents",
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- file_base64="file_base64",
- file_url="file_url",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.async_(
- file=b"raw file contents",
- output_format="output_format",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.async_(
- file=b"raw file contents",
- output_format="output_format",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="output_format",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- file=b"raw file contents",
- output_format="output_format",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- file=b"raw file contents",
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- enable_streaming=True,
- file_base64="file_base64",
- file_url="file_url",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.stream(
- file=b"raw file contents",
- output_format="output_format",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = await response.parse()
- await stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.stream(
- file=b"raw file contents",
- output_format="output_format",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = await response.parse()
- await stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
@@ -402,22 +69,6 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
)
assert_matches_type(ExtractResponse, extract, path=["response"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.sync(
- file=b"raw file contents",
- output_format="output_format",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- file_base64="file_base64",
- file_url="file_url",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
From cee4e51ef55edee2402626eeb04dfe74f41c4676 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:22:41 +0000
Subject: [PATCH 18/26] feat(api): api update
---
.stats.yml | 6 +-
README.md | 2 +-
api.md | 2 +-
src/docstrange/_client.py | 2 +-
src/docstrange/pagination.py | 67 ---------------
src/docstrange/resources/classify.py | 4 +-
.../resources/{extract => }/extract.py | 81 ++++++++++++++++---
src/docstrange/resources/extract/__init__.py | 19 -----
src/docstrange/types/classify_sync_params.py | 2 +-
src/docstrange/types/extract/__init__.py | 3 -
src/docstrange/types/extract_sync_params.py | 27 ++++++-
tests/api_resources/extract/__init__.py | 1 -
tests/api_resources/test_extract.py | 44 ++++++++--
tests/test_client.py | 24 +++---
14 files changed, 150 insertions(+), 134 deletions(-)
delete mode 100644 src/docstrange/pagination.py
rename src/docstrange/resources/{extract => }/extract.py (70%)
delete mode 100644 src/docstrange/resources/extract/__init__.py
delete mode 100644 src/docstrange/types/extract/__init__.py
delete mode 100644 tests/api_resources/extract/__init__.py
diff --git a/.stats.yml b/.stats.yml
index 1d97927..457a2a7 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 2
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-3843cc83cc328a1c86126018a4309fbcd13aac4df5fd9afefd652e21e59530ab.yml
-openapi_spec_hash: b4046d95714426b15edb8ac003f904c6
-config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-eed2d21f54dac82f72faa7f05408973593e5a6338717864d4f37bf2333274518.yml
+openapi_spec_hash: 47cb78aa2caa018fe58742fc19b0a49c
+config_hash: 6f0ab1fd6c4433590ee82d88ab5298a7
diff --git a/README.md b/README.md
index 622faec..74c6d8b 100644
--- a/README.md
+++ b/README.md
@@ -127,7 +127,7 @@ client = Docstrange()
client.extract.sync(
file=Path("/path/to/file"),
- output_format="output_format",
+ output_format="markdown",
)
```
diff --git a/api.md b/api.md
index 90358a6..0cac7c9 100644
--- a/api.md
+++ b/api.md
@@ -8,7 +8,7 @@ from docstrange.types import ExtractResponse
Methods:
-- client.extract.sync(\*\*params) -> ExtractResponse
+- client.extract.sync(\*\*params) -> ExtractResponse
# Classify
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 271a014..42d282d 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -32,8 +32,8 @@
if TYPE_CHECKING:
from .resources import extract, classify
+ from .resources.extract import ExtractResource, AsyncExtractResource
from .resources.classify import ClassifyResource, AsyncClassifyResource
- from .resources.extract.extract import ExtractResource, AsyncExtractResource
__all__ = [
"Timeout",
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
deleted file mode 100644
index e926095..0000000
--- a/src/docstrange/pagination.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Generic, TypeVar, Optional, cast
-from typing_extensions import override
-
-from ._models import BaseModel
-from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
-
-__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
-
-_T = TypeVar("_T")
-
-
-class PageNumberPaginationPagination(BaseModel):
- has_next: Optional[bool] = None
-
- total_count: Optional[int] = None
-
-
-class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
- results: List[_T]
- pagination: Optional[PageNumberPaginationPagination] = None
-
- @override
- def _get_page_items(self) -> List[_T]:
- results = self.results
- if not results:
- return []
- return results
-
- @override
- def next_page_info(self) -> Optional[PageInfo]:
- last_page = cast("int | None", self._options.params.get("page")) or 1
-
- total_pages = None
- if self.pagination is not None:
- if self.pagination.total_count is not None:
- total_pages = self.pagination.total_count
- if total_pages is not None and last_page >= total_pages:
- return None
-
- return PageInfo(params={"page": last_page + 1})
-
-
-class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
- results: List[_T]
- pagination: Optional[PageNumberPaginationPagination] = None
-
- @override
- def _get_page_items(self) -> List[_T]:
- results = self.results
- if not results:
- return []
- return results
-
- @override
- def next_page_info(self) -> Optional[PageInfo]:
- last_page = cast("int | None", self._options.params.get("page")) or 1
-
- total_pages = None
- if self.pagination is not None:
- if self.pagination.total_count is not None:
- total_pages = self.pagination.total_count
- if total_pages is not None and last_page >= total_pages:
- return None
-
- return PageInfo(params={"page": last_page + 1})
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index 69045f4..d7853b4 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -59,7 +59,7 @@ def sync(
Classify a single document.
Args:
- categories: JSON array of categories
+ categories: JSON array of category objects
file: File to classify
@@ -129,7 +129,7 @@ async def sync(
Classify a single document.
Args:
- categories: JSON array of categories
+ categories: JSON array of category objects
file: File to classify
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract.py
similarity index 70%
rename from src/docstrange/resources/extract/extract.py
rename to src/docstrange/resources/extract.py
index 0fe0d14..5b896e5 100644
--- a/src/docstrange/resources/extract/extract.py
+++ b/src/docstrange/resources/extract.py
@@ -3,22 +3,23 @@
from __future__ import annotations
from typing import Mapping, cast
+from typing_extensions import Literal
import httpx
-from ...types import extract_sync_params
-from ..._types import Body, Query, Headers, NotGiven, FileTypes, not_given
-from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
+from ..types import extract_sync_params
+from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ..._base_client import make_request_options
-from ...types.extract_response import ExtractResponse
+from .._base_client import make_request_options
+from ..types.extract_response import ExtractResponse
__all__ = ["ExtractResource", "AsyncExtractResource"]
@@ -48,6 +49,13 @@ def sync(
*,
file: FileTypes,
output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -59,9 +67,23 @@ def sync(
Process a document and return extracted content immediately.
Args:
- file: File to upload
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
- output_format: Output format
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ prompt_mode: append or replace
extra_headers: Send extra headers
@@ -75,6 +97,13 @@ def sync(
{
"file": file,
"output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
}
)
files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
@@ -118,6 +147,13 @@ async def sync(
*,
file: FileTypes,
output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -129,9 +165,23 @@ async def sync(
Process a document and return extracted content immediately.
Args:
- file: File to upload
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
- output_format: Output format
+ prompt_mode: append or replace
extra_headers: Send extra headers
@@ -145,6 +195,13 @@ async def sync(
{
"file": file,
"output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
}
)
files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
deleted file mode 100644
index a0fee27..0000000
--- a/src/docstrange/resources/extract/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .extract import (
- ExtractResource,
- AsyncExtractResource,
- ExtractResourceWithRawResponse,
- AsyncExtractResourceWithRawResponse,
- ExtractResourceWithStreamingResponse,
- AsyncExtractResourceWithStreamingResponse,
-)
-
-__all__ = [
- "ExtractResource",
- "AsyncExtractResource",
- "ExtractResourceWithRawResponse",
- "AsyncExtractResourceWithRawResponse",
- "ExtractResourceWithStreamingResponse",
- "AsyncExtractResourceWithStreamingResponse",
-]
diff --git a/src/docstrange/types/classify_sync_params.py b/src/docstrange/types/classify_sync_params.py
index ff11627..d0b3e16 100644
--- a/src/docstrange/types/classify_sync_params.py
+++ b/src/docstrange/types/classify_sync_params.py
@@ -11,7 +11,7 @@
class ClassifySyncParams(TypedDict, total=False):
categories: Required[str]
- """JSON array of categories"""
+ """JSON array of category objects"""
file: Required[FileTypes]
"""File to classify"""
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
deleted file mode 100644
index f8ee8b1..0000000
--- a/src/docstrange/types/extract/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 242ce95..1f032ea 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing_extensions import Required, TypedDict
+from typing_extensions import Literal, Required, TypedDict
from .._types import FileTypes
@@ -11,7 +11,28 @@
class ExtractSyncParams(TypedDict, total=False):
file: Required[FileTypes]
- """File to upload"""
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
output_format: Required[str]
- """Output format"""
+ """Output format(s): markdown, html, json, csv."""
+
+ csv_options: str
+ """CSV extraction options"""
+
+ custom_instructions: str
+ """Custom extraction instructions"""
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata types"""
+
+ json_options: str
+ """JSON extraction options"""
+
+ prompt_mode: Literal["append", "replace"]
+ """append or replace"""
diff --git a/tests/api_resources/extract/__init__.py b/tests/api_resources/extract/__init__.py
deleted file mode 100644
index fd8019a..0000000
--- a/tests/api_resources/extract/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index d8117c2..d911970 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -22,7 +22,23 @@ class TestExtract:
def test_method_sync(self, client: Docstrange) -> None:
extract = client.extract.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_sync_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.sync(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -31,7 +47,7 @@ def test_method_sync(self, client: Docstrange) -> None:
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
)
assert response.is_closed is True
@@ -44,7 +60,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -65,7 +81,23 @@ class TestAsyncExtract:
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.sync(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -74,7 +106,7 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
)
assert response.is_closed is True
@@ -87,7 +119,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.sync(
file=b"raw file contents",
- output_format="output_format",
+ output_format="markdown",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/test_client.py b/tests/test_client.py
index 2756693..719c826 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -862,9 +862,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
- ).__enter__()
+ client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@@ -874,9 +872,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
- ).__enter__()
+ client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -905,7 +901,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
+ response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -930,7 +926,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -955,7 +951,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1773,7 +1769,7 @@ async def test_retrying_timeout_errors_doesnt_leak(
with pytest.raises(APITimeoutError):
await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
+ file=b"raw file contents", output_format="markdown"
).__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1787,7 +1783,7 @@ async def test_retrying_status_errors_doesnt_leak(
with pytest.raises(APIStatusError):
await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="output_format"
+ file=b"raw file contents", output_format="markdown"
).__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1817,7 +1813,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="output_format")
+ response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1842,7 +1838,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": Omit()}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -1867,7 +1863,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="output_format", extra_headers={"x-stainless-retry-count": "42"}
+ file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
From 0cb48631aa0c08788f26a3abb051fef2c12aaa20 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:25:29 +0000
Subject: [PATCH 19/26] feat(api): api update
---
.stats.yml | 8 +-
README.md | 61 ++
api.md | 52 +-
src/docstrange/_client.py | 41 +-
src/docstrange/pagination.py | 67 ++
src/docstrange/resources/__init__.py | 14 +
src/docstrange/resources/chat.py | 182 +++++
src/docstrange/resources/classify.py | 147 +++-
src/docstrange/resources/extract.py | 256 -------
src/docstrange/resources/extract/__init__.py | 33 +
src/docstrange/resources/extract/extract.py | 724 ++++++++++++++++++
src/docstrange/resources/extract/results.py | 290 +++++++
src/docstrange/types/__init__.py | 13 +
.../types/batch_classify_response.py | 24 +
.../types/batch_extract_response.py | 24 +
.../types/chat_create_completion_params.py | 40 +
src/docstrange/types/classify_batch_params.py | 17 +
src/docstrange/types/classify_response.py | 5 +
src/docstrange/types/extract/__init__.py | 8 +
.../types/extract/extraction_list_response.py | 17 +
.../types/extract/pagination_info.py | 21 +
.../types/extract/result_list_params.py | 17 +
.../types/extract/result_retrieve_params.py | 11 +
src/docstrange/types/extract_async_params.py | 37 +
src/docstrange/types/extract_batch_params.py | 26 +
src/docstrange/types/extract_response.py | 21 +-
src/docstrange/types/extract_stream_params.py | 35 +
.../types/extract_stream_response.py | 7 +
src/docstrange/types/extract_sync_params.py | 1 -
.../types/extraction_format_result.py | 15 +
src/docstrange/types/extraction_metadata.py | 13 +
src/docstrange/types/extraction_result.py | 20 +
.../types/file_classification_result.py | 22 +
src/docstrange/types/page_classification.py | 19 +
tests/api_resources/extract/__init__.py | 1 +
tests/api_resources/extract/test_results.py | 205 +++++
tests/api_resources/test_chat.py | 171 +++++
tests/api_resources/test_classify.py | 76 +-
tests/api_resources/test_extract.py | 319 +++++++-
39 files changed, 2767 insertions(+), 293 deletions(-)
create mode 100644 src/docstrange/pagination.py
create mode 100644 src/docstrange/resources/chat.py
delete mode 100644 src/docstrange/resources/extract.py
create mode 100644 src/docstrange/resources/extract/__init__.py
create mode 100644 src/docstrange/resources/extract/extract.py
create mode 100644 src/docstrange/resources/extract/results.py
create mode 100644 src/docstrange/types/batch_classify_response.py
create mode 100644 src/docstrange/types/batch_extract_response.py
create mode 100644 src/docstrange/types/chat_create_completion_params.py
create mode 100644 src/docstrange/types/classify_batch_params.py
create mode 100644 src/docstrange/types/extract/__init__.py
create mode 100644 src/docstrange/types/extract/extraction_list_response.py
create mode 100644 src/docstrange/types/extract/pagination_info.py
create mode 100644 src/docstrange/types/extract/result_list_params.py
create mode 100644 src/docstrange/types/extract/result_retrieve_params.py
create mode 100644 src/docstrange/types/extract_async_params.py
create mode 100644 src/docstrange/types/extract_batch_params.py
create mode 100644 src/docstrange/types/extract_stream_params.py
create mode 100644 src/docstrange/types/extract_stream_response.py
create mode 100644 src/docstrange/types/extraction_format_result.py
create mode 100644 src/docstrange/types/extraction_metadata.py
create mode 100644 src/docstrange/types/extraction_result.py
create mode 100644 src/docstrange/types/file_classification_result.py
create mode 100644 src/docstrange/types/page_classification.py
create mode 100644 tests/api_resources/extract/__init__.py
create mode 100644 tests/api_resources/extract/test_results.py
create mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index 457a2a7..031d39f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 2
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-eed2d21f54dac82f72faa7f05408973593e5a6338717864d4f37bf2333274518.yml
-openapi_spec_hash: 47cb78aa2caa018fe58742fc19b0a49c
-config_hash: 6f0ab1fd6c4433590ee82d88ab5298a7
+configured_endpoints: 9
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-4dc8746b7c32d8b0ed281e28dc83a6af06e280f87a173d4535a6e7e0db5d1fe6.yml
+openapi_spec_hash: c6154bc9b0c0f3611223180cc335673b
+config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
diff --git a/README.md b/README.md
index 74c6d8b..991dcba 100644
--- a/README.md
+++ b/README.md
@@ -115,6 +115,67 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
+## Pagination
+
+List methods in the Docstrange API are paginated.
+
+This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
+
+```python
+from docstrange import Docstrange
+
+client = Docstrange()
+
+all_results = []
+# Automatically fetches more pages as needed.
+for result in client.extract.results.list():
+ # Do something with result here
+ all_results.append(result)
+print(all_results)
+```
+
+Or, asynchronously:
+
+```python
+import asyncio
+from docstrange import AsyncDocstrange
+
+client = AsyncDocstrange()
+
+
+async def main() -> None:
+ all_results = []
+ # Iterate through items across all pages, issuing requests as needed.
+ async for result in client.extract.results.list():
+ all_results.append(result)
+ print(all_results)
+
+
+asyncio.run(main())
+```
+
+Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
+
+```python
+first_page = await client.extract.results.list()
+if first_page.has_next_page():
+ print(f"will fetch next page using these details: {first_page.next_page_info()}")
+ next_page = await first_page.get_next_page()
+ print(f"number of items we just fetched: {len(next_page.results)}")
+
+# Remove `await` for non-async usage.
+```
+
+Or just work directly with the returned data:
+
+```python
+first_page = await client.extract.results.list()
+for result in first_page.results:
+ print(result.record_id)
+
+# Remove `await` for non-async usage.
+```
+
## File uploads
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)`.
diff --git a/api.md b/api.md
index 0cac7c9..7ccbce8 100644
--- a/api.md
+++ b/api.md
@@ -3,21 +3,67 @@
Types:
```python
-from docstrange.types import ExtractResponse
+from docstrange.types import (
+ BatchExtractRequestBody,
+ BatchExtractResponse,
+ ExtractRequestBody,
+ ExtractResponse,
+ ExtractionFormatResult,
+ ExtractionMetadata,
+ ExtractionResult,
+ StreamExtractRequestBody,
+ ExtractStreamResponse,
+)
```
Methods:
-- client.extract.sync(\*\*params) -> ExtractResponse
+- client.extract.async\_(\*\*params) -> ExtractResponse
+- client.extract.batch(\*\*params) -> BatchExtractResponse
+- client.extract.stream(\*\*params) -> str
+- client.extract.sync(\*\*params) -> ExtractResponse
+
+## Results
+
+Types:
+
+```python
+from docstrange.types.extract import ExtractionListResponse, PaginationInfo
+```
+
+Methods:
+
+- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
+- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[ExtractResponse]
# Classify
Types:
```python
-from docstrange.types import ClassifyResponse
+from docstrange.types import (
+ BatchClassifyRequestBody,
+ BatchClassifyResponse,
+ ClassifyRequestBody,
+ ClassifyResponse,
+ FileClassificationResult,
+ PageClassification,
+)
```
Methods:
+- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
+
+# Chat
+
+Types:
+
+```python
+from docstrange.types import ChatCompletionsRequest
+```
+
+Methods:
+
+- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 42d282d..4c5bcc4 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,9 +31,10 @@
)
if TYPE_CHECKING:
- from .resources import extract, classify
- from .resources.extract import ExtractResource, AsyncExtractResource
+ from .resources import chat, extract, classify
+ from .resources.chat import ChatResource, AsyncChatResource
from .resources.classify import ClassifyResource, AsyncClassifyResource
+ from .resources.extract.extract import ExtractResource, AsyncExtractResource
__all__ = [
"Timeout",
@@ -114,6 +115,12 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
+ @cached_property
+ def chat(self) -> ChatResource:
+ from .resources.chat import ChatResource
+
+ return ChatResource(self)
+
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -294,6 +301,12 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
+ @cached_property
+ def chat(self) -> AsyncChatResource:
+ from .resources.chat import AsyncChatResource
+
+ return AsyncChatResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -425,6 +438,12 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithRawResponse:
+ from .resources.chat import ChatResourceWithRawResponse
+
+ return ChatResourceWithRawResponse(self._client.chat)
+
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -444,6 +463,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithRawResponse:
+ from .resources.chat import AsyncChatResourceWithRawResponse
+
+ return AsyncChatResourceWithRawResponse(self._client.chat)
+
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -463,6 +488,12 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithStreamingResponse:
+ from .resources.chat import ChatResourceWithStreamingResponse
+
+ return ChatResourceWithStreamingResponse(self._client.chat)
+
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -482,6 +513,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
+ from .resources.chat import AsyncChatResourceWithStreamingResponse
+
+ return AsyncChatResourceWithStreamingResponse(self._client.chat)
+
Client = Docstrange
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
new file mode 100644
index 0000000..e926095
--- /dev/null
+++ b/src/docstrange/pagination.py
@@ -0,0 +1,67 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Generic, TypeVar, Optional, cast
+from typing_extensions import override
+
+from ._models import BaseModel
+from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
+
+__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
+
+_T = TypeVar("_T")
+
+
+class PageNumberPaginationPagination(BaseModel):
+ has_next: Optional[bool] = None
+
+ total_count: Optional[int] = None
+
+
+class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ results = self.results
+ if not results:
+ return []
+ return results
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
+ return PageInfo(params={"page": last_page + 1})
+
+
+class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ results = self.results
+ if not results:
+ return []
+ return results
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
+ return PageInfo(params={"page": last_page + 1})
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index 6d7ff55..a3172dd 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,5 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .chat import (
+ ChatResource,
+ AsyncChatResource,
+ ChatResourceWithRawResponse,
+ AsyncChatResourceWithRawResponse,
+ ChatResourceWithStreamingResponse,
+ AsyncChatResourceWithStreamingResponse,
+)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -30,4 +38,10 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
+ "ChatResource",
+ "AsyncChatResource",
+ "ChatResourceWithRawResponse",
+ "AsyncChatResourceWithRawResponse",
+ "ChatResourceWithStreamingResponse",
+ "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
new file mode 100644
index 0000000..7e8899d
--- /dev/null
+++ b/src/docstrange/resources/chat.py
@@ -0,0 +1,182 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+
+import httpx
+
+from ..types import chat_create_completion_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+
+__all__ = ["ChatResource", "AsyncChatResource"]
+
+
+class ChatResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ChatResourceWithStreamingResponse(self)
+
+ def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """
+ OpenAI-compatible chat completions endpoint.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._post(
+ "/v1/chat/completions",
+ body=maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class AsyncChatResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncChatResourceWithStreamingResponse(self)
+
+ async def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """
+ OpenAI-compatible chat completions endpoint.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._post(
+ "/v1/chat/completions",
+ body=await async_maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class ChatResourceWithRawResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithRawResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class ChatResourceWithStreamingResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_streamed_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithStreamingResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_streamed_response_wrapper(
+ chat.create_completion,
+ )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index d7853b4..ded77af 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,13 +2,11 @@
from __future__ import annotations
-from typing import Mapping, cast
-
import httpx
-from ..types import classify_sync_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from ..types import classify_sync_params, classify_batch_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -19,6 +17,7 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
+from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -43,6 +42,53 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
+ def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50).
+
+ Args:
+ categories: JSON array of category objects
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/classify/batch",
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
def sync(
self,
*,
@@ -71,21 +117,19 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -113,6 +157,53 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
+ async def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50).
+
+ Args:
+ categories: JSON array of category objects
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/classify/batch",
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
async def sync(
self,
*,
@@ -141,21 +232,19 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -167,6 +256,9 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -176,6 +268,9 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -185,6 +280,9 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -194,6 +292,9 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract.py b/src/docstrange/resources/extract.py
deleted file mode 100644
index 5b896e5..0000000
--- a/src/docstrange/resources/extract.py
+++ /dev/null
@@ -1,256 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Mapping, cast
-from typing_extensions import Literal
-
-import httpx
-
-from ..types import extract_sync_params
-from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-from ..types.extract_response import ExtractResponse
-
-__all__ = ["ExtractResource", "AsyncExtractResource"]
-
-
-class ExtractResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ExtractResourceWithStreamingResponse(self)
-
- def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- prompt_mode: append or replace
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- body = deepcopy_minimal(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/sync",
- body=maybe_transform(body, extract_sync_params.ExtractSyncParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class AsyncExtractResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncExtractResourceWithStreamingResponse(self)
-
- async def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- prompt_mode: append or replace
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- body = deepcopy_minimal(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/sync",
- body=await async_maybe_transform(body, extract_sync_params.ExtractSyncParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class ExtractResourceWithRawResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.sync = to_raw_response_wrapper(
- extract.sync,
- )
-
-
-class AsyncExtractResourceWithRawResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.sync = async_to_raw_response_wrapper(
- extract.sync,
- )
-
-
-class ExtractResourceWithStreamingResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.sync = to_streamed_response_wrapper(
- extract.sync,
- )
-
-
-class AsyncExtractResourceWithStreamingResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.sync = async_to_streamed_response_wrapper(
- extract.sync,
- )
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
new file mode 100644
index 0000000..22cd257
--- /dev/null
+++ b/src/docstrange/resources/extract/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .extract import (
+ ExtractResource,
+ AsyncExtractResource,
+ ExtractResourceWithRawResponse,
+ AsyncExtractResourceWithRawResponse,
+ ExtractResourceWithStreamingResponse,
+ AsyncExtractResourceWithStreamingResponse,
+)
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ResultsResource",
+ "AsyncResultsResource",
+ "ResultsResourceWithRawResponse",
+ "AsyncResultsResourceWithRawResponse",
+ "ResultsResourceWithStreamingResponse",
+ "AsyncResultsResourceWithStreamingResponse",
+ "ExtractResource",
+ "AsyncExtractResource",
+ "ExtractResourceWithRawResponse",
+ "AsyncExtractResourceWithRawResponse",
+ "ExtractResourceWithStreamingResponse",
+ "AsyncExtractResourceWithStreamingResponse",
+]
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
new file mode 100644
index 0000000..335f013
--- /dev/null
+++ b/src/docstrange/resources/extract/extract.py
@@ -0,0 +1,724 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
+from ..._types import (
+ Body,
+ Omit,
+ Query,
+ Headers,
+ NotGiven,
+ FileTypes,
+ SequenceNotStr,
+ omit,
+ not_given,
+)
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..._streaming import Stream, AsyncStream
+from ..._base_client import make_request_options
+from ...types.extract_response import ExtractResponse
+from ...types.batch_extract_response import BatchExtractResponse
+from ...types.extract_stream_response import ExtractStreamResponse
+
+__all__ = ["ExtractResource", "AsyncExtractResource"]
+
+
+class ExtractResource(SyncAPIResource):
+ @cached_property
+ def results(self) -> ResultsResource:
+ return ResultsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> ExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ExtractResourceWithStreamingResponse(self)
+
+ def async_(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Queue a document for background processing.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/async",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_async_params.ExtractAsyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """
+ Process multiple files asynchronously (max 50).
+
+ Args:
+ files: Files to process (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/batch",
+ body=maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ def stream(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> Stream[ExtractStreamResponse]:
+ """
+ Stream extraction results via SSE.
+
+ Args:
+ file: File to upload
+
+ output_format: Output format(s)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/stream",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=str,
+ stream=True,
+ stream_cls=Stream[ExtractStreamResponse],
+ )
+
+ def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/sync",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_sync_params.ExtractSyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class AsyncExtractResource(AsyncAPIResource):
+ @cached_property
+ def results(self) -> AsyncResultsResource:
+ return AsyncResultsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncExtractResourceWithStreamingResponse(self)
+
+ async def async_(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Queue a document for background processing.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/async",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_async_params.ExtractAsyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ async def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """
+ Process multiple files asynchronously (max 50).
+
+ Args:
+ files: Files to process (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/batch",
+ body=await async_maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ async def stream(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncStream[ExtractStreamResponse]:
+ """
+ Stream extraction results via SSE.
+
+ Args:
+ file: File to upload
+
+ output_format: Output format(s)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/stream",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=str,
+ stream=True,
+ stream_cls=AsyncStream[ExtractStreamResponse],
+ )
+
+ async def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/sync",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_sync_params.ExtractSyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class ExtractResourceWithRawResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_raw_response_wrapper(
+ extract.stream,
+ )
+ self.sync = to_raw_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> ResultsResourceWithRawResponse:
+ return ResultsResourceWithRawResponse(self._extract.results)
+
+
+class AsyncExtractResourceWithRawResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = async_to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_raw_response_wrapper(
+ extract.stream,
+ )
+ self.sync = async_to_raw_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithRawResponse:
+ return AsyncResultsResourceWithRawResponse(self._extract.results)
+
+
+class ExtractResourceWithStreamingResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_streamed_response_wrapper(
+ extract.stream,
+ )
+ self.sync = to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> ResultsResourceWithStreamingResponse:
+ return ResultsResourceWithStreamingResponse(self._extract.results)
+
+
+class AsyncExtractResourceWithStreamingResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = async_to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_streamed_response_wrapper(
+ extract.stream,
+ )
+ self.sync = async_to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithStreamingResponse:
+ return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
new file mode 100644
index 0000000..bf20529
--- /dev/null
+++ b/src/docstrange/resources/extract/results.py
@@ -0,0 +1,290 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+from ..._base_client import AsyncPaginator, make_request_options
+from ...types.extract import result_list_params, result_retrieve_params
+from ...types.extract_response import ExtractResponse
+
+__all__ = ["ResultsResource", "AsyncResultsResource"]
+
+
+class ResultsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ResultsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> SyncPageNumberPagination[ExtractResponse]:
+ """
+ List all extraction jobs (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=SyncPageNumberPagination[ExtractResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=ExtractResponse,
+ )
+
+
+class AsyncResultsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncResultsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return await self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncPaginator[ExtractResponse, AsyncPageNumberPagination[ExtractResponse]]:
+ """
+ List all extraction jobs (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=AsyncPageNumberPagination[ExtractResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=ExtractResponse,
+ )
+
+
+class ResultsResourceWithRawResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithRawResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class ResultsResourceWithStreamingResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithStreamingResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ results.list,
+ )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index fac3955..a18a10a 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -4,5 +4,18 @@
from .extract_response import ExtractResponse as ExtractResponse
from .classify_response import ClassifyResponse as ClassifyResponse
+from .extraction_result import ExtractionResult as ExtractionResult
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
+from .extraction_metadata import ExtractionMetadata as ExtractionMetadata
+from .page_classification import PageClassification as PageClassification
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
+from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
+from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
+from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
+from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
+from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
+from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
+from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
+from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
+from .file_classification_result import FileClassificationResult as FileClassificationResult
+from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
new file mode 100644
index 0000000..a36e5a8
--- /dev/null
+++ b/src/docstrange/types/batch_classify_response.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .file_classification_result import FileClassificationResult
+
+__all__ = ["BatchClassifyResponse"]
+
+
+class BatchClassifyResponse(BaseModel):
+ batch_id: str
+
+ failed_files: int
+
+ message: str
+
+ results: List[FileClassificationResult]
+
+ success: bool
+
+ successful_files: int
+
+ total_files: int
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
new file mode 100644
index 0000000..4e73773
--- /dev/null
+++ b/src/docstrange/types/batch_extract_response.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .extract_response import ExtractResponse
+
+__all__ = ["BatchExtractResponse"]
+
+
+class BatchExtractResponse(BaseModel):
+ accepted_files: int
+
+ batch_id: str
+
+ message: str
+
+ records: List[ExtractResponse]
+
+ rejected_files: int
+
+ success: bool
+
+ total_files: int
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
new file mode 100644
index 0000000..eea9be6
--- /dev/null
+++ b/src/docstrange/types/chat_create_completion_params.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
+
+
+class ChatCreateCompletionParams(TypedDict, total=False):
+ messages: Required[Iterable[Message]]
+
+ model: Required[str]
+
+ stream: bool
+
+
+class MessageContentFileURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContentImageURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContent(TypedDict, total=False):
+ file_url: MessageContentFileURL
+
+ image_url: MessageContentImageURL
+
+ text: str
+
+ type: str
+
+
+class Message(TypedDict, total=False):
+ content: Required[Iterable[MessageContent]]
+
+ role: Required[str]
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
new file mode 100644
index 0000000..1f23cd0
--- /dev/null
+++ b/src/docstrange/types/classify_batch_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ClassifyBatchParams"]
+
+
+class ClassifyBatchParams(TypedDict, total=False):
+ categories: Required[str]
+ """JSON array of category objects"""
+
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to classify (max 50)"""
diff --git a/src/docstrange/types/classify_response.py b/src/docstrange/types/classify_response.py
index 5bab3de..fdebbb0 100644
--- a/src/docstrange/types/classify_response.py
+++ b/src/docstrange/types/classify_response.py
@@ -1,6 +1,9 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from typing import Optional
+
from .._models import BaseModel
+from .file_classification_result import FileClassificationResult
__all__ = ["ClassifyResponse"]
@@ -9,3 +12,5 @@ class ClassifyResponse(BaseModel):
message: str
success: bool
+
+ result: Optional[FileClassificationResult] = None
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
new file mode 100644
index 0000000..387a007
--- /dev/null
+++ b/src/docstrange/types/extract/__init__.py
@@ -0,0 +1,8 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .pagination_info import PaginationInfo as PaginationInfo
+from .result_list_params import ResultListParams as ResultListParams
+from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
+from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
new file mode 100644
index 0000000..26a12e7
--- /dev/null
+++ b/src/docstrange/types/extract/extraction_list_response.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from .pagination_info import PaginationInfo
+from ..extract_response import ExtractResponse
+
+__all__ = ["ExtractionListResponse"]
+
+
+class ExtractionListResponse(BaseModel):
+ pagination: PaginationInfo
+
+ results: List[ExtractResponse]
+
+ success: bool
diff --git a/src/docstrange/types/extract/pagination_info.py b/src/docstrange/types/extract/pagination_info.py
new file mode 100644
index 0000000..7a678a9
--- /dev/null
+++ b/src/docstrange/types/extract/pagination_info.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["PaginationInfo"]
+
+
+class PaginationInfo(BaseModel):
+ has_next: Optional[bool] = None
+
+ has_previous: Optional[bool] = None
+
+ page: Optional[int] = None
+
+ page_size: Optional[int] = None
+
+ total_count: Optional[int] = None
+
+ total_pages: Optional[int] = None
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
new file mode 100644
index 0000000..7dfe38a
--- /dev/null
+++ b/src/docstrange/types/extract/result_list_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["ResultListParams"]
+
+
+class ResultListParams(TypedDict, total=False):
+ page: int
+
+ page_size: int
+
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+
+ sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
new file mode 100644
index 0000000..1de1a80
--- /dev/null
+++ b/src/docstrange/types/extract/result_retrieve_params.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["ResultRetrieveParams"]
+
+
+class ResultRetrieveParams(TypedDict, total=False):
+ include_content: bool
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
new file mode 100644
index 0000000..2895923
--- /dev/null
+++ b/src/docstrange/types/extract_async_params.py
@@ -0,0 +1,37 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractAsyncParams"]
+
+
+class ExtractAsyncParams(TypedDict, total=False):
+ file: Required[FileTypes]
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+
+ output_format: Required[str]
+ """Output format(s): markdown, html, json, csv."""
+
+ csv_options: str
+ """CSV extraction options"""
+
+ custom_instructions: str
+ """Custom extraction instructions"""
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata types"""
+
+ json_options: str
+ """JSON extraction options"""
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
new file mode 100644
index 0000000..380d386
--- /dev/null
+++ b/src/docstrange/types/extract_batch_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ExtractBatchParams"]
+
+
+class ExtractBatchParams(TypedDict, total=False):
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to process (max 50)"""
+
+ output_format: Required[str]
+
+ csv_options: str
+
+ custom_instructions: str
+
+ include_metadata: str
+
+ json_options: str
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_response.py b/src/docstrange/types/extract_response.py
index ba021e0..a4d3ed3 100644
--- a/src/docstrange/types/extract_response.py
+++ b/src/docstrange/types/extract_response.py
@@ -1,17 +1,34 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
+from .extraction_result import ExtractionResult
__all__ = ["ExtractResponse"]
class ExtractResponse(BaseModel):
+ message: str
+
record_id: str
- status: str
+ status: Literal["completed", "processing", "failed"]
success: bool
- message: Optional[str] = None
+ created_at: Optional[datetime] = None
+
+ file_size: Optional[int] = None
+
+ filename: Optional[str] = None
+
+ output_format: Optional[str] = None
+
+ pages_processed: Optional[int] = None
+
+ processing_time: Optional[float] = None
+
+ result: Optional[ExtractionResult] = None
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
new file mode 100644
index 0000000..52147de
--- /dev/null
+++ b/src/docstrange/types/extract_stream_params.py
@@ -0,0 +1,35 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractStreamParams"]
+
+
+class ExtractStreamParams(TypedDict, total=False):
+ file: Required[FileTypes]
+ """File to upload"""
+
+ output_format: Required[str]
+ """Output format(s)"""
+
+ csv_options: str
+
+ custom_instructions: str
+
+ enable_streaming: bool
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+
+ json_options: str
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
new file mode 100644
index 0000000..333ff97
--- /dev/null
+++ b/src/docstrange/types/extract_stream_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["ExtractStreamResponse"]
+
+ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 1f032ea..3208694 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -35,4 +35,3 @@ class ExtractSyncParams(TypedDict, total=False):
"""JSON extraction options"""
prompt_mode: Literal["append", "replace"]
- """append or replace"""
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
new file mode 100644
index 0000000..579500c
--- /dev/null
+++ b/src/docstrange/types/extraction_format_result.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union, Optional
+
+from .._models import BaseModel
+from .extraction_metadata import ExtractionMetadata
+
+__all__ = ["ExtractionFormatResult"]
+
+
+class ExtractionFormatResult(BaseModel):
+ content: Union[str, object]
+ """Extracted content"""
+
+ metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/extraction_metadata.py b/src/docstrange/types/extraction_metadata.py
new file mode 100644
index 0000000..d206781
--- /dev/null
+++ b/src/docstrange/types/extraction_metadata.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["ExtractionMetadata"]
+
+
+class ExtractionMetadata(BaseModel):
+ bounding_boxes: Optional[object] = None
+
+ confidence_score: Optional[object] = None
diff --git a/src/docstrange/types/extraction_result.py b/src/docstrange/types/extraction_result.py
new file mode 100644
index 0000000..8cd1772
--- /dev/null
+++ b/src/docstrange/types/extraction_result.py
@@ -0,0 +1,20 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+from .extraction_format_result import ExtractionFormatResult
+
+__all__ = ["ExtractionResult"]
+
+
+class ExtractionResult(BaseModel):
+ csv: Optional[ExtractionFormatResult] = None
+
+ html: Optional[ExtractionFormatResult] = None
+
+ json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
+
+ markdown: Optional[ExtractionFormatResult] = None
diff --git a/src/docstrange/types/file_classification_result.py b/src/docstrange/types/file_classification_result.py
new file mode 100644
index 0000000..3c1b290
--- /dev/null
+++ b/src/docstrange/types/file_classification_result.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+from .page_classification import PageClassification
+
+__all__ = ["FileClassificationResult"]
+
+
+class FileClassificationResult(BaseModel):
+ filename: str
+
+ pages: List[PageClassification]
+
+ total_pages: int
+
+ error: Optional[str] = None
+
+ processing_time: Optional[float] = None
+
+ record_id: Optional[str] = None
diff --git a/src/docstrange/types/page_classification.py b/src/docstrange/types/page_classification.py
new file mode 100644
index 0000000..afc73a3
--- /dev/null
+++ b/src/docstrange/types/page_classification.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["PageClassification"]
+
+
+class PageClassification(BaseModel):
+ category: str
+
+ confidence: int
+
+ page_number: int
+
+ reasoning: str
+
+ identified_category: Optional[str] = None
diff --git a/tests/api_resources/extract/__init__.py b/tests/api_resources/extract/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/extract/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
new file mode 100644
index 0000000..ee1d5f5
--- /dev/null
+++ b/tests/api_resources/extract/test_results.py
@@ -0,0 +1,205 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+from docstrange.types import ExtractResponse
+from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestResults:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Docstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Docstrange) -> None:
+ result = client.extract.results.list()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncResults:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ await async_client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
new file mode 100644
index 0000000..84bfced
--- /dev/null
+++ b/tests/api_resources/test_chat.py
@@ -0,0 +1,171 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestChat:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "type",
+ }
+ ],
+ "role": "role",
+ }
+ ],
+ model="model",
+ stream=True,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_create_completion(self, client: Docstrange) -> None:
+ response = client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_create_completion(self, client: Docstrange) -> None:
+ with client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncChat:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "type",
+ }
+ ],
+ "role": "role",
+ }
+ ],
+ model="model",
+ stream=True,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index 63539df..d40e1fa 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse
+from docstrange.types import ClassifyResponse, BatchClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,6 +17,43 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ classify = client.classify.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.classify.with_raw_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.classify.with_streaming_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -60,6 +97,43 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ classify = await async_client.classify.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.classify.with_raw_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.classify.with_streaming_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index d911970..bd13f30 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,7 +9,10 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
+from docstrange.types import (
+ ExtractResponse,
+ BatchExtractResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,6 +20,163 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_async(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_async(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream_with_all_params(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_raw_response_stream(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = response.parse()
+ stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_streaming_response_stream(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = response.parse()
+ stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -76,6 +236,163 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = await response.parse()
+ await stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = await response.parse()
+ await stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
From 55c65e11f1cbfcd60df5ec2d65c503330bc29a3c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:27:10 +0000
Subject: [PATCH 20/26] feat(api): api update
---
.stats.yml | 8 +-
README.md | 61 --
api.md | 52 +-
src/docstrange/_client.py | 41 +-
src/docstrange/pagination.py | 67 --
src/docstrange/resources/__init__.py | 14 -
src/docstrange/resources/chat.py | 182 -----
src/docstrange/resources/classify.py | 147 +---
src/docstrange/resources/extract.py | 256 +++++++
src/docstrange/resources/extract/__init__.py | 33 -
src/docstrange/resources/extract/extract.py | 724 ------------------
src/docstrange/resources/extract/results.py | 290 -------
src/docstrange/types/__init__.py | 13 -
.../types/batch_classify_response.py | 24 -
.../types/batch_extract_response.py | 24 -
.../types/chat_create_completion_params.py | 40 -
src/docstrange/types/classify_batch_params.py | 17 -
src/docstrange/types/classify_response.py | 5 -
src/docstrange/types/extract/__init__.py | 8 -
.../types/extract/extraction_list_response.py | 17 -
.../types/extract/pagination_info.py | 21 -
.../types/extract/result_list_params.py | 17 -
.../types/extract/result_retrieve_params.py | 11 -
src/docstrange/types/extract_async_params.py | 37 -
src/docstrange/types/extract_batch_params.py | 26 -
src/docstrange/types/extract_response.py | 21 +-
src/docstrange/types/extract_stream_params.py | 35 -
.../types/extract_stream_response.py | 7 -
src/docstrange/types/extract_sync_params.py | 1 +
.../types/extraction_format_result.py | 15 -
src/docstrange/types/extraction_metadata.py | 13 -
src/docstrange/types/extraction_result.py | 20 -
.../types/file_classification_result.py | 22 -
src/docstrange/types/page_classification.py | 19 -
tests/api_resources/extract/__init__.py | 1 -
tests/api_resources/extract/test_results.py | 205 -----
tests/api_resources/test_chat.py | 171 -----
tests/api_resources/test_classify.py | 76 +-
tests/api_resources/test_extract.py | 319 +-------
39 files changed, 293 insertions(+), 2767 deletions(-)
delete mode 100644 src/docstrange/pagination.py
delete mode 100644 src/docstrange/resources/chat.py
create mode 100644 src/docstrange/resources/extract.py
delete mode 100644 src/docstrange/resources/extract/__init__.py
delete mode 100644 src/docstrange/resources/extract/extract.py
delete mode 100644 src/docstrange/resources/extract/results.py
delete mode 100644 src/docstrange/types/batch_classify_response.py
delete mode 100644 src/docstrange/types/batch_extract_response.py
delete mode 100644 src/docstrange/types/chat_create_completion_params.py
delete mode 100644 src/docstrange/types/classify_batch_params.py
delete mode 100644 src/docstrange/types/extract/__init__.py
delete mode 100644 src/docstrange/types/extract/extraction_list_response.py
delete mode 100644 src/docstrange/types/extract/pagination_info.py
delete mode 100644 src/docstrange/types/extract/result_list_params.py
delete mode 100644 src/docstrange/types/extract/result_retrieve_params.py
delete mode 100644 src/docstrange/types/extract_async_params.py
delete mode 100644 src/docstrange/types/extract_batch_params.py
delete mode 100644 src/docstrange/types/extract_stream_params.py
delete mode 100644 src/docstrange/types/extract_stream_response.py
delete mode 100644 src/docstrange/types/extraction_format_result.py
delete mode 100644 src/docstrange/types/extraction_metadata.py
delete mode 100644 src/docstrange/types/extraction_result.py
delete mode 100644 src/docstrange/types/file_classification_result.py
delete mode 100644 src/docstrange/types/page_classification.py
delete mode 100644 tests/api_resources/extract/__init__.py
delete mode 100644 tests/api_resources/extract/test_results.py
delete mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index 031d39f..e24fff1 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-4dc8746b7c32d8b0ed281e28dc83a6af06e280f87a173d4535a6e7e0db5d1fe6.yml
-openapi_spec_hash: c6154bc9b0c0f3611223180cc335673b
-config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
+configured_endpoints: 2
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-4a17ecf235fd346afe631381db80e46b26346368a323939de7b0741a5b60ce3d.yml
+openapi_spec_hash: c46bca368a4f85e1a684b309e4129ef5
+config_hash: 6f0ab1fd6c4433590ee82d88ab5298a7
diff --git a/README.md b/README.md
index 991dcba..74c6d8b 100644
--- a/README.md
+++ b/README.md
@@ -115,67 +115,6 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
-## Pagination
-
-List methods in the Docstrange API are paginated.
-
-This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
-
-```python
-from docstrange import Docstrange
-
-client = Docstrange()
-
-all_results = []
-# Automatically fetches more pages as needed.
-for result in client.extract.results.list():
- # Do something with result here
- all_results.append(result)
-print(all_results)
-```
-
-Or, asynchronously:
-
-```python
-import asyncio
-from docstrange import AsyncDocstrange
-
-client = AsyncDocstrange()
-
-
-async def main() -> None:
- all_results = []
- # Iterate through items across all pages, issuing requests as needed.
- async for result in client.extract.results.list():
- all_results.append(result)
- print(all_results)
-
-
-asyncio.run(main())
-```
-
-Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
-
-```python
-first_page = await client.extract.results.list()
-if first_page.has_next_page():
- print(f"will fetch next page using these details: {first_page.next_page_info()}")
- next_page = await first_page.get_next_page()
- print(f"number of items we just fetched: {len(next_page.results)}")
-
-# Remove `await` for non-async usage.
-```
-
-Or just work directly with the returned data:
-
-```python
-first_page = await client.extract.results.list()
-for result in first_page.results:
- print(result.record_id)
-
-# Remove `await` for non-async usage.
-```
-
## File uploads
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)`.
diff --git a/api.md b/api.md
index 7ccbce8..0cac7c9 100644
--- a/api.md
+++ b/api.md
@@ -3,67 +3,21 @@
Types:
```python
-from docstrange.types import (
- BatchExtractRequestBody,
- BatchExtractResponse,
- ExtractRequestBody,
- ExtractResponse,
- ExtractionFormatResult,
- ExtractionMetadata,
- ExtractionResult,
- StreamExtractRequestBody,
- ExtractStreamResponse,
-)
+from docstrange.types import ExtractResponse
```
Methods:
-- client.extract.async\_(\*\*params) -> ExtractResponse
-- client.extract.batch(\*\*params) -> BatchExtractResponse
-- client.extract.stream(\*\*params) -> str
-- client.extract.sync(\*\*params) -> ExtractResponse
-
-## Results
-
-Types:
-
-```python
-from docstrange.types.extract import ExtractionListResponse, PaginationInfo
-```
-
-Methods:
-
-- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
-- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[ExtractResponse]
+- client.extract.sync(\*\*params) -> ExtractResponse
# Classify
Types:
```python
-from docstrange.types import (
- BatchClassifyRequestBody,
- BatchClassifyResponse,
- ClassifyRequestBody,
- ClassifyResponse,
- FileClassificationResult,
- PageClassification,
-)
+from docstrange.types import ClassifyResponse
```
Methods:
-- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
-
-# Chat
-
-Types:
-
-```python
-from docstrange.types import ChatCompletionsRequest
-```
-
-Methods:
-
-- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 4c5bcc4..42d282d 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,10 +31,9 @@
)
if TYPE_CHECKING:
- from .resources import chat, extract, classify
- from .resources.chat import ChatResource, AsyncChatResource
+ from .resources import extract, classify
+ from .resources.extract import ExtractResource, AsyncExtractResource
from .resources.classify import ClassifyResource, AsyncClassifyResource
- from .resources.extract.extract import ExtractResource, AsyncExtractResource
__all__ = [
"Timeout",
@@ -115,12 +114,6 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
- @cached_property
- def chat(self) -> ChatResource:
- from .resources.chat import ChatResource
-
- return ChatResource(self)
-
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -301,12 +294,6 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
- @cached_property
- def chat(self) -> AsyncChatResource:
- from .resources.chat import AsyncChatResource
-
- return AsyncChatResource(self)
-
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -438,12 +425,6 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithRawResponse:
- from .resources.chat import ChatResourceWithRawResponse
-
- return ChatResourceWithRawResponse(self._client.chat)
-
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -463,12 +444,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithRawResponse:
- from .resources.chat import AsyncChatResourceWithRawResponse
-
- return AsyncChatResourceWithRawResponse(self._client.chat)
-
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -488,12 +463,6 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithStreamingResponse:
- from .resources.chat import ChatResourceWithStreamingResponse
-
- return ChatResourceWithStreamingResponse(self._client.chat)
-
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -513,12 +482,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
- from .resources.chat import AsyncChatResourceWithStreamingResponse
-
- return AsyncChatResourceWithStreamingResponse(self._client.chat)
-
Client = Docstrange
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
deleted file mode 100644
index e926095..0000000
--- a/src/docstrange/pagination.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Generic, TypeVar, Optional, cast
-from typing_extensions import override
-
-from ._models import BaseModel
-from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
-
-__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
-
-_T = TypeVar("_T")
-
-
-class PageNumberPaginationPagination(BaseModel):
- has_next: Optional[bool] = None
-
- total_count: Optional[int] = None
-
-
-class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
- results: List[_T]
- pagination: Optional[PageNumberPaginationPagination] = None
-
- @override
- def _get_page_items(self) -> List[_T]:
- results = self.results
- if not results:
- return []
- return results
-
- @override
- def next_page_info(self) -> Optional[PageInfo]:
- last_page = cast("int | None", self._options.params.get("page")) or 1
-
- total_pages = None
- if self.pagination is not None:
- if self.pagination.total_count is not None:
- total_pages = self.pagination.total_count
- if total_pages is not None and last_page >= total_pages:
- return None
-
- return PageInfo(params={"page": last_page + 1})
-
-
-class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
- results: List[_T]
- pagination: Optional[PageNumberPaginationPagination] = None
-
- @override
- def _get_page_items(self) -> List[_T]:
- results = self.results
- if not results:
- return []
- return results
-
- @override
- def next_page_info(self) -> Optional[PageInfo]:
- last_page = cast("int | None", self._options.params.get("page")) or 1
-
- total_pages = None
- if self.pagination is not None:
- if self.pagination.total_count is not None:
- total_pages = self.pagination.total_count
- if total_pages is not None and last_page >= total_pages:
- return None
-
- return PageInfo(params={"page": last_page + 1})
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index a3172dd..6d7ff55 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,13 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from .chat import (
- ChatResource,
- AsyncChatResource,
- ChatResourceWithRawResponse,
- AsyncChatResourceWithRawResponse,
- ChatResourceWithStreamingResponse,
- AsyncChatResourceWithStreamingResponse,
-)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -38,10 +30,4 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
- "ChatResource",
- "AsyncChatResource",
- "ChatResourceWithRawResponse",
- "AsyncChatResourceWithRawResponse",
- "ChatResourceWithStreamingResponse",
- "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
deleted file mode 100644
index 7e8899d..0000000
--- a/src/docstrange/resources/chat.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-
-import httpx
-
-from ..types import chat_create_completion_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-
-__all__ = ["ChatResource", "AsyncChatResource"]
-
-
-class ChatResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ChatResourceWithStreamingResponse(self)
-
- def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- OpenAI-compatible chat completions endpoint.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._post(
- "/v1/chat/completions",
- body=maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class AsyncChatResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncChatResourceWithStreamingResponse(self)
-
- async def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- OpenAI-compatible chat completions endpoint.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return await self._post(
- "/v1/chat/completions",
- body=await async_maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class ChatResourceWithRawResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithRawResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class ChatResourceWithStreamingResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_streamed_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithStreamingResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_streamed_response_wrapper(
- chat.create_completion,
- )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index ded77af..d7853b4 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,11 +2,13 @@
from __future__ import annotations
+from typing import Mapping, cast
+
import httpx
-from ..types import classify_sync_params, classify_batch_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from ..types import classify_sync_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -17,7 +19,6 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
-from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -42,53 +43,6 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
- def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50).
-
- Args:
- categories: JSON array of category objects
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/classify/batch",
- body=maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
def sync(
self,
*,
@@ -117,19 +71,21 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -157,53 +113,6 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
- async def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50).
-
- Args:
- categories: JSON array of category objects
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/classify/batch",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
async def sync(
self,
*,
@@ -232,19 +141,21 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -256,9 +167,6 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_raw_response_wrapper(
- classify.batch,
- )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -268,9 +176,6 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_raw_response_wrapper(
- classify.batch,
- )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -280,9 +185,6 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -292,9 +194,6 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract.py b/src/docstrange/resources/extract.py
new file mode 100644
index 0000000..5b896e5
--- /dev/null
+++ b/src/docstrange/resources/extract.py
@@ -0,0 +1,256 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Mapping, cast
+from typing_extensions import Literal
+
+import httpx
+
+from ..types import extract_sync_params
+from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+from ..types.extract_response import ExtractResponse
+
+__all__ = ["ExtractResource", "AsyncExtractResource"]
+
+
+class ExtractResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ExtractResourceWithStreamingResponse(self)
+
+ def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ prompt_mode: append or replace
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/sync",
+ body=maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class AsyncExtractResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncExtractResourceWithStreamingResponse(self)
+
+ async def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ prompt_mode: append or replace
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/sync",
+ body=await async_maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class ExtractResourceWithRawResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = to_raw_response_wrapper(
+ extract.sync,
+ )
+
+
+class AsyncExtractResourceWithRawResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = async_to_raw_response_wrapper(
+ extract.sync,
+ )
+
+
+class ExtractResourceWithStreamingResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+
+class AsyncExtractResourceWithStreamingResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.sync = async_to_streamed_response_wrapper(
+ extract.sync,
+ )
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
deleted file mode 100644
index 22cd257..0000000
--- a/src/docstrange/resources/extract/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .extract import (
- ExtractResource,
- AsyncExtractResource,
- ExtractResourceWithRawResponse,
- AsyncExtractResourceWithRawResponse,
- ExtractResourceWithStreamingResponse,
- AsyncExtractResourceWithStreamingResponse,
-)
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
-
-__all__ = [
- "ResultsResource",
- "AsyncResultsResource",
- "ResultsResourceWithRawResponse",
- "AsyncResultsResourceWithRawResponse",
- "ResultsResourceWithStreamingResponse",
- "AsyncResultsResourceWithStreamingResponse",
- "ExtractResource",
- "AsyncExtractResource",
- "ExtractResourceWithRawResponse",
- "AsyncExtractResourceWithRawResponse",
- "ExtractResourceWithStreamingResponse",
- "AsyncExtractResourceWithStreamingResponse",
-]
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
deleted file mode 100644
index 335f013..0000000
--- a/src/docstrange/resources/extract/extract.py
+++ /dev/null
@@ -1,724 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-import httpx
-
-from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
-from ..._types import (
- Body,
- Omit,
- Query,
- Headers,
- NotGiven,
- FileTypes,
- SequenceNotStr,
- omit,
- not_given,
-)
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ..._streaming import Stream, AsyncStream
-from ..._base_client import make_request_options
-from ...types.extract_response import ExtractResponse
-from ...types.batch_extract_response import BatchExtractResponse
-from ...types.extract_stream_response import ExtractStreamResponse
-
-__all__ = ["ExtractResource", "AsyncExtractResource"]
-
-
-class ExtractResource(SyncAPIResource):
- @cached_property
- def results(self) -> ResultsResource:
- return ResultsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> ExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ExtractResourceWithStreamingResponse(self)
-
- def async_(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Queue a document for background processing.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/async",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """
- Process multiple files asynchronously (max 50).
-
- Args:
- files: Files to process (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/batch",
- body=maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
- )
-
- def stream(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Stream[ExtractStreamResponse]:
- """
- Stream extraction results via SSE.
-
- Args:
- file: File to upload
-
- output_format: Output format(s)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/stream",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=Stream[ExtractStreamResponse],
- )
-
- def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/sync",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class AsyncExtractResource(AsyncAPIResource):
- @cached_property
- def results(self) -> AsyncResultsResource:
- return AsyncResultsResource(self._client)
-
- @cached_property
- def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncExtractResourceWithStreamingResponse(self)
-
- async def async_(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Queue a document for background processing.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/async",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- async def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """
- Process multiple files asynchronously (max 50).
-
- Args:
- files: Files to process (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/batch",
- body=await async_maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
- )
-
- async def stream(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncStream[ExtractStreamResponse]:
- """
- Stream extraction results via SSE.
-
- Args:
- file: File to upload
-
- output_format: Output format(s)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/stream",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=AsyncStream[ExtractStreamResponse],
- )
-
- async def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/sync",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class ExtractResourceWithRawResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.async_ = to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = to_raw_response_wrapper(
- extract.stream,
- )
- self.sync = to_raw_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> ResultsResourceWithRawResponse:
- return ResultsResourceWithRawResponse(self._extract.results)
-
-
-class AsyncExtractResourceWithRawResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.async_ = async_to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_raw_response_wrapper(
- extract.stream,
- )
- self.sync = async_to_raw_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> AsyncResultsResourceWithRawResponse:
- return AsyncResultsResourceWithRawResponse(self._extract.results)
-
-
-class ExtractResourceWithStreamingResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.async_ = to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = to_streamed_response_wrapper(
- extract.stream,
- )
- self.sync = to_streamed_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> ResultsResourceWithStreamingResponse:
- return ResultsResourceWithStreamingResponse(self._extract.results)
-
-
-class AsyncExtractResourceWithStreamingResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.async_ = async_to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_streamed_response_wrapper(
- extract.stream,
- )
- self.sync = async_to_streamed_response_wrapper(
- extract.sync,
- )
-
- @cached_property
- def results(self) -> AsyncResultsResourceWithStreamingResponse:
- return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
deleted file mode 100644
index bf20529..0000000
--- a/src/docstrange/resources/extract/results.py
+++ /dev/null
@@ -1,290 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-from ..._base_client import AsyncPaginator, make_request_options
-from ...types.extract import result_list_params, result_retrieve_params
-from ...types.extract_response import ExtractResponse
-
-__all__ = ["ResultsResource", "AsyncResultsResource"]
-
-
-class ResultsResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ResultsResourceWithStreamingResponse(self)
-
- def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> SyncPageNumberPagination[ExtractResponse]:
- """
- List all extraction jobs (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=SyncPageNumberPagination[ExtractResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=ExtractResponse,
- )
-
-
-class AsyncResultsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncResultsResourceWithStreamingResponse(self)
-
- async def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return await self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncPaginator[ExtractResponse, AsyncPageNumberPagination[ExtractResponse]]:
- """
- List all extraction jobs (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=AsyncPageNumberPagination[ExtractResponse],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=ExtractResponse,
- )
-
-
-class ResultsResourceWithRawResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = to_raw_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithRawResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_raw_response_wrapper(
- results.list,
- )
-
-
-class ResultsResourceWithStreamingResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = to_streamed_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithStreamingResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_streamed_response_wrapper(
- results.list,
- )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index a18a10a..fac3955 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -4,18 +4,5 @@
from .extract_response import ExtractResponse as ExtractResponse
from .classify_response import ClassifyResponse as ClassifyResponse
-from .extraction_result import ExtractionResult as ExtractionResult
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
-from .extraction_metadata import ExtractionMetadata as ExtractionMetadata
-from .page_classification import PageClassification as PageClassification
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
-from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
-from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
-from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
-from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
-from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
-from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
-from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
-from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
-from .file_classification_result import FileClassificationResult as FileClassificationResult
-from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
deleted file mode 100644
index a36e5a8..0000000
--- a/src/docstrange/types/batch_classify_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-from .file_classification_result import FileClassificationResult
-
-__all__ = ["BatchClassifyResponse"]
-
-
-class BatchClassifyResponse(BaseModel):
- batch_id: str
-
- failed_files: int
-
- message: str
-
- results: List[FileClassificationResult]
-
- success: bool
-
- successful_files: int
-
- total_files: int
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
deleted file mode 100644
index 4e73773..0000000
--- a/src/docstrange/types/batch_extract_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-from .extract_response import ExtractResponse
-
-__all__ = ["BatchExtractResponse"]
-
-
-class BatchExtractResponse(BaseModel):
- accepted_files: int
-
- batch_id: str
-
- message: str
-
- records: List[ExtractResponse]
-
- rejected_files: int
-
- success: bool
-
- total_files: int
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
deleted file mode 100644
index eea9be6..0000000
--- a/src/docstrange/types/chat_create_completion_params.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-from typing_extensions import Required, TypedDict
-
-__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
-
-
-class ChatCreateCompletionParams(TypedDict, total=False):
- messages: Required[Iterable[Message]]
-
- model: Required[str]
-
- stream: bool
-
-
-class MessageContentFileURL(TypedDict, total=False):
- url: str
-
-
-class MessageContentImageURL(TypedDict, total=False):
- url: str
-
-
-class MessageContent(TypedDict, total=False):
- file_url: MessageContentFileURL
-
- image_url: MessageContentImageURL
-
- text: str
-
- type: str
-
-
-class Message(TypedDict, total=False):
- content: Required[Iterable[MessageContent]]
-
- role: Required[str]
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
deleted file mode 100644
index 1f23cd0..0000000
--- a/src/docstrange/types/classify_batch_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ClassifyBatchParams"]
-
-
-class ClassifyBatchParams(TypedDict, total=False):
- categories: Required[str]
- """JSON array of category objects"""
-
- files: Required[SequenceNotStr[FileTypes]]
- """Files to classify (max 50)"""
diff --git a/src/docstrange/types/classify_response.py b/src/docstrange/types/classify_response.py
index fdebbb0..5bab3de 100644
--- a/src/docstrange/types/classify_response.py
+++ b/src/docstrange/types/classify_response.py
@@ -1,9 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
-
from .._models import BaseModel
-from .file_classification_result import FileClassificationResult
__all__ = ["ClassifyResponse"]
@@ -12,5 +9,3 @@ class ClassifyResponse(BaseModel):
message: str
success: bool
-
- result: Optional[FileClassificationResult] = None
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
deleted file mode 100644
index 387a007..0000000
--- a/src/docstrange/types/extract/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from .pagination_info import PaginationInfo as PaginationInfo
-from .result_list_params import ResultListParams as ResultListParams
-from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
-from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
deleted file mode 100644
index 26a12e7..0000000
--- a/src/docstrange/types/extract/extraction_list_response.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from ..._models import BaseModel
-from .pagination_info import PaginationInfo
-from ..extract_response import ExtractResponse
-
-__all__ = ["ExtractionListResponse"]
-
-
-class ExtractionListResponse(BaseModel):
- pagination: PaginationInfo
-
- results: List[ExtractResponse]
-
- success: bool
diff --git a/src/docstrange/types/extract/pagination_info.py b/src/docstrange/types/extract/pagination_info.py
deleted file mode 100644
index 7a678a9..0000000
--- a/src/docstrange/types/extract/pagination_info.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from ..._models import BaseModel
-
-__all__ = ["PaginationInfo"]
-
-
-class PaginationInfo(BaseModel):
- has_next: Optional[bool] = None
-
- has_previous: Optional[bool] = None
-
- page: Optional[int] = None
-
- page_size: Optional[int] = None
-
- total_count: Optional[int] = None
-
- total_pages: Optional[int] = None
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
deleted file mode 100644
index 7dfe38a..0000000
--- a/src/docstrange/types/extract/result_list_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypedDict
-
-__all__ = ["ResultListParams"]
-
-
-class ResultListParams(TypedDict, total=False):
- page: int
-
- page_size: int
-
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
-
- sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
deleted file mode 100644
index 1de1a80..0000000
--- a/src/docstrange/types/extract/result_retrieve_params.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import TypedDict
-
-__all__ = ["ResultRetrieveParams"]
-
-
-class ResultRetrieveParams(TypedDict, total=False):
- include_content: bool
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
deleted file mode 100644
index 2895923..0000000
--- a/src/docstrange/types/extract_async_params.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractAsyncParams"]
-
-
-class ExtractAsyncParams(TypedDict, total=False):
- file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
- output_format: Required[str]
- """Output format(s): markdown, html, json, csv."""
-
- csv_options: str
- """CSV extraction options"""
-
- custom_instructions: str
- """Custom extraction instructions"""
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata types"""
-
- json_options: str
- """JSON extraction options"""
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
deleted file mode 100644
index 380d386..0000000
--- a/src/docstrange/types/extract_batch_params.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ExtractBatchParams"]
-
-
-class ExtractBatchParams(TypedDict, total=False):
- files: Required[SequenceNotStr[FileTypes]]
- """Files to process (max 50)"""
-
- output_format: Required[str]
-
- csv_options: str
-
- custom_instructions: str
-
- include_metadata: str
-
- json_options: str
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_response.py b/src/docstrange/types/extract_response.py
index a4d3ed3..ba021e0 100644
--- a/src/docstrange/types/extract_response.py
+++ b/src/docstrange/types/extract_response.py
@@ -1,34 +1,17 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
-from datetime import datetime
-from typing_extensions import Literal
from .._models import BaseModel
-from .extraction_result import ExtractionResult
__all__ = ["ExtractResponse"]
class ExtractResponse(BaseModel):
- message: str
-
record_id: str
- status: Literal["completed", "processing", "failed"]
+ status: str
success: bool
- created_at: Optional[datetime] = None
-
- file_size: Optional[int] = None
-
- filename: Optional[str] = None
-
- output_format: Optional[str] = None
-
- pages_processed: Optional[int] = None
-
- processing_time: Optional[float] = None
-
- result: Optional[ExtractionResult] = None
+ message: Optional[str] = None
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
deleted file mode 100644
index 52147de..0000000
--- a/src/docstrange/types/extract_stream_params.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractStreamParams"]
-
-
-class ExtractStreamParams(TypedDict, total=False):
- file: Required[FileTypes]
- """File to upload"""
-
- output_format: Required[str]
- """Output format(s)"""
-
- csv_options: str
-
- custom_instructions: str
-
- enable_streaming: bool
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
-
- json_options: str
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
deleted file mode 100644
index 333ff97..0000000
--- a/src/docstrange/types/extract_stream_response.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import TypeAlias
-
-__all__ = ["ExtractStreamResponse"]
-
-ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 3208694..1f032ea 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -35,3 +35,4 @@ class ExtractSyncParams(TypedDict, total=False):
"""JSON extraction options"""
prompt_mode: Literal["append", "replace"]
+ """append or replace"""
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
deleted file mode 100644
index 579500c..0000000
--- a/src/docstrange/types/extraction_format_result.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Union, Optional
-
-from .._models import BaseModel
-from .extraction_metadata import ExtractionMetadata
-
-__all__ = ["ExtractionFormatResult"]
-
-
-class ExtractionFormatResult(BaseModel):
- content: Union[str, object]
- """Extracted content"""
-
- metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/extraction_metadata.py b/src/docstrange/types/extraction_metadata.py
deleted file mode 100644
index d206781..0000000
--- a/src/docstrange/types/extraction_metadata.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from .._models import BaseModel
-
-__all__ = ["ExtractionMetadata"]
-
-
-class ExtractionMetadata(BaseModel):
- bounding_boxes: Optional[object] = None
-
- confidence_score: Optional[object] = None
diff --git a/src/docstrange/types/extraction_result.py b/src/docstrange/types/extraction_result.py
deleted file mode 100644
index 8cd1772..0000000
--- a/src/docstrange/types/extraction_result.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-from .extraction_format_result import ExtractionFormatResult
-
-__all__ = ["ExtractionResult"]
-
-
-class ExtractionResult(BaseModel):
- csv: Optional[ExtractionFormatResult] = None
-
- html: Optional[ExtractionFormatResult] = None
-
- json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
-
- markdown: Optional[ExtractionFormatResult] = None
diff --git a/src/docstrange/types/file_classification_result.py b/src/docstrange/types/file_classification_result.py
deleted file mode 100644
index 3c1b290..0000000
--- a/src/docstrange/types/file_classification_result.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from .._models import BaseModel
-from .page_classification import PageClassification
-
-__all__ = ["FileClassificationResult"]
-
-
-class FileClassificationResult(BaseModel):
- filename: str
-
- pages: List[PageClassification]
-
- total_pages: int
-
- error: Optional[str] = None
-
- processing_time: Optional[float] = None
-
- record_id: Optional[str] = None
diff --git a/src/docstrange/types/page_classification.py b/src/docstrange/types/page_classification.py
deleted file mode 100644
index afc73a3..0000000
--- a/src/docstrange/types/page_classification.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-
-from .._models import BaseModel
-
-__all__ = ["PageClassification"]
-
-
-class PageClassification(BaseModel):
- category: str
-
- confidence: int
-
- page_number: int
-
- reasoning: str
-
- identified_category: Optional[str] = None
diff --git a/tests/api_resources/extract/__init__.py b/tests/api_resources/extract/__init__.py
deleted file mode 100644
index fd8019a..0000000
--- a/tests/api_resources/extract/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
deleted file mode 100644
index ee1d5f5..0000000
--- a/tests/api_resources/extract/test_results.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
-from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestResults:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_retrieve(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_retrieve(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_retrieve(self, client: Docstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list(self, client: Docstrange) -> None:
- result = client.extract.results.list()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncResults:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- await async_client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
deleted file mode 100644
index 84bfced..0000000
--- a/tests/api_resources/test_chat.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestChat:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "type",
- }
- ],
- "role": "role",
- }
- ],
- model="model",
- stream=True,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_create_completion(self, client: Docstrange) -> None:
- response = client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_create_completion(self, client: Docstrange) -> None:
- with client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncChat:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "type",
- }
- ],
- "role": "role",
- }
- ],
- model="model",
- stream=True,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- async with async_client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index d40e1fa..63539df 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse, BatchClassifyResponse
+from docstrange.types import ClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,43 +17,6 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- classify = client.classify.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.classify.with_raw_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.classify.with_streaming_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -97,43 +60,6 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- classify = await async_client.classify.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.classify.with_raw_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.classify.with_streaming_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index bd13f30..d911970 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,10 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import (
- ExtractResponse,
- BatchExtractResponse,
-)
+from docstrange.types import ExtractResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -20,163 +17,6 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_async(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_async(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream_with_all_params(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- enable_streaming=True,
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_raw_response_stream(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = response.parse()
- stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_streaming_response_stream(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = response.parse()
- stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -236,163 +76,6 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- enable_streaming=True,
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = await response.parse()
- await stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = await response.parse()
- await stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
From f6e304ad4aea0364c89273b1a17f53cf730c9f09 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:29:03 +0000
Subject: [PATCH 21/26] feat(api): api update
---
.stats.yml | 8 +-
README.md | 61 ++
api.md | 47 +-
src/docstrange/_client.py | 41 +-
src/docstrange/pagination.py | 67 ++
src/docstrange/resources/__init__.py | 14 +
src/docstrange/resources/chat.py | 182 +++++
src/docstrange/resources/classify.py | 147 +++-
src/docstrange/resources/extract.py | 256 -------
src/docstrange/resources/extract/__init__.py | 33 +
src/docstrange/resources/extract/extract.py | 724 ++++++++++++++++++
src/docstrange/resources/extract/results.py | 290 +++++++
src/docstrange/types/__init__.py | 8 +
.../types/batch_classify_response.py | 13 +
.../types/batch_extract_response.py | 13 +
.../types/chat_create_completion_params.py | 40 +
src/docstrange/types/classify_batch_params.py | 17 +
src/docstrange/types/extract/__init__.py | 7 +
.../types/extract/extraction_list_response.py | 15 +
.../types/extract/result_list_params.py | 17 +
.../types/extract/result_retrieve_params.py | 11 +
src/docstrange/types/extract_async_params.py | 37 +
src/docstrange/types/extract_batch_params.py | 26 +
src/docstrange/types/extract_stream_params.py | 35 +
.../types/extract_stream_response.py | 7 +
src/docstrange/types/extract_sync_params.py | 1 -
tests/api_resources/extract/__init__.py | 1 +
tests/api_resources/extract/test_results.py | 205 +++++
tests/api_resources/test_chat.py | 171 +++++
tests/api_resources/test_classify.py | 76 +-
tests/api_resources/test_extract.py | 319 +++++++-
31 files changed, 2598 insertions(+), 291 deletions(-)
create mode 100644 src/docstrange/pagination.py
create mode 100644 src/docstrange/resources/chat.py
delete mode 100644 src/docstrange/resources/extract.py
create mode 100644 src/docstrange/resources/extract/__init__.py
create mode 100644 src/docstrange/resources/extract/extract.py
create mode 100644 src/docstrange/resources/extract/results.py
create mode 100644 src/docstrange/types/batch_classify_response.py
create mode 100644 src/docstrange/types/batch_extract_response.py
create mode 100644 src/docstrange/types/chat_create_completion_params.py
create mode 100644 src/docstrange/types/classify_batch_params.py
create mode 100644 src/docstrange/types/extract/__init__.py
create mode 100644 src/docstrange/types/extract/extraction_list_response.py
create mode 100644 src/docstrange/types/extract/result_list_params.py
create mode 100644 src/docstrange/types/extract/result_retrieve_params.py
create mode 100644 src/docstrange/types/extract_async_params.py
create mode 100644 src/docstrange/types/extract_batch_params.py
create mode 100644 src/docstrange/types/extract_stream_params.py
create mode 100644 src/docstrange/types/extract_stream_response.py
create mode 100644 tests/api_resources/extract/__init__.py
create mode 100644 tests/api_resources/extract/test_results.py
create mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index e24fff1..2430e33 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 2
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-4a17ecf235fd346afe631381db80e46b26346368a323939de7b0741a5b60ce3d.yml
-openapi_spec_hash: c46bca368a4f85e1a684b309e4129ef5
-config_hash: 6f0ab1fd6c4433590ee82d88ab5298a7
+configured_endpoints: 9
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-61ca0326580cb90b4bc39c85c49cb2083d14ce9865ea272f2cb84cc7c639b0b2.yml
+openapi_spec_hash: 6940490040b26eeb3c38bb2d7d9f00ce
+config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
diff --git a/README.md b/README.md
index 74c6d8b..e26fbd2 100644
--- a/README.md
+++ b/README.md
@@ -115,6 +115,67 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
+## Pagination
+
+List methods in the Docstrange API are paginated.
+
+This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
+
+```python
+from docstrange import Docstrange
+
+client = Docstrange()
+
+all_results = []
+# Automatically fetches more pages as needed.
+for result in client.extract.results.list():
+ # Do something with result here
+ all_results.append(result)
+print(all_results)
+```
+
+Or, asynchronously:
+
+```python
+import asyncio
+from docstrange import AsyncDocstrange
+
+client = AsyncDocstrange()
+
+
+async def main() -> None:
+ all_results = []
+ # Iterate through items across all pages, issuing requests as needed.
+ async for result in client.extract.results.list():
+ all_results.append(result)
+ print(all_results)
+
+
+asyncio.run(main())
+```
+
+Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
+
+```python
+first_page = await client.extract.results.list()
+if first_page.has_next_page():
+ print(f"will fetch next page using these details: {first_page.next_page_info()}")
+ next_page = await first_page.get_next_page()
+ print(f"number of items we just fetched: {len(next_page.results)}")
+
+# Remove `await` for non-async usage.
+```
+
+Or just work directly with the returned data:
+
+```python
+first_page = await client.extract.results.list()
+for result in first_page.results:
+ print(result)
+
+# Remove `await` for non-async usage.
+```
+
## File uploads
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)`.
diff --git a/api.md b/api.md
index 0cac7c9..790cf4e 100644
--- a/api.md
+++ b/api.md
@@ -3,21 +3,62 @@
Types:
```python
-from docstrange.types import ExtractResponse
+from docstrange.types import (
+ BatchExtractRequestBody,
+ BatchExtractResponse,
+ ExtractRequestBody,
+ ExtractResponse,
+ StreamExtractRequestBody,
+ ExtractStreamResponse,
+)
```
Methods:
-- client.extract.sync(\*\*params) -> ExtractResponse
+- client.extract.async\_(\*\*params) -> ExtractResponse
+- client.extract.batch(\*\*params) -> BatchExtractResponse
+- client.extract.stream(\*\*params) -> str
+- client.extract.sync(\*\*params) -> ExtractResponse
+
+## Results
+
+Types:
+
+```python
+from docstrange.types.extract import ExtractionListResponse
+```
+
+Methods:
+
+- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
+- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[object]
# Classify
Types:
```python
-from docstrange.types import ClassifyResponse
+from docstrange.types import (
+ BatchClassifyRequestBody,
+ BatchClassifyResponse,
+ ClassifyRequestBody,
+ ClassifyResponse,
+)
```
Methods:
+- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
+
+# Chat
+
+Types:
+
+```python
+from docstrange.types import ChatCompletionsRequest
+```
+
+Methods:
+
+- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 42d282d..4c5bcc4 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,9 +31,10 @@
)
if TYPE_CHECKING:
- from .resources import extract, classify
- from .resources.extract import ExtractResource, AsyncExtractResource
+ from .resources import chat, extract, classify
+ from .resources.chat import ChatResource, AsyncChatResource
from .resources.classify import ClassifyResource, AsyncClassifyResource
+ from .resources.extract.extract import ExtractResource, AsyncExtractResource
__all__ = [
"Timeout",
@@ -114,6 +115,12 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
+ @cached_property
+ def chat(self) -> ChatResource:
+ from .resources.chat import ChatResource
+
+ return ChatResource(self)
+
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -294,6 +301,12 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
+ @cached_property
+ def chat(self) -> AsyncChatResource:
+ from .resources.chat import AsyncChatResource
+
+ return AsyncChatResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -425,6 +438,12 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithRawResponse:
+ from .resources.chat import ChatResourceWithRawResponse
+
+ return ChatResourceWithRawResponse(self._client.chat)
+
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -444,6 +463,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithRawResponse:
+ from .resources.chat import AsyncChatResourceWithRawResponse
+
+ return AsyncChatResourceWithRawResponse(self._client.chat)
+
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -463,6 +488,12 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithStreamingResponse:
+ from .resources.chat import ChatResourceWithStreamingResponse
+
+ return ChatResourceWithStreamingResponse(self._client.chat)
+
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -482,6 +513,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
+ from .resources.chat import AsyncChatResourceWithStreamingResponse
+
+ return AsyncChatResourceWithStreamingResponse(self._client.chat)
+
Client = Docstrange
diff --git a/src/docstrange/pagination.py b/src/docstrange/pagination.py
new file mode 100644
index 0000000..e926095
--- /dev/null
+++ b/src/docstrange/pagination.py
@@ -0,0 +1,67 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Generic, TypeVar, Optional, cast
+from typing_extensions import override
+
+from ._models import BaseModel
+from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
+
+__all__ = ["PageNumberPaginationPagination", "SyncPageNumberPagination", "AsyncPageNumberPagination"]
+
+_T = TypeVar("_T")
+
+
+class PageNumberPaginationPagination(BaseModel):
+ has_next: Optional[bool] = None
+
+ total_count: Optional[int] = None
+
+
+class SyncPageNumberPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ results = self.results
+ if not results:
+ return []
+ return results
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
+ return PageInfo(params={"page": last_page + 1})
+
+
+class AsyncPageNumberPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
+ results: List[_T]
+ pagination: Optional[PageNumberPaginationPagination] = None
+
+ @override
+ def _get_page_items(self) -> List[_T]:
+ results = self.results
+ if not results:
+ return []
+ return results
+
+ @override
+ def next_page_info(self) -> Optional[PageInfo]:
+ last_page = cast("int | None", self._options.params.get("page")) or 1
+
+ total_pages = None
+ if self.pagination is not None:
+ if self.pagination.total_count is not None:
+ total_pages = self.pagination.total_count
+ if total_pages is not None and last_page >= total_pages:
+ return None
+
+ return PageInfo(params={"page": last_page + 1})
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index 6d7ff55..a3172dd 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,5 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .chat import (
+ ChatResource,
+ AsyncChatResource,
+ ChatResourceWithRawResponse,
+ AsyncChatResourceWithRawResponse,
+ ChatResourceWithStreamingResponse,
+ AsyncChatResourceWithStreamingResponse,
+)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -30,4 +38,10 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
+ "ChatResource",
+ "AsyncChatResource",
+ "ChatResourceWithRawResponse",
+ "AsyncChatResourceWithRawResponse",
+ "ChatResourceWithStreamingResponse",
+ "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
new file mode 100644
index 0000000..7e8899d
--- /dev/null
+++ b/src/docstrange/resources/chat.py
@@ -0,0 +1,182 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+
+import httpx
+
+from ..types import chat_create_completion_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+
+__all__ = ["ChatResource", "AsyncChatResource"]
+
+
+class ChatResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ChatResourceWithStreamingResponse(self)
+
+ def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """
+ OpenAI-compatible chat completions endpoint.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._post(
+ "/v1/chat/completions",
+ body=maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class AsyncChatResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncChatResourceWithStreamingResponse(self)
+
+ async def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """
+ OpenAI-compatible chat completions endpoint.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._post(
+ "/v1/chat/completions",
+ body=await async_maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class ChatResourceWithRawResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithRawResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class ChatResourceWithStreamingResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_streamed_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithStreamingResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_streamed_response_wrapper(
+ chat.create_completion,
+ )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index d7853b4..ded77af 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,13 +2,11 @@
from __future__ import annotations
-from typing import Mapping, cast
-
import httpx
-from ..types import classify_sync_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from ..types import classify_sync_params, classify_batch_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
+from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -19,6 +17,7 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
+from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -43,6 +42,53 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
+ def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50).
+
+ Args:
+ categories: JSON array of category objects
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/classify/batch",
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
def sync(
self,
*,
@@ -71,21 +117,19 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -113,6 +157,53 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
+ async def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50).
+
+ Args:
+ categories: JSON array of category objects
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/classify/batch",
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "files": files,
+ },
+ classify_batch_params.ClassifyBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
async def sync(
self,
*,
@@ -141,21 +232,19 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
- body = deepcopy_minimal(
- {
- "categories": categories,
- "file": file,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
- files=files,
+ body=await async_maybe_transform(
+ {
+ "categories": categories,
+ "file": file,
+ },
+ classify_sync_params.ClassifySyncParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -167,6 +256,9 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -176,6 +268,9 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -185,6 +280,9 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -194,6 +292,9 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract.py b/src/docstrange/resources/extract.py
deleted file mode 100644
index 5b896e5..0000000
--- a/src/docstrange/resources/extract.py
+++ /dev/null
@@ -1,256 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Mapping, cast
-from typing_extensions import Literal
-
-import httpx
-
-from ..types import extract_sync_params
-from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-from ..types.extract_response import ExtractResponse
-
-__all__ = ["ExtractResource", "AsyncExtractResource"]
-
-
-class ExtractResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ExtractResourceWithStreamingResponse(self)
-
- def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- prompt_mode: append or replace
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- body = deepcopy_minimal(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/sync",
- body=maybe_transform(body, extract_sync_params.ExtractSyncParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class AsyncExtractResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncExtractResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncExtractResourceWithStreamingResponse(self)
-
- async def sync(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- prompt_mode: append or replace
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- body = deepcopy_minimal(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/sync",
- body=await async_maybe_transform(body, extract_sync_params.ExtractSyncParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
-
-class ExtractResourceWithRawResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.sync = to_raw_response_wrapper(
- extract.sync,
- )
-
-
-class AsyncExtractResourceWithRawResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.sync = async_to_raw_response_wrapper(
- extract.sync,
- )
-
-
-class ExtractResourceWithStreamingResponse:
- def __init__(self, extract: ExtractResource) -> None:
- self._extract = extract
-
- self.sync = to_streamed_response_wrapper(
- extract.sync,
- )
-
-
-class AsyncExtractResourceWithStreamingResponse:
- def __init__(self, extract: AsyncExtractResource) -> None:
- self._extract = extract
-
- self.sync = async_to_streamed_response_wrapper(
- extract.sync,
- )
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
new file mode 100644
index 0000000..22cd257
--- /dev/null
+++ b/src/docstrange/resources/extract/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .extract import (
+ ExtractResource,
+ AsyncExtractResource,
+ ExtractResourceWithRawResponse,
+ AsyncExtractResourceWithRawResponse,
+ ExtractResourceWithStreamingResponse,
+ AsyncExtractResourceWithStreamingResponse,
+)
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ResultsResource",
+ "AsyncResultsResource",
+ "ResultsResourceWithRawResponse",
+ "AsyncResultsResourceWithRawResponse",
+ "ResultsResourceWithStreamingResponse",
+ "AsyncResultsResourceWithStreamingResponse",
+ "ExtractResource",
+ "AsyncExtractResource",
+ "ExtractResourceWithRawResponse",
+ "AsyncExtractResourceWithRawResponse",
+ "ExtractResourceWithStreamingResponse",
+ "AsyncExtractResourceWithStreamingResponse",
+]
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
new file mode 100644
index 0000000..335f013
--- /dev/null
+++ b/src/docstrange/resources/extract/extract.py
@@ -0,0 +1,724 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
+from ..._types import (
+ Body,
+ Omit,
+ Query,
+ Headers,
+ NotGiven,
+ FileTypes,
+ SequenceNotStr,
+ omit,
+ not_given,
+)
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ..._streaming import Stream, AsyncStream
+from ..._base_client import make_request_options
+from ...types.extract_response import ExtractResponse
+from ...types.batch_extract_response import BatchExtractResponse
+from ...types.extract_stream_response import ExtractStreamResponse
+
+__all__ = ["ExtractResource", "AsyncExtractResource"]
+
+
+class ExtractResource(SyncAPIResource):
+ @cached_property
+ def results(self) -> ResultsResource:
+ return ResultsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> ExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ExtractResourceWithStreamingResponse(self)
+
+ def async_(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Queue a document for background processing.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/async",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_async_params.ExtractAsyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """
+ Process multiple files asynchronously (max 50).
+
+ Args:
+ files: Files to process (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/batch",
+ body=maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ def stream(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> Stream[ExtractStreamResponse]:
+ """
+ Stream extraction results via SSE.
+
+ Args:
+ file: File to upload
+
+ output_format: Output format(s)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/stream",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=str,
+ stream=True,
+ stream_cls=Stream[ExtractStreamResponse],
+ )
+
+ def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/sync",
+ body=maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_sync_params.ExtractSyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class AsyncExtractResource(AsyncAPIResource):
+ @cached_property
+ def results(self) -> AsyncResultsResource:
+ return AsyncResultsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncExtractResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncExtractResourceWithStreamingResponse(self)
+
+ async def async_(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Queue a document for background processing.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/async",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_async_params.ExtractAsyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ async def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """
+ Process multiple files asynchronously (max 50).
+
+ Args:
+ files: Files to process (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/batch",
+ body=await async_maybe_transform(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_batch_params.ExtractBatchParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ async def stream(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncStream[ExtractStreamResponse]:
+ """
+ Stream extraction results via SSE.
+
+ Args:
+ file: File to upload
+
+ output_format: Output format(s)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/stream",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_stream_params.ExtractStreamParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=str,
+ stream=True,
+ stream_cls=AsyncStream[ExtractStreamResponse],
+ )
+
+ async def sync(
+ self,
+ *,
+ file: FileTypes,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Process a document and return extracted content immediately.
+
+ Args:
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ output_format: Output format(s): markdown, html, json, csv.
+
+ csv_options: CSV extraction options
+
+ custom_instructions: Custom extraction instructions
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata types
+
+ json_options: JSON extraction options
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/sync",
+ body=await async_maybe_transform(
+ {
+ "file": file,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ },
+ extract_sync_params.ExtractSyncParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+
+class ExtractResourceWithRawResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_raw_response_wrapper(
+ extract.stream,
+ )
+ self.sync = to_raw_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> ResultsResourceWithRawResponse:
+ return ResultsResourceWithRawResponse(self._extract.results)
+
+
+class AsyncExtractResourceWithRawResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = async_to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_raw_response_wrapper(
+ extract.stream,
+ )
+ self.sync = async_to_raw_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithRawResponse:
+ return AsyncResultsResourceWithRawResponse(self._extract.results)
+
+
+class ExtractResourceWithStreamingResponse:
+ def __init__(self, extract: ExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_streamed_response_wrapper(
+ extract.stream,
+ )
+ self.sync = to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> ResultsResourceWithStreamingResponse:
+ return ResultsResourceWithStreamingResponse(self._extract.results)
+
+
+class AsyncExtractResourceWithStreamingResponse:
+ def __init__(self, extract: AsyncExtractResource) -> None:
+ self._extract = extract
+
+ self.async_ = async_to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_streamed_response_wrapper(
+ extract.stream,
+ )
+ self.sync = async_to_streamed_response_wrapper(
+ extract.sync,
+ )
+
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithStreamingResponse:
+ return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
new file mode 100644
index 0000000..dab80bf
--- /dev/null
+++ b/src/docstrange/resources/extract/results.py
@@ -0,0 +1,290 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+from ..._base_client import AsyncPaginator, make_request_options
+from ...types.extract import result_list_params, result_retrieve_params
+from ...types.extract_response import ExtractResponse
+
+__all__ = ["ResultsResource", "AsyncResultsResource"]
+
+
+class ResultsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ResultsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> SyncPageNumberPagination[object]:
+ """
+ List all extraction jobs (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=SyncPageNumberPagination[object],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=object,
+ )
+
+
+class AsyncResultsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncResultsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return await self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncPaginator[object, AsyncPageNumberPagination[object]]:
+ """
+ List all extraction jobs (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=AsyncPageNumberPagination[object],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=object,
+ )
+
+
+class ResultsResourceWithRawResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithRawResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class ResultsResourceWithStreamingResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithStreamingResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ results.list,
+ )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index fac3955..f7946ad 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -6,3 +6,11 @@
from .classify_response import ClassifyResponse as ClassifyResponse
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
+from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
+from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
+from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
+from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
+from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
+from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
+from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
+from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
new file mode 100644
index 0000000..7b26938
--- /dev/null
+++ b/src/docstrange/types/batch_classify_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["BatchClassifyResponse"]
+
+
+class BatchClassifyResponse(BaseModel):
+ batch_id: str
+
+ message: str
+
+ success: bool
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
new file mode 100644
index 0000000..64b21bf
--- /dev/null
+++ b/src/docstrange/types/batch_extract_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["BatchExtractResponse"]
+
+
+class BatchExtractResponse(BaseModel):
+ batch_id: str
+
+ message: str
+
+ success: bool
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
new file mode 100644
index 0000000..eea9be6
--- /dev/null
+++ b/src/docstrange/types/chat_create_completion_params.py
@@ -0,0 +1,40 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
+
+
+class ChatCreateCompletionParams(TypedDict, total=False):
+ messages: Required[Iterable[Message]]
+
+ model: Required[str]
+
+ stream: bool
+
+
+class MessageContentFileURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContentImageURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContent(TypedDict, total=False):
+ file_url: MessageContentFileURL
+
+ image_url: MessageContentImageURL
+
+ text: str
+
+ type: str
+
+
+class Message(TypedDict, total=False):
+ content: Required[Iterable[MessageContent]]
+
+ role: Required[str]
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
new file mode 100644
index 0000000..1f23cd0
--- /dev/null
+++ b/src/docstrange/types/classify_batch_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ClassifyBatchParams"]
+
+
+class ClassifyBatchParams(TypedDict, total=False):
+ categories: Required[str]
+ """JSON array of category objects"""
+
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to classify (max 50)"""
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
new file mode 100644
index 0000000..692c8de
--- /dev/null
+++ b/src/docstrange/types/extract/__init__.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .result_list_params import ResultListParams as ResultListParams
+from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
+from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
new file mode 100644
index 0000000..60f049a
--- /dev/null
+++ b/src/docstrange/types/extract/extraction_list_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+
+__all__ = ["ExtractionListResponse"]
+
+
+class ExtractionListResponse(BaseModel):
+ pagination: object
+
+ results: List[object]
+
+ success: bool
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
new file mode 100644
index 0000000..7dfe38a
--- /dev/null
+++ b/src/docstrange/types/extract/result_list_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["ResultListParams"]
+
+
+class ResultListParams(TypedDict, total=False):
+ page: int
+
+ page_size: int
+
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+
+ sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
new file mode 100644
index 0000000..1de1a80
--- /dev/null
+++ b/src/docstrange/types/extract/result_retrieve_params.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["ResultRetrieveParams"]
+
+
+class ResultRetrieveParams(TypedDict, total=False):
+ include_content: bool
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
new file mode 100644
index 0000000..2895923
--- /dev/null
+++ b/src/docstrange/types/extract_async_params.py
@@ -0,0 +1,37 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractAsyncParams"]
+
+
+class ExtractAsyncParams(TypedDict, total=False):
+ file: Required[FileTypes]
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+
+ output_format: Required[str]
+ """Output format(s): markdown, html, json, csv."""
+
+ csv_options: str
+ """CSV extraction options"""
+
+ custom_instructions: str
+ """Custom extraction instructions"""
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata types"""
+
+ json_options: str
+ """JSON extraction options"""
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
new file mode 100644
index 0000000..380d386
--- /dev/null
+++ b/src/docstrange/types/extract_batch_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ExtractBatchParams"]
+
+
+class ExtractBatchParams(TypedDict, total=False):
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to process (max 50)"""
+
+ output_format: Required[str]
+
+ csv_options: str
+
+ custom_instructions: str
+
+ include_metadata: str
+
+ json_options: str
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
new file mode 100644
index 0000000..52147de
--- /dev/null
+++ b/src/docstrange/types/extract_stream_params.py
@@ -0,0 +1,35 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractStreamParams"]
+
+
+class ExtractStreamParams(TypedDict, total=False):
+ file: Required[FileTypes]
+ """File to upload"""
+
+ output_format: Required[str]
+ """Output format(s)"""
+
+ csv_options: str
+
+ custom_instructions: str
+
+ enable_streaming: bool
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+
+ json_options: str
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
new file mode 100644
index 0000000..333ff97
--- /dev/null
+++ b/src/docstrange/types/extract_stream_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["ExtractStreamResponse"]
+
+ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 1f032ea..3208694 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -35,4 +35,3 @@ class ExtractSyncParams(TypedDict, total=False):
"""JSON extraction options"""
prompt_mode: Literal["append", "replace"]
- """append or replace"""
diff --git a/tests/api_resources/extract/__init__.py b/tests/api_resources/extract/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/extract/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
new file mode 100644
index 0000000..0b67e0f
--- /dev/null
+++ b/tests/api_resources/extract/test_results.py
@@ -0,0 +1,205 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+from docstrange.types import ExtractResponse
+from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestResults:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Docstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Docstrange) -> None:
+ result = client.extract.results.list()
+ assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncResults:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ await async_client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list()
+ assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
new file mode 100644
index 0000000..84bfced
--- /dev/null
+++ b/tests/api_resources/test_chat.py
@@ -0,0 +1,171 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestChat:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "type",
+ }
+ ],
+ "role": "role",
+ }
+ ],
+ model="model",
+ stream=True,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_create_completion(self, client: Docstrange) -> None:
+ response = client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_create_completion(self, client: Docstrange) -> None:
+ with client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncChat:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "type",
+ }
+ ],
+ "role": "role",
+ }
+ ],
+ model="model",
+ stream=True,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}],
+ "role": "role",
+ }
+ ],
+ model="model",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index 63539df..d40e1fa 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse
+from docstrange.types import ClassifyResponse, BatchClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,6 +17,43 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ classify = client.classify.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.classify.with_raw_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.classify.with_streaming_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -60,6 +97,43 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ classify = await async_client.classify.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.classify.with_raw_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.classify.with_streaming_response.batch(
+ categories="categories",
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index d911970..bd13f30 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,7 +9,10 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
+from docstrange.types import (
+ ExtractResponse,
+ BatchExtractResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,6 +20,163 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_async(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_async(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream_with_all_params(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_raw_response_stream(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = response.parse()
+ stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_streaming_response_stream(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = response.parse()
+ stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -76,6 +236,163 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.async_(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = await response.parse()
+ await stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.stream(
+ file=b"raw file contents",
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = await response.parse()
+ await stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
From 5d5fe8c9980e169a262eeed5601a568b8688a666 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:30:40 +0000
Subject: [PATCH 22/26] feat(api): api update
---
.stats.yml | 6 +-
README.md | 61 ---
api.md | 45 +-
src/docstrange/_client.py | 39 +-
src/docstrange/resources/__init__.py | 14 -
src/docstrange/resources/chat.py | 182 -------
src/docstrange/resources/classify.py | 111 +---
src/docstrange/resources/extract/__init__.py | 14 -
src/docstrange/resources/extract/extract.py | 485 +-----------------
src/docstrange/resources/extract/results.py | 290 -----------
src/docstrange/types/__init__.py | 8 -
.../types/batch_classify_response.py | 13 -
.../types/batch_extract_response.py | 13 -
.../types/chat_create_completion_params.py | 40 --
src/docstrange/types/classify_batch_params.py | 17 -
src/docstrange/types/extract/__init__.py | 4 -
.../types/extract/extraction_list_response.py | 15 -
.../types/extract/result_list_params.py | 17 -
.../types/extract/result_retrieve_params.py | 11 -
src/docstrange/types/extract_async_params.py | 37 --
src/docstrange/types/extract_batch_params.py | 26 -
src/docstrange/types/extract_stream_params.py | 35 --
.../types/extract_stream_response.py | 7 -
src/docstrange/types/extract_sync_params.py | 1 +
tests/api_resources/extract/test_results.py | 205 --------
tests/api_resources/test_chat.py | 171 ------
tests/api_resources/test_classify.py | 76 +--
tests/api_resources/test_extract.py | 319 +-----------
28 files changed, 17 insertions(+), 2245 deletions(-)
delete mode 100644 src/docstrange/resources/chat.py
delete mode 100644 src/docstrange/resources/extract/results.py
delete mode 100644 src/docstrange/types/batch_classify_response.py
delete mode 100644 src/docstrange/types/batch_extract_response.py
delete mode 100644 src/docstrange/types/chat_create_completion_params.py
delete mode 100644 src/docstrange/types/classify_batch_params.py
delete mode 100644 src/docstrange/types/extract/extraction_list_response.py
delete mode 100644 src/docstrange/types/extract/result_list_params.py
delete mode 100644 src/docstrange/types/extract/result_retrieve_params.py
delete mode 100644 src/docstrange/types/extract_async_params.py
delete mode 100644 src/docstrange/types/extract_batch_params.py
delete mode 100644 src/docstrange/types/extract_stream_params.py
delete mode 100644 src/docstrange/types/extract_stream_response.py
delete mode 100644 tests/api_resources/extract/test_results.py
delete mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index 2430e33..f839396 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 9
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-61ca0326580cb90b4bc39c85c49cb2083d14ce9865ea272f2cb84cc7c639b0b2.yml
-openapi_spec_hash: 6940490040b26eeb3c38bb2d7d9f00ce
+configured_endpoints: 2
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-75dd621006675868b0701738226a045f2e9d7211242fece922f06478bef66738.yml
+openapi_spec_hash: 47cb78aa2caa018fe58742fc19b0a49c
config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
diff --git a/README.md b/README.md
index e26fbd2..74c6d8b 100644
--- a/README.md
+++ b/README.md
@@ -115,67 +115,6 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
-## Pagination
-
-List methods in the Docstrange API are paginated.
-
-This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
-
-```python
-from docstrange import Docstrange
-
-client = Docstrange()
-
-all_results = []
-# Automatically fetches more pages as needed.
-for result in client.extract.results.list():
- # Do something with result here
- all_results.append(result)
-print(all_results)
-```
-
-Or, asynchronously:
-
-```python
-import asyncio
-from docstrange import AsyncDocstrange
-
-client = AsyncDocstrange()
-
-
-async def main() -> None:
- all_results = []
- # Iterate through items across all pages, issuing requests as needed.
- async for result in client.extract.results.list():
- all_results.append(result)
- print(all_results)
-
-
-asyncio.run(main())
-```
-
-Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
-
-```python
-first_page = await client.extract.results.list()
-if first_page.has_next_page():
- print(f"will fetch next page using these details: {first_page.next_page_info()}")
- next_page = await first_page.get_next_page()
- print(f"number of items we just fetched: {len(next_page.results)}")
-
-# Remove `await` for non-async usage.
-```
-
-Or just work directly with the returned data:
-
-```python
-first_page = await client.extract.results.list()
-for result in first_page.results:
- print(result)
-
-# Remove `await` for non-async usage.
-```
-
## File uploads
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)`.
diff --git a/api.md b/api.md
index 790cf4e..96e2318 100644
--- a/api.md
+++ b/api.md
@@ -3,62 +3,21 @@
Types:
```python
-from docstrange.types import (
- BatchExtractRequestBody,
- BatchExtractResponse,
- ExtractRequestBody,
- ExtractResponse,
- StreamExtractRequestBody,
- ExtractStreamResponse,
-)
+from docstrange.types import ExtractRequestBody, ExtractResponse
```
Methods:
-- client.extract.async\_(\*\*params) -> ExtractResponse
-- client.extract.batch(\*\*params) -> BatchExtractResponse
-- client.extract.stream(\*\*params) -> str
- client.extract.sync(\*\*params) -> ExtractResponse
-## Results
-
-Types:
-
-```python
-from docstrange.types.extract import ExtractionListResponse
-```
-
-Methods:
-
-- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
-- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[object]
-
# Classify
Types:
```python
-from docstrange.types import (
- BatchClassifyRequestBody,
- BatchClassifyResponse,
- ClassifyRequestBody,
- ClassifyResponse,
-)
+from docstrange.types import ClassifyRequestBody, ClassifyResponse
```
Methods:
-- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
-
-# Chat
-
-Types:
-
-```python
-from docstrange.types import ChatCompletionsRequest
-```
-
-Methods:
-
-- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 4c5bcc4..271a014 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,8 +31,7 @@
)
if TYPE_CHECKING:
- from .resources import chat, extract, classify
- from .resources.chat import ChatResource, AsyncChatResource
+ from .resources import extract, classify
from .resources.classify import ClassifyResource, AsyncClassifyResource
from .resources.extract.extract import ExtractResource, AsyncExtractResource
@@ -115,12 +114,6 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
- @cached_property
- def chat(self) -> ChatResource:
- from .resources.chat import ChatResource
-
- return ChatResource(self)
-
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -301,12 +294,6 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
- @cached_property
- def chat(self) -> AsyncChatResource:
- from .resources.chat import AsyncChatResource
-
- return AsyncChatResource(self)
-
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -438,12 +425,6 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithRawResponse:
- from .resources.chat import ChatResourceWithRawResponse
-
- return ChatResourceWithRawResponse(self._client.chat)
-
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -463,12 +444,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithRawResponse:
- from .resources.chat import AsyncChatResourceWithRawResponse
-
- return AsyncChatResourceWithRawResponse(self._client.chat)
-
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -488,12 +463,6 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.ChatResourceWithStreamingResponse:
- from .resources.chat import ChatResourceWithStreamingResponse
-
- return ChatResourceWithStreamingResponse(self._client.chat)
-
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -513,12 +482,6 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
- @cached_property
- def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
- from .resources.chat import AsyncChatResourceWithStreamingResponse
-
- return AsyncChatResourceWithStreamingResponse(self._client.chat)
-
Client = Docstrange
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index a3172dd..6d7ff55 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,13 +1,5 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from .chat import (
- ChatResource,
- AsyncChatResource,
- ChatResourceWithRawResponse,
- AsyncChatResourceWithRawResponse,
- ChatResourceWithStreamingResponse,
- AsyncChatResourceWithStreamingResponse,
-)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -38,10 +30,4 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
- "ChatResource",
- "AsyncChatResource",
- "ChatResourceWithRawResponse",
- "AsyncChatResourceWithRawResponse",
- "ChatResourceWithStreamingResponse",
- "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
deleted file mode 100644
index 7e8899d..0000000
--- a/src/docstrange/resources/chat.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-
-import httpx
-
-from ..types import chat_create_completion_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
-from .._compat import cached_property
-from .._resource import SyncAPIResource, AsyncAPIResource
-from .._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from .._base_client import make_request_options
-
-__all__ = ["ChatResource", "AsyncChatResource"]
-
-
-class ChatResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ChatResourceWithStreamingResponse(self)
-
- def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- OpenAI-compatible chat completions endpoint.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._post(
- "/v1/chat/completions",
- body=maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class AsyncChatResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncChatResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncChatResourceWithStreamingResponse(self)
-
- async def create_completion(
- self,
- *,
- messages: Iterable[chat_create_completion_params.Message],
- model: str,
- stream: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> object:
- """
- OpenAI-compatible chat completions endpoint.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return await self._post(
- "/v1/chat/completions",
- body=await async_maybe_transform(
- {
- "messages": messages,
- "model": model,
- "stream": stream,
- },
- chat_create_completion_params.ChatCreateCompletionParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=object,
- )
-
-
-class ChatResourceWithRawResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithRawResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_raw_response_wrapper(
- chat.create_completion,
- )
-
-
-class ChatResourceWithStreamingResponse:
- def __init__(self, chat: ChatResource) -> None:
- self._chat = chat
-
- self.create_completion = to_streamed_response_wrapper(
- chat.create_completion,
- )
-
-
-class AsyncChatResourceWithStreamingResponse:
- def __init__(self, chat: AsyncChatResource) -> None:
- self._chat = chat
-
- self.create_completion = async_to_streamed_response_wrapper(
- chat.create_completion,
- )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index ded77af..382aa89 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -4,8 +4,8 @@
import httpx
-from ..types import classify_sync_params, classify_batch_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
+from ..types import classify_sync_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -17,7 +17,6 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
-from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -42,53 +41,6 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
- def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50).
-
- Args:
- categories: JSON array of category objects
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/classify/batch",
- body=maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
def sync(
self,
*,
@@ -157,53 +109,6 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
- async def batch(
- self,
- *,
- categories: str,
- files: SequenceNotStr[FileTypes],
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchClassifyResponse:
- """
- Classify multiple documents asynchronously (max 50).
-
- Args:
- categories: JSON array of category objects
-
- files: Files to classify (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/classify/batch",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "files": files,
- },
- classify_batch_params.ClassifyBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchClassifyResponse,
- )
-
async def sync(
self,
*,
@@ -256,9 +161,6 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_raw_response_wrapper(
- classify.batch,
- )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -268,9 +170,6 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_raw_response_wrapper(
- classify.batch,
- )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -280,9 +179,6 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
- self.batch = to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -292,9 +188,6 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
- self.batch = async_to_streamed_response_wrapper(
- classify.batch,
- )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
index 22cd257..a0fee27 100644
--- a/src/docstrange/resources/extract/__init__.py
+++ b/src/docstrange/resources/extract/__init__.py
@@ -8,22 +8,8 @@
ExtractResourceWithStreamingResponse,
AsyncExtractResourceWithStreamingResponse,
)
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
__all__ = [
- "ResultsResource",
- "AsyncResultsResource",
- "ResultsResourceWithRawResponse",
- "AsyncResultsResourceWithRawResponse",
- "ResultsResourceWithStreamingResponse",
- "AsyncResultsResourceWithStreamingResponse",
"ExtractResource",
"AsyncExtractResource",
"ExtractResourceWithRawResponse",
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
index 335f013..f5b48d9 100644
--- a/src/docstrange/resources/extract/extract.py
+++ b/src/docstrange/resources/extract/extract.py
@@ -6,26 +6,8 @@
import httpx
-from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
-from .results import (
- ResultsResource,
- AsyncResultsResource,
- ResultsResourceWithRawResponse,
- AsyncResultsResourceWithRawResponse,
- ResultsResourceWithStreamingResponse,
- AsyncResultsResourceWithStreamingResponse,
-)
-from ..._types import (
- Body,
- Omit,
- Query,
- Headers,
- NotGiven,
- FileTypes,
- SequenceNotStr,
- omit,
- not_given,
-)
+from ...types import extract_sync_params
+from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
@@ -35,20 +17,13 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ..._streaming import Stream, AsyncStream
from ..._base_client import make_request_options
from ...types.extract_response import ExtractResponse
-from ...types.batch_extract_response import BatchExtractResponse
-from ...types.extract_stream_response import ExtractStreamResponse
__all__ = ["ExtractResource", "AsyncExtractResource"]
class ExtractResource(SyncAPIResource):
- @cached_property
- def results(self) -> ResultsResource:
- return ResultsResource(self._client)
-
@cached_property
def with_raw_response(self) -> ExtractResourceWithRawResponse:
"""
@@ -68,204 +43,6 @@ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
"""
return ExtractResourceWithStreamingResponse(self)
- def async_(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Queue a document for background processing.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/async",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """
- Process multiple files asynchronously (max 50).
-
- Args:
- files: Files to process (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/batch",
- body=maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
- )
-
- def stream(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Stream[ExtractStreamResponse]:
- """
- Stream extraction results via SSE.
-
- Args:
- file: File to upload
-
- output_format: Output format(s)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- "/api/v1/extract/stream",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=Stream[ExtractStreamResponse],
- )
-
def sync(
self,
*,
@@ -305,6 +82,8 @@ def sync(
json_options: JSON extraction options
+ prompt_mode: append or replace
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -341,10 +120,6 @@ def sync(
class AsyncExtractResource(AsyncAPIResource):
- @cached_property
- def results(self) -> AsyncResultsResource:
- return AsyncResultsResource(self._client)
-
@cached_property
def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
"""
@@ -364,204 +139,6 @@ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
"""
return AsyncExtractResourceWithStreamingResponse(self)
- async def async_(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Queue a document for background processing.
-
- Args:
- file: File to upload (PDF, Word, Excel, PowerPoint, images)
-
- output_format: Output format(s): markdown, html, json, csv.
-
- csv_options: CSV extraction options
-
- custom_instructions: Custom extraction instructions
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- include_metadata: Comma-separated metadata types
-
- json_options: JSON extraction options
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/async",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_async_params.ExtractAsyncParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExtractResponse,
- )
-
- async def batch(
- self,
- *,
- files: SequenceNotStr[FileTypes],
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> BatchExtractResponse:
- """
- Process multiple files asynchronously (max 50).
-
- Args:
- files: Files to process (max 50)
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/batch",
- body=await async_maybe_transform(
- {
- "files": files,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_batch_params.ExtractBatchParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BatchExtractResponse,
- )
-
- async def stream(
- self,
- *,
- file: FileTypes,
- output_format: str,
- csv_options: str | Omit = omit,
- custom_instructions: str | Omit = omit,
- enable_streaming: bool | Omit = omit,
- file_base64: str | Omit = omit,
- file_url: str | Omit = omit,
- include_metadata: str | Omit = omit,
- json_options: str | Omit = omit,
- prompt_mode: Literal["append", "replace"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncStream[ExtractStreamResponse]:
- """
- Stream extraction results via SSE.
-
- Args:
- file: File to upload
-
- output_format: Output format(s)
-
- file_base64: Base64-encoded file content
-
- file_url: URL to download file from
-
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- "/api/v1/extract/stream",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "enable_streaming": enable_streaming,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_stream_params.ExtractStreamParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=str,
- stream=True,
- stream_cls=AsyncStream[ExtractStreamResponse],
- )
-
async def sync(
self,
*,
@@ -601,6 +178,8 @@ async def sync(
json_options: JSON extraction options
+ prompt_mode: append or replace
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -640,85 +219,33 @@ class ExtractResourceWithRawResponse:
def __init__(self, extract: ExtractResource) -> None:
self._extract = extract
- self.async_ = to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = to_raw_response_wrapper(
- extract.stream,
- )
self.sync = to_raw_response_wrapper(
extract.sync,
)
- @cached_property
- def results(self) -> ResultsResourceWithRawResponse:
- return ResultsResourceWithRawResponse(self._extract.results)
-
class AsyncExtractResourceWithRawResponse:
def __init__(self, extract: AsyncExtractResource) -> None:
self._extract = extract
- self.async_ = async_to_raw_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_raw_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_raw_response_wrapper(
- extract.stream,
- )
self.sync = async_to_raw_response_wrapper(
extract.sync,
)
- @cached_property
- def results(self) -> AsyncResultsResourceWithRawResponse:
- return AsyncResultsResourceWithRawResponse(self._extract.results)
-
class ExtractResourceWithStreamingResponse:
def __init__(self, extract: ExtractResource) -> None:
self._extract = extract
- self.async_ = to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = to_streamed_response_wrapper(
- extract.stream,
- )
self.sync = to_streamed_response_wrapper(
extract.sync,
)
- @cached_property
- def results(self) -> ResultsResourceWithStreamingResponse:
- return ResultsResourceWithStreamingResponse(self._extract.results)
-
class AsyncExtractResourceWithStreamingResponse:
def __init__(self, extract: AsyncExtractResource) -> None:
self._extract = extract
- self.async_ = async_to_streamed_response_wrapper(
- extract.async_,
- )
- self.batch = async_to_streamed_response_wrapper(
- extract.batch,
- )
- self.stream = async_to_streamed_response_wrapper(
- extract.stream,
- )
self.sync = async_to_streamed_response_wrapper(
extract.sync,
)
-
- @cached_property
- def results(self) -> AsyncResultsResourceWithStreamingResponse:
- return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
deleted file mode 100644
index dab80bf..0000000
--- a/src/docstrange/resources/extract/results.py
+++ /dev/null
@@ -1,290 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-import httpx
-
-from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
-from ..._response import (
- to_raw_response_wrapper,
- to_streamed_response_wrapper,
- async_to_raw_response_wrapper,
- async_to_streamed_response_wrapper,
-)
-from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-from ..._base_client import AsyncPaginator, make_request_options
-from ...types.extract import result_list_params, result_retrieve_params
-from ...types.extract_response import ExtractResponse
-
-__all__ = ["ResultsResource", "AsyncResultsResource"]
-
-
-class ResultsResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> ResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return ResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return ResultsResourceWithStreamingResponse(self)
-
- def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> SyncPageNumberPagination[object]:
- """
- List all extraction jobs (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=SyncPageNumberPagination[object],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=object,
- )
-
-
-class AsyncResultsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
- """
- This property can be used as a prefix for any HTTP method call to return
- the raw response object instead of the parsed content.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
- """
- return AsyncResultsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
- """
- An alternative to `.with_raw_response` that doesn't eagerly read the response body.
-
- For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
- """
- return AsyncResultsResourceWithStreamingResponse(self)
-
- async def retrieve(
- self,
- record_id: str,
- *,
- include_content: bool | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExtractResponse:
- """
- Retrieve status and result of an extraction job.
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- if not record_id:
- raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
- return await self._get(
- f"/api/v1/extract/results/{record_id}",
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
- ),
- ),
- cast_to=ExtractResponse,
- )
-
- def list(
- self,
- *,
- page: int | Omit = omit,
- page_size: int | Omit = omit,
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
- | Omit = omit,
- sort_order: Literal["asc", "desc"] | Omit = omit,
- # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
- # The extra values given here take precedence over values defined on the client or passed to this method.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncPaginator[object, AsyncPageNumberPagination[object]]:
- """
- List all extraction jobs (paginated).
-
- Args:
- extra_headers: Send extra headers
-
- extra_query: Add additional query parameters to the request
-
- extra_body: Add additional JSON properties to the request
-
- timeout: Override the client-level default timeout for this request, in seconds
- """
- return self._get_api_list(
- "/api/v1/extract/results",
- page=AsyncPageNumberPagination[object],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "page": page,
- "page_size": page_size,
- "sort_by": sort_by,
- "sort_order": sort_order,
- },
- result_list_params.ResultListParams,
- ),
- ),
- model=object,
- )
-
-
-class ResultsResourceWithRawResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = to_raw_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithRawResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_raw_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_raw_response_wrapper(
- results.list,
- )
-
-
-class ResultsResourceWithStreamingResponse:
- def __init__(self, results: ResultsResource) -> None:
- self._results = results
-
- self.retrieve = to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = to_streamed_response_wrapper(
- results.list,
- )
-
-
-class AsyncResultsResourceWithStreamingResponse:
- def __init__(self, results: AsyncResultsResource) -> None:
- self._results = results
-
- self.retrieve = async_to_streamed_response_wrapper(
- results.retrieve,
- )
- self.list = async_to_streamed_response_wrapper(
- results.list,
- )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index f7946ad..fac3955 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -6,11 +6,3 @@
from .classify_response import ClassifyResponse as ClassifyResponse
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
-from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
-from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
-from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
-from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
-from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
-from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
-from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
-from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
deleted file mode 100644
index 7b26938..0000000
--- a/src/docstrange/types/batch_classify_response.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .._models import BaseModel
-
-__all__ = ["BatchClassifyResponse"]
-
-
-class BatchClassifyResponse(BaseModel):
- batch_id: str
-
- message: str
-
- success: bool
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
deleted file mode 100644
index 64b21bf..0000000
--- a/src/docstrange/types/batch_extract_response.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .._models import BaseModel
-
-__all__ = ["BatchExtractResponse"]
-
-
-class BatchExtractResponse(BaseModel):
- batch_id: str
-
- message: str
-
- success: bool
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
deleted file mode 100644
index eea9be6..0000000
--- a/src/docstrange/types/chat_create_completion_params.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import Iterable
-from typing_extensions import Required, TypedDict
-
-__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
-
-
-class ChatCreateCompletionParams(TypedDict, total=False):
- messages: Required[Iterable[Message]]
-
- model: Required[str]
-
- stream: bool
-
-
-class MessageContentFileURL(TypedDict, total=False):
- url: str
-
-
-class MessageContentImageURL(TypedDict, total=False):
- url: str
-
-
-class MessageContent(TypedDict, total=False):
- file_url: MessageContentFileURL
-
- image_url: MessageContentImageURL
-
- text: str
-
- type: str
-
-
-class Message(TypedDict, total=False):
- content: Required[Iterable[MessageContent]]
-
- role: Required[str]
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
deleted file mode 100644
index 1f23cd0..0000000
--- a/src/docstrange/types/classify_batch_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ClassifyBatchParams"]
-
-
-class ClassifyBatchParams(TypedDict, total=False):
- categories: Required[str]
- """JSON array of category objects"""
-
- files: Required[SequenceNotStr[FileTypes]]
- """Files to classify (max 50)"""
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
index 692c8de..f8ee8b1 100644
--- a/src/docstrange/types/extract/__init__.py
+++ b/src/docstrange/types/extract/__init__.py
@@ -1,7 +1,3 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from __future__ import annotations
-
-from .result_list_params import ResultListParams as ResultListParams
-from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
-from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
deleted file mode 100644
index 60f049a..0000000
--- a/src/docstrange/types/extract/extraction_list_response.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from ..._models import BaseModel
-
-__all__ = ["ExtractionListResponse"]
-
-
-class ExtractionListResponse(BaseModel):
- pagination: object
-
- results: List[object]
-
- success: bool
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
deleted file mode 100644
index 7dfe38a..0000000
--- a/src/docstrange/types/extract/result_list_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypedDict
-
-__all__ = ["ResultListParams"]
-
-
-class ResultListParams(TypedDict, total=False):
- page: int
-
- page_size: int
-
- sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
-
- sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
deleted file mode 100644
index 1de1a80..0000000
--- a/src/docstrange/types/extract/result_retrieve_params.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import TypedDict
-
-__all__ = ["ResultRetrieveParams"]
-
-
-class ResultRetrieveParams(TypedDict, total=False):
- include_content: bool
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
deleted file mode 100644
index 2895923..0000000
--- a/src/docstrange/types/extract_async_params.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractAsyncParams"]
-
-
-class ExtractAsyncParams(TypedDict, total=False):
- file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
- output_format: Required[str]
- """Output format(s): markdown, html, json, csv."""
-
- csv_options: str
- """CSV extraction options"""
-
- custom_instructions: str
- """Custom extraction instructions"""
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
- """Comma-separated metadata types"""
-
- json_options: str
- """JSON extraction options"""
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
deleted file mode 100644
index 380d386..0000000
--- a/src/docstrange/types/extract_batch_params.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes, SequenceNotStr
-
-__all__ = ["ExtractBatchParams"]
-
-
-class ExtractBatchParams(TypedDict, total=False):
- files: Required[SequenceNotStr[FileTypes]]
- """Files to process (max 50)"""
-
- output_format: Required[str]
-
- csv_options: str
-
- custom_instructions: str
-
- include_metadata: str
-
- json_options: str
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
deleted file mode 100644
index 52147de..0000000
--- a/src/docstrange/types/extract_stream_params.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ExtractStreamParams"]
-
-
-class ExtractStreamParams(TypedDict, total=False):
- file: Required[FileTypes]
- """File to upload"""
-
- output_format: Required[str]
- """Output format(s)"""
-
- csv_options: str
-
- custom_instructions: str
-
- enable_streaming: bool
-
- file_base64: str
- """Base64-encoded file content"""
-
- file_url: str
- """URL to download file from"""
-
- include_metadata: str
-
- json_options: str
-
- prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
deleted file mode 100644
index 333ff97..0000000
--- a/src/docstrange/types/extract_stream_response.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import TypeAlias
-
-__all__ = ["ExtractStreamResponse"]
-
-ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 3208694..1f032ea 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -35,3 +35,4 @@ class ExtractSyncParams(TypedDict, total=False):
"""JSON extraction options"""
prompt_mode: Literal["append", "replace"]
+ """append or replace"""
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
deleted file mode 100644
index 0b67e0f..0000000
--- a/tests/api_resources/extract/test_results.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
-from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestResults:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_retrieve(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_retrieve(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_path_params_retrieve(self, client: Docstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list(self, client: Docstrange) -> None:
- result = client.extract.results.list()
- assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_list_with_all_params(self, client: Docstrange) -> None:
- result = client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Docstrange) -> None:
- response = client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Docstrange) -> None:
- with client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = response.parse()
- assert_matches_type(SyncPageNumberPagination[object], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncResults:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.retrieve(
- record_id="record_id",
- include_content=True,
- )
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.retrieve(
- record_id="record_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.retrieve(
- record_id="record_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(ExtractResponse, result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
- await async_client.extract.results.with_raw_response.retrieve(
- record_id="",
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list()
- assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
- result = await async_client.extract.results.list(
- page=1,
- page_size=1,
- sort_by="created_at",
- sort_order="asc",
- )
- assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.results.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.results.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- result = await response.parse()
- assert_matches_type(AsyncPageNumberPagination[object], result, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
deleted file mode 100644
index 84bfced..0000000
--- a/tests/api_resources/test_chat.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import os
-from typing import Any, cast
-
-import pytest
-
-from docstrange import Docstrange, AsyncDocstrange
-from tests.utils import assert_matches_type
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestChat:
- parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
- chat = client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "type",
- }
- ],
- "role": "role",
- }
- ],
- model="model",
- stream=True,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_create_completion(self, client: Docstrange) -> None:
- response = client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_create_completion(self, client: Docstrange) -> None:
- with client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
-
-class TestAsyncChat:
- parametrize = pytest.mark.parametrize(
- "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
- )
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
- chat = await async_client.chat.create_completion(
- messages=[
- {
- "content": [
- {
- "file_url": {"url": "url"},
- "image_url": {"url": "url"},
- "text": "text",
- "type": "type",
- }
- ],
- "role": "role",
- }
- ],
- model="model",
- stream=True,
- )
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.chat.with_raw_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
- async with async_client.chat.with_streaming_response.create_completion(
- messages=[
- {
- "content": [{}],
- "role": "role",
- }
- ],
- model="model",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = await response.parse()
- assert_matches_type(object, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index d40e1fa..63539df 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse, BatchClassifyResponse
+from docstrange.types import ClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,43 +17,6 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- classify = client.classify.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.classify.with_raw_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.classify.with_streaming_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -97,43 +60,6 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- classify = await async_client.classify.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.classify.with_raw_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.classify.with_streaming_response.batch(
- categories="categories",
- files=[b"raw file contents"],
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- classify = await response.parse()
- assert_matches_type(BatchClassifyResponse, classify, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index bd13f30..d911970 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,10 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import (
- ExtractResponse,
- BatchExtractResponse,
-)
+from docstrange.types import ExtractResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -20,163 +17,6 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_async_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_async(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_async(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_method_batch_with_all_params(self, client: Docstrange) -> None:
- extract = client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_raw_response_batch(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- def test_streaming_response_batch(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_method_stream_with_all_params(self, client: Docstrange) -> None:
- extract_stream = client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- enable_streaming=True,
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- extract_stream.response.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_raw_response_stream(self, client: Docstrange) -> None:
- response = client.extract.with_raw_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = response.parse()
- stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- def test_streaming_response_stream(self, client: Docstrange) -> None:
- with client.extract.with_streaming_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = response.parse()
- stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
@@ -236,163 +76,6 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.async_(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.async_(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(ExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract = await async_client.extract.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- csv_options="csv_options",
- custom_instructions="custom_instructions",
- include_metadata="include_metadata",
- json_options="json_options",
- prompt_mode="append",
- )
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- @pytest.mark.skip(reason="Prism tests are disabled")
- @parametrize
- async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.batch(
- files=[b"raw file contents"],
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- extract = await response.parse()
- assert_matches_type(BatchExtractResponse, extract, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
- extract_stream = await async_client.extract.stream(
- file=b"raw file contents",
- output_format="markdown",
- csv_options="",
- custom_instructions="",
- enable_streaming=True,
- file_base64="",
- file_url="",
- include_metadata="",
- json_options="",
- prompt_mode="append",
- )
- await extract_stream.response.aclose()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
- response = await async_client.extract.with_raw_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- )
-
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- stream = await response.parse()
- await stream.close()
-
- @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
- @parametrize
- async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
- async with async_client.extract.with_streaming_response.stream(
- file=b"raw file contents",
- output_format="markdown",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- stream = await response.parse()
- await stream.close()
-
- assert cast(Any, response.is_closed) is True
-
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
From b03ae9b0d7d5940df2aaff8b4cfa22c163a31b6b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:32:27 +0000
Subject: [PATCH 23/26] feat(api): api update
---
.stats.yml | 8 +-
README.md | 71 +-
api.md | 45 +-
src/docstrange/_client.py | 39 +-
src/docstrange/resources/__init__.py | 14 +
src/docstrange/resources/chat.py | 218 ++++++
src/docstrange/resources/classify.py | 179 ++++-
src/docstrange/resources/extract/__init__.py | 14 +
src/docstrange/resources/extract/extract.py | 670 ++++++++++++++++--
src/docstrange/resources/extract/results.py | 294 ++++++++
src/docstrange/types/__init__.py | 13 +
.../types/batch_classify_response.py | 24 +
.../types/batch_extract_response.py | 24 +
.../types/chat_create_completion_params.py | 45 ++
src/docstrange/types/classify_batch_params.py | 17 +
src/docstrange/types/classify_response.py | 5 +
src/docstrange/types/classify_sync_params.py | 7 +-
src/docstrange/types/extract/__init__.py | 5 +
.../types/extract/extraction_list_response.py | 17 +
.../types/extract/pagination_info.py | 21 +
.../types/extract/result_list_params.py | 17 +
.../types/extract/result_retrieve_params.py | 12 +
src/docstrange/types/extract_async_params.py | 45 ++
src/docstrange/types/extract_batch_params.py | 27 +
src/docstrange/types/extract_response.py | 25 +-
src/docstrange/types/extract_stream_params.py | 47 ++
.../types/extract_stream_response.py | 7 +
src/docstrange/types/extract_sync_params.py | 25 +-
.../types/extraction_format_result.py | 15 +
src/docstrange/types/extraction_metadata.py | 15 +
src/docstrange/types/extraction_result.py | 22 +
.../types/file_classification_result.py | 24 +
src/docstrange/types/page_classification.py | 27 +
tests/api_resources/extract/test_results.py | 205 ++++++
tests/api_resources/test_chat.py | 183 +++++
tests/api_resources/test_classify.py | 88 ++-
tests/api_resources/test_extract.py | 317 ++++++++-
tests/test_client.py | 24 +-
38 files changed, 2728 insertions(+), 127 deletions(-)
create mode 100644 src/docstrange/resources/chat.py
create mode 100644 src/docstrange/resources/extract/results.py
create mode 100644 src/docstrange/types/batch_classify_response.py
create mode 100644 src/docstrange/types/batch_extract_response.py
create mode 100644 src/docstrange/types/chat_create_completion_params.py
create mode 100644 src/docstrange/types/classify_batch_params.py
create mode 100644 src/docstrange/types/extract/extraction_list_response.py
create mode 100644 src/docstrange/types/extract/pagination_info.py
create mode 100644 src/docstrange/types/extract/result_list_params.py
create mode 100644 src/docstrange/types/extract/result_retrieve_params.py
create mode 100644 src/docstrange/types/extract_async_params.py
create mode 100644 src/docstrange/types/extract_batch_params.py
create mode 100644 src/docstrange/types/extract_stream_params.py
create mode 100644 src/docstrange/types/extract_stream_response.py
create mode 100644 src/docstrange/types/extraction_format_result.py
create mode 100644 src/docstrange/types/extraction_metadata.py
create mode 100644 src/docstrange/types/extraction_result.py
create mode 100644 src/docstrange/types/file_classification_result.py
create mode 100644 src/docstrange/types/page_classification.py
create mode 100644 tests/api_resources/extract/test_results.py
create mode 100644 tests/api_resources/test_chat.py
diff --git a/.stats.yml b/.stats.yml
index f839396..6864372 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 2
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-75dd621006675868b0701738226a045f2e9d7211242fece922f06478bef66738.yml
-openapi_spec_hash: 47cb78aa2caa018fe58742fc19b0a49c
-config_hash: aed0d6cc8b4cffa1f02021baec0a6da3
+configured_endpoints: 9
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
+openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
+config_hash: 1804754b97b5ccf95ad31183c74527bc
diff --git a/README.md b/README.md
index 74c6d8b..917f116 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,6 @@ client = Docstrange(
)
extract_response = client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
print(extract_response.record_id)
@@ -60,7 +59,6 @@ client = AsyncDocstrange(
async def main() -> None:
extract_response = await client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
print(extract_response.record_id)
@@ -97,7 +95,6 @@ async def main() -> None:
http_client=DefaultAioHttpClient(),
) as client:
extract_response = await client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
print(extract_response.record_id)
@@ -115,6 +112,67 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ
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`.
+## Pagination
+
+List methods in the Docstrange API are paginated.
+
+This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:
+
+```python
+from docstrange import Docstrange
+
+client = Docstrange()
+
+all_results = []
+# Automatically fetches more pages as needed.
+for result in client.extract.results.list():
+ # Do something with result here
+ all_results.append(result)
+print(all_results)
+```
+
+Or, asynchronously:
+
+```python
+import asyncio
+from docstrange import AsyncDocstrange
+
+client = AsyncDocstrange()
+
+
+async def main() -> None:
+ all_results = []
+ # Iterate through items across all pages, issuing requests as needed.
+ async for result in client.extract.results.list():
+ all_results.append(result)
+ print(all_results)
+
+
+asyncio.run(main())
+```
+
+Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
+
+```python
+first_page = await client.extract.results.list()
+if first_page.has_next_page():
+ print(f"will fetch next page using these details: {first_page.next_page_info()}")
+ next_page = await first_page.get_next_page()
+ print(f"number of items we just fetched: {len(next_page.results)}")
+
+# Remove `await` for non-async usage.
+```
+
+Or just work directly with the returned data:
+
+```python
+first_page = await client.extract.results.list()
+for result in first_page.results:
+ print(result.record_id)
+
+# Remove `await` for non-async usage.
+```
+
## File uploads
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)`.
@@ -126,8 +184,8 @@ from docstrange import Docstrange
client = Docstrange()
client.extract.sync(
- file=Path("/path/to/file"),
output_format="markdown",
+ file=Path("/path/to/file"),
)
```
@@ -150,7 +208,6 @@ client = Docstrange()
try:
client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
except docstrange.APIConnectionError as e:
@@ -196,7 +253,6 @@ client = Docstrange(
# Or, configure per-request:
client.with_options(max_retries=5).extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
```
@@ -222,7 +278,6 @@ client = Docstrange(
# Override per-request:
client.with_options(timeout=5.0).extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
```
@@ -266,7 +321,6 @@ from docstrange import Docstrange
client = Docstrange()
response = client.extract.with_raw_response.sync(
- file=b"raw file contents",
output_format="markdown",
)
print(response.headers.get('X-My-Header'))
@@ -287,7 +341,6 @@ To stream the response body, use `.with_streaming_response` instead, which requi
```python
with client.extract.with_streaming_response.sync(
- file=b"raw file contents",
output_format="markdown",
) as response:
print(response.headers.get("X-My-Header"))
diff --git a/api.md b/api.md
index 96e2318..df1bce4 100644
--- a/api.md
+++ b/api.md
@@ -3,21 +3,62 @@
Types:
```python
-from docstrange.types import ExtractRequestBody, ExtractResponse
+from docstrange.types import (
+ BatchExtractResponse,
+ ExtractResponse,
+ ExtractionFormatResult,
+ ExtractionMetadata,
+ ExtractionResult,
+ ExtractStreamResponse,
+)
```
Methods:
+- client.extract.async\_(\*\*params) -> ExtractResponse
+- client.extract.batch(\*\*params) -> BatchExtractResponse
+- client.extract.stream(\*\*params) -> str
- client.extract.sync(\*\*params) -> ExtractResponse
+## Results
+
+Types:
+
+```python
+from docstrange.types.extract import ExtractionListResponse, PaginationInfo
+```
+
+Methods:
+
+- client.extract.results.retrieve(record_id, \*\*params) -> ExtractResponse
+- client.extract.results.list(\*\*params) -> SyncPageNumberPagination[ExtractResponse]
+
# Classify
Types:
```python
-from docstrange.types import ClassifyRequestBody, ClassifyResponse
+from docstrange.types import (
+ BatchClassifyResponse,
+ ClassifyResponse,
+ FileClassificationResult,
+ PageClassification,
+)
```
Methods:
+- client.classify.batch(\*\*params) -> BatchClassifyResponse
- client.classify.sync(\*\*params) -> ClassifyResponse
+
+# Chat
+
+Types:
+
+```python
+from docstrange.types import ChatCompletionsRequest
+```
+
+Methods:
+
+- client.chat.create_completion(\*\*params) -> object
diff --git a/src/docstrange/_client.py b/src/docstrange/_client.py
index 271a014..4c5bcc4 100644
--- a/src/docstrange/_client.py
+++ b/src/docstrange/_client.py
@@ -31,7 +31,8 @@
)
if TYPE_CHECKING:
- from .resources import extract, classify
+ from .resources import chat, extract, classify
+ from .resources.chat import ChatResource, AsyncChatResource
from .resources.classify import ClassifyResource, AsyncClassifyResource
from .resources.extract.extract import ExtractResource, AsyncExtractResource
@@ -114,6 +115,12 @@ def classify(self) -> ClassifyResource:
return ClassifyResource(self)
+ @cached_property
+ def chat(self) -> ChatResource:
+ from .resources.chat import ChatResource
+
+ return ChatResource(self)
+
@cached_property
def with_raw_response(self) -> DocstrangeWithRawResponse:
return DocstrangeWithRawResponse(self)
@@ -294,6 +301,12 @@ def classify(self) -> AsyncClassifyResource:
return AsyncClassifyResource(self)
+ @cached_property
+ def chat(self) -> AsyncChatResource:
+ from .resources.chat import AsyncChatResource
+
+ return AsyncChatResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncDocstrangeWithRawResponse:
return AsyncDocstrangeWithRawResponse(self)
@@ -425,6 +438,12 @@ def classify(self) -> classify.ClassifyResourceWithRawResponse:
return ClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithRawResponse:
+ from .resources.chat import ChatResourceWithRawResponse
+
+ return ChatResourceWithRawResponse(self._client.chat)
+
class AsyncDocstrangeWithRawResponse:
_client: AsyncDocstrange
@@ -444,6 +463,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithRawResponse:
return AsyncClassifyResourceWithRawResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithRawResponse:
+ from .resources.chat import AsyncChatResourceWithRawResponse
+
+ return AsyncChatResourceWithRawResponse(self._client.chat)
+
class DocstrangeWithStreamedResponse:
_client: Docstrange
@@ -463,6 +488,12 @@ def classify(self) -> classify.ClassifyResourceWithStreamingResponse:
return ClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.ChatResourceWithStreamingResponse:
+ from .resources.chat import ChatResourceWithStreamingResponse
+
+ return ChatResourceWithStreamingResponse(self._client.chat)
+
class AsyncDocstrangeWithStreamedResponse:
_client: AsyncDocstrange
@@ -482,6 +513,12 @@ def classify(self) -> classify.AsyncClassifyResourceWithStreamingResponse:
return AsyncClassifyResourceWithStreamingResponse(self._client.classify)
+ @cached_property
+ def chat(self) -> chat.AsyncChatResourceWithStreamingResponse:
+ from .resources.chat import AsyncChatResourceWithStreamingResponse
+
+ return AsyncChatResourceWithStreamingResponse(self._client.chat)
+
Client = Docstrange
diff --git a/src/docstrange/resources/__init__.py b/src/docstrange/resources/__init__.py
index 6d7ff55..a3172dd 100644
--- a/src/docstrange/resources/__init__.py
+++ b/src/docstrange/resources/__init__.py
@@ -1,5 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .chat import (
+ ChatResource,
+ AsyncChatResource,
+ ChatResourceWithRawResponse,
+ AsyncChatResourceWithRawResponse,
+ ChatResourceWithStreamingResponse,
+ AsyncChatResourceWithStreamingResponse,
+)
from .extract import (
ExtractResource,
AsyncExtractResource,
@@ -30,4 +38,10 @@
"AsyncClassifyResourceWithRawResponse",
"ClassifyResourceWithStreamingResponse",
"AsyncClassifyResourceWithStreamingResponse",
+ "ChatResource",
+ "AsyncChatResource",
+ "ChatResourceWithRawResponse",
+ "AsyncChatResourceWithRawResponse",
+ "ChatResourceWithStreamingResponse",
+ "AsyncChatResourceWithStreamingResponse",
]
diff --git a/src/docstrange/resources/chat.py b/src/docstrange/resources/chat.py
new file mode 100644
index 0000000..0a892c1
--- /dev/null
+++ b/src/docstrange/resources/chat.py
@@ -0,0 +1,218 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+
+import httpx
+
+from ..types import chat_create_completion_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+
+__all__ = ["ChatResource", "AsyncChatResource"]
+
+
+class ChatResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ChatResourceWithStreamingResponse(self)
+
+ def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """OpenAI-compatible chat completions endpoint.
+
+ Supports text messages and
+ file/image inputs via `image_url` or `file_url` parts.
+
+ **Limits and behavior:**
+
+ - The backend enforces a model context limit of ~20,000 tokens (text +
+ multimodal tokens).
+ - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
+ and embedded as data URLs.
+ - Inline data URLs are limited to ~64MB decoded size per item.
+
+ For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
+
+ Args:
+ messages: Chat messages array
+
+ model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
+
+ stream: Enable SSE streaming
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._post(
+ "/v1/chat/completions",
+ body=maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class AsyncChatResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncChatResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncChatResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncChatResourceWithStreamingResponse(self)
+
+ async def create_completion(
+ self,
+ *,
+ messages: Iterable[chat_create_completion_params.Message],
+ model: str,
+ stream: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> object:
+ """OpenAI-compatible chat completions endpoint.
+
+ Supports text messages and
+ file/image inputs via `image_url` or `file_url` parts.
+
+ **Limits and behavior:**
+
+ - The backend enforces a model context limit of ~20,000 tokens (text +
+ multimodal tokens).
+ - `file_url` inputs (e.g., PDFs) are expanded into per-page `image_url` parts
+ and embedded as data URLs.
+ - Inline data URLs are limited to ~64MB decoded size per item.
+
+ For large or multi-page documents, prefer `/api/v1/extract/*` endpoints.
+
+ Args:
+ messages: Chat messages array
+
+ model: Model identifier (e.g., nanonets/Nanonets-OCR-s)
+
+ stream: Enable SSE streaming
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._post(
+ "/v1/chat/completions",
+ body=await async_maybe_transform(
+ {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ },
+ chat_create_completion_params.ChatCreateCompletionParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=object,
+ )
+
+
+class ChatResourceWithRawResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithRawResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_raw_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class ChatResourceWithStreamingResponse:
+ def __init__(self, chat: ChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = to_streamed_response_wrapper(
+ chat.create_completion,
+ )
+
+
+class AsyncChatResourceWithStreamingResponse:
+ def __init__(self, chat: AsyncChatResource) -> None:
+ self._chat = chat
+
+ self.create_completion = async_to_streamed_response_wrapper(
+ chat.create_completion,
+ )
diff --git a/src/docstrange/resources/classify.py b/src/docstrange/resources/classify.py
index 382aa89..797bf65 100644
--- a/src/docstrange/resources/classify.py
+++ b/src/docstrange/resources/classify.py
@@ -2,11 +2,13 @@
from __future__ import annotations
+from typing import Mapping, cast
+
import httpx
-from ..types import classify_sync_params
-from .._types import Body, Query, Headers, NotGiven, FileTypes, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from ..types import classify_sync_params, classify_batch_params
+from .._types import Body, Query, Headers, NotGiven, FileTypes, SequenceNotStr, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -17,6 +19,7 @@
)
from .._base_client import make_request_options
from ..types.classify_response import ClassifyResponse
+from ..types.batch_classify_response import BatchClassifyResponse
__all__ = ["ClassifyResource", "AsyncClassifyResource"]
@@ -41,6 +44,58 @@ def with_streaming_response(self) -> ClassifyResourceWithStreamingResponse:
"""
return ClassifyResourceWithStreamingResponse(self)
+ def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50 files).
+
+ Files are queued for background processing. Use
+ `GET /api/v1/extract/results/{record_id}` to poll results.
+
+ Args:
+ categories: JSON array of category objects (max 50 categories)
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "files": files,
+ }
+ )
+ extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/classify/batch",
+ body=maybe_transform(body, classify_batch_params.ClassifyBatchParams),
+ files=extracted_files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
def sync(
self,
*,
@@ -54,12 +109,17 @@ def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document.
+ Classify a single document into predefined categories synchronously.
+
+ Each page is classified individually with category, confidence score (0-100),
+ and reasoning.
Args:
- categories: JSON array of category objects
+ categories:
+ JSON array of category objects: [{"name": "Category Name", "description":
+ "Optional description"}]
- file: File to classify
+ file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
extra_headers: Send extra headers
@@ -69,19 +129,21 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
"/api/v1/classify/sync",
- body=maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -109,6 +171,58 @@ def with_streaming_response(self) -> AsyncClassifyResourceWithStreamingResponse:
"""
return AsyncClassifyResourceWithStreamingResponse(self)
+ async def batch(
+ self,
+ *,
+ categories: str,
+ files: SequenceNotStr[FileTypes],
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchClassifyResponse:
+ """
+ Classify multiple documents asynchronously (max 50 files).
+
+ Files are queued for background processing. Use
+ `GET /api/v1/extract/results/{record_id}` to poll results.
+
+ Args:
+ categories: JSON array of category objects (max 50 categories)
+
+ files: Files to classify (max 50)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "files": files,
+ }
+ )
+ extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/classify/batch",
+ body=await async_maybe_transform(body, classify_batch_params.ClassifyBatchParams),
+ files=extracted_files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchClassifyResponse,
+ )
+
async def sync(
self,
*,
@@ -122,12 +236,17 @@ async def sync(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ClassifyResponse:
"""
- Classify a single document.
+ Classify a single document into predefined categories synchronously.
+
+ Each page is classified individually with category, confidence score (0-100),
+ and reasoning.
Args:
- categories: JSON array of category objects
+ categories:
+ JSON array of category objects: [{"name": "Category Name", "description":
+ "Optional description"}]
- file: File to classify
+ file: File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)
extra_headers: Send extra headers
@@ -137,19 +256,21 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ body = deepcopy_minimal(
+ {
+ "categories": categories,
+ "file": file,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
"/api/v1/classify/sync",
- body=await async_maybe_transform(
- {
- "categories": categories,
- "file": file,
- },
- classify_sync_params.ClassifySyncParams,
- ),
+ body=await async_maybe_transform(body, classify_sync_params.ClassifySyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -161,6 +282,9 @@ class ClassifyResourceWithRawResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = to_raw_response_wrapper(
classify.sync,
)
@@ -170,6 +294,9 @@ class AsyncClassifyResourceWithRawResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_raw_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_raw_response_wrapper(
classify.sync,
)
@@ -179,6 +306,9 @@ class ClassifyResourceWithStreamingResponse:
def __init__(self, classify: ClassifyResource) -> None:
self._classify = classify
+ self.batch = to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = to_streamed_response_wrapper(
classify.sync,
)
@@ -188,6 +318,9 @@ class AsyncClassifyResourceWithStreamingResponse:
def __init__(self, classify: AsyncClassifyResource) -> None:
self._classify = classify
+ self.batch = async_to_streamed_response_wrapper(
+ classify.batch,
+ )
self.sync = async_to_streamed_response_wrapper(
classify.sync,
)
diff --git a/src/docstrange/resources/extract/__init__.py b/src/docstrange/resources/extract/__init__.py
index a0fee27..22cd257 100644
--- a/src/docstrange/resources/extract/__init__.py
+++ b/src/docstrange/resources/extract/__init__.py
@@ -8,8 +8,22 @@
ExtractResourceWithStreamingResponse,
AsyncExtractResourceWithStreamingResponse,
)
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
__all__ = [
+ "ResultsResource",
+ "AsyncResultsResource",
+ "ResultsResourceWithRawResponse",
+ "AsyncResultsResourceWithRawResponse",
+ "ResultsResourceWithStreamingResponse",
+ "AsyncResultsResourceWithStreamingResponse",
"ExtractResource",
"AsyncExtractResource",
"ExtractResourceWithRawResponse",
diff --git a/src/docstrange/resources/extract/extract.py b/src/docstrange/resources/extract/extract.py
index f5b48d9..5a0f0fa 100644
--- a/src/docstrange/resources/extract/extract.py
+++ b/src/docstrange/resources/extract/extract.py
@@ -2,13 +2,32 @@
from __future__ import annotations
+from typing import Mapping, cast
from typing_extensions import Literal
import httpx
-from ...types import extract_sync_params
-from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
+from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params
+from .results import (
+ ResultsResource,
+ AsyncResultsResource,
+ ResultsResourceWithRawResponse,
+ AsyncResultsResourceWithRawResponse,
+ ResultsResourceWithStreamingResponse,
+ AsyncResultsResourceWithStreamingResponse,
+)
+from ..._types import (
+ Body,
+ Omit,
+ Query,
+ Headers,
+ NotGiven,
+ FileTypes,
+ SequenceNotStr,
+ omit,
+ not_given,
+)
+from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -17,13 +36,20 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
+from ..._streaming import Stream, AsyncStream
from ..._base_client import make_request_options
from ...types.extract_response import ExtractResponse
+from ...types.batch_extract_response import BatchExtractResponse
+from ...types.extract_stream_response import ExtractStreamResponse
__all__ = ["ExtractResource", "AsyncExtractResource"]
class ExtractResource(SyncAPIResource):
+ @cached_property
+ def results(self) -> ResultsResource:
+ return ResultsResource(self._client)
+
@cached_property
def with_raw_response(self) -> ExtractResourceWithRawResponse:
"""
@@ -43,13 +69,13 @@ def with_streaming_response(self) -> ExtractResourceWithStreamingResponse:
"""
return ExtractResourceWithStreamingResponse(self)
- def sync(
+ def async_(
self,
*,
- file: FileTypes,
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
+ file: FileTypes | Omit = omit,
file_base64: str | Omit = omit,
file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
@@ -62,27 +88,187 @@ def sync(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
+ """Queue a document for background processing.
+
+ Returns a `record_id` to poll
+ results via `GET /api/v1/extract/results/{record_id}`.
+
+ Recommended for large documents (>50 pages).
Args:
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
file: File to upload (PDF, Word, Excel, PowerPoint, images)
- output_format: Output format(s): markdown, html, json, csv.
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/async",
+ body=maybe_transform(body, extract_async_params.ExtractAsyncParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """Process multiple files asynchronously (max 50 files).
+
+ All files share the same
+ extraction options.
+
+ Args:
+ files: Files to process (max 50)
+
+ output_format: Output format(s) for all files
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/batch",
+ body=maybe_transform(body, extract_batch_params.ExtractBatchParams),
+ files=extracted_files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ def stream(
+ self,
+ *,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file: FileTypes | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> Stream[ExtractStreamResponse]:
+ """
+ Stream extraction results via Server-Sent Events (SSE) for real-time content
+ delivery.
+
+ **Event Types:**
+
+ - `content`: Incremental content chunks (streaming mode)
+ - `complete`: Full content at once (batch mode)
+ - `done`: Final event with record_id and processing_time
+ - `error`: Error information
+ - `async_queued`: Large files queued for async processing
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
+ multiple.
csv_options: CSV extraction options
custom_instructions: Custom extraction instructions
+ enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
+ mode.
+
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
file_base64: Base64-encoded file content
file_url: URL to download file from
- include_metadata: Comma-separated metadata types
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
json_options: JSON extraction options
- prompt_mode: append or replace
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
extra_headers: Send extra headers
@@ -92,26 +278,115 @@ def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ body = deepcopy_minimal(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
- "/api/v1/extract/sync",
- body=maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
+ "/api/v1/extract/stream",
+ body=maybe_transform(body, extract_stream_params.ExtractStreamParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
+ cast_to=str,
+ stream=True,
+ stream_cls=Stream[ExtractStreamResponse],
+ )
+
+ def sync(
+ self,
+ *,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file: FileTypes | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """Process a document and return extracted content immediately.
+
+ (Works for files
+ with 5 pages or less.)
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ "/api/v1/extract/sync",
+ body=maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -120,6 +395,10 @@ def sync(
class AsyncExtractResource(AsyncAPIResource):
+ @cached_property
+ def results(self) -> AsyncResultsResource:
+ return AsyncResultsResource(self._client)
+
@cached_property
def with_raw_response(self) -> AsyncExtractResourceWithRawResponse:
"""
@@ -139,13 +418,13 @@ def with_streaming_response(self) -> AsyncExtractResourceWithStreamingResponse:
"""
return AsyncExtractResourceWithStreamingResponse(self)
- async def sync(
+ async def async_(
self,
*,
- file: FileTypes,
output_format: str,
csv_options: str | Omit = omit,
custom_instructions: str | Omit = omit,
+ file: FileTypes | Omit = omit,
file_base64: str | Omit = omit,
file_url: str | Omit = omit,
include_metadata: str | Omit = omit,
@@ -158,27 +437,187 @@ async def sync(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ExtractResponse:
- """
- Process a document and return extracted content immediately.
+ """Queue a document for background processing.
+
+ Returns a `record_id` to poll
+ results via `GET /api/v1/extract/results/{record_id}`.
+
+ Recommended for large documents (>50 pages).
Args:
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
file: File to upload (PDF, Word, Excel, PowerPoint, images)
- output_format: Output format(s): markdown, html, json, csv.
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/async",
+ body=await async_maybe_transform(body, extract_async_params.ExtractAsyncParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ async def batch(
+ self,
+ *,
+ files: SequenceNotStr[FileTypes],
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> BatchExtractResponse:
+ """Process multiple files asynchronously (max 50 files).
+
+ All files share the same
+ extraction options.
+
+ Args:
+ files: Files to process (max 50)
+
+ output_format: Output format(s) for all files
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "files": files,
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ extracted_files = extract_files(cast(Mapping[str, object], body), paths=[["files", ""]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/batch",
+ body=await async_maybe_transform(body, extract_batch_params.ExtractBatchParams),
+ files=extracted_files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BatchExtractResponse,
+ )
+
+ async def stream(
+ self,
+ *,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ enable_streaming: bool | Omit = omit,
+ file: FileTypes | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncStream[ExtractStreamResponse]:
+ """
+ Stream extraction results via Server-Sent Events (SSE) for real-time content
+ delivery.
+
+ **Event Types:**
+
+ - `content`: Incremental content chunks (streaming mode)
+ - `complete`: Full content at once (batch mode)
+ - `done`: Final event with record_id and processing_time
+ - `error`: Error information
+ - `async_queued`: Large files queued for async processing
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for
+ multiple.
csv_options: CSV extraction options
custom_instructions: Custom extraction instructions
+ enable_streaming: Enable real-time streaming. If false, returns complete content via SSE batch
+ mode.
+
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
file_base64: Base64-encoded file content
file_url: URL to download file from
- include_metadata: Comma-separated metadata types
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
json_options: JSON extraction options
- prompt_mode: append or replace
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
extra_headers: Send extra headers
@@ -188,26 +627,115 @@ async def sync(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
+ body = deepcopy_minimal(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "enable_streaming": enable_streaming,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
# It should be noted that the actual Content-Type header that will be
# sent to the server will contain a `boundary` parameter, e.g.
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
- "/api/v1/extract/sync",
- body=await async_maybe_transform(
- {
- "file": file,
- "output_format": output_format,
- "csv_options": csv_options,
- "custom_instructions": custom_instructions,
- "file_base64": file_base64,
- "file_url": file_url,
- "include_metadata": include_metadata,
- "json_options": json_options,
- "prompt_mode": prompt_mode,
- },
- extract_sync_params.ExtractSyncParams,
+ "/api/v1/extract/stream",
+ body=await async_maybe_transform(body, extract_stream_params.ExtractStreamParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
+ cast_to=str,
+ stream=True,
+ stream_cls=AsyncStream[ExtractStreamResponse],
+ )
+
+ async def sync(
+ self,
+ *,
+ output_format: str,
+ csv_options: str | Omit = omit,
+ custom_instructions: str | Omit = omit,
+ file: FileTypes | Omit = omit,
+ file_base64: str | Omit = omit,
+ file_url: str | Omit = omit,
+ include_metadata: str | Omit = omit,
+ json_options: str | Omit = omit,
+ prompt_mode: Literal["append", "replace"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """Process a document and return extracted content immediately.
+
+ (Works for files
+ with 5 pages or less.)
+
+ Provide exactly one of: `file`, `file_url`, or `file_base64`.
+
+ Args:
+ output_format: Output format(s): `markdown`, `html`, `json`, `csv`. Comma-separate for multiple
+ (e.g., `markdown,json`).
+
+ csv_options: CSV extraction options (e.g., `table`)
+
+ custom_instructions: Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)
+
+ file: File to upload (PDF, Word, Excel, PowerPoint, images)
+
+ file_base64: Base64-encoded file content
+
+ file_url: URL to download file from
+
+ include_metadata: Comma-separated metadata: `bounding_boxes`, `confidence_score`
+
+ json_options: JSON extraction options. Values: `hierarchy_output`, `table-of-contents`, field
+ list `["field1", "field2"]`, or JSON schema `{...}`
+
+ prompt_mode: `append`: add to base prompt, `replace`: use only custom instructions
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ body = deepcopy_minimal(
+ {
+ "output_format": output_format,
+ "csv_options": csv_options,
+ "custom_instructions": custom_instructions,
+ "file": file,
+ "file_base64": file_base64,
+ "file_url": file_url,
+ "include_metadata": include_metadata,
+ "json_options": json_options,
+ "prompt_mode": prompt_mode,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ "/api/v1/extract/sync",
+ body=await async_maybe_transform(body, extract_sync_params.ExtractSyncParams),
+ files=files,
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -219,33 +747,85 @@ class ExtractResourceWithRawResponse:
def __init__(self, extract: ExtractResource) -> None:
self._extract = extract
+ self.async_ = to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_raw_response_wrapper(
+ extract.stream,
+ )
self.sync = to_raw_response_wrapper(
extract.sync,
)
+ @cached_property
+ def results(self) -> ResultsResourceWithRawResponse:
+ return ResultsResourceWithRawResponse(self._extract.results)
+
class AsyncExtractResourceWithRawResponse:
def __init__(self, extract: AsyncExtractResource) -> None:
self._extract = extract
+ self.async_ = async_to_raw_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_raw_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_raw_response_wrapper(
+ extract.stream,
+ )
self.sync = async_to_raw_response_wrapper(
extract.sync,
)
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithRawResponse:
+ return AsyncResultsResourceWithRawResponse(self._extract.results)
+
class ExtractResourceWithStreamingResponse:
def __init__(self, extract: ExtractResource) -> None:
self._extract = extract
+ self.async_ = to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = to_streamed_response_wrapper(
+ extract.stream,
+ )
self.sync = to_streamed_response_wrapper(
extract.sync,
)
+ @cached_property
+ def results(self) -> ResultsResourceWithStreamingResponse:
+ return ResultsResourceWithStreamingResponse(self._extract.results)
+
class AsyncExtractResourceWithStreamingResponse:
def __init__(self, extract: AsyncExtractResource) -> None:
self._extract = extract
+ self.async_ = async_to_streamed_response_wrapper(
+ extract.async_,
+ )
+ self.batch = async_to_streamed_response_wrapper(
+ extract.batch,
+ )
+ self.stream = async_to_streamed_response_wrapper(
+ extract.stream,
+ )
self.sync = async_to_streamed_response_wrapper(
extract.sync,
)
+
+ @cached_property
+ def results(self) -> AsyncResultsResourceWithStreamingResponse:
+ return AsyncResultsResourceWithStreamingResponse(self._extract.results)
diff --git a/src/docstrange/resources/extract/results.py b/src/docstrange/resources/extract/results.py
new file mode 100644
index 0000000..1533ac2
--- /dev/null
+++ b/src/docstrange/resources/extract/results.py
@@ -0,0 +1,294 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+from ..._base_client import AsyncPaginator, make_request_options
+from ...types.extract import result_list_params, result_retrieve_params
+from ...types.extract_response import ExtractResponse
+
+__all__ = ["ResultsResource", "AsyncResultsResource"]
+
+
+class ResultsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return ResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return ResultsResourceWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ include_content: Include full extracted content (default: true)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> SyncPageNumberPagination[ExtractResponse]:
+ """
+ List all extraction jobs for the authenticated user (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=SyncPageNumberPagination[ExtractResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=ExtractResponse,
+ )
+
+
+class AsyncResultsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncResultsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncResultsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncResultsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/NanoNets/docstrange-python#with_streaming_response
+ """
+ return AsyncResultsResourceWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ record_id: str,
+ *,
+ include_content: bool | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> ExtractResponse:
+ """
+ Retrieve status and result of an extraction job.
+
+ Args:
+ include_content: Include full extracted content (default: true)
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not record_id:
+ raise ValueError(f"Expected a non-empty value for `record_id` but received {record_id!r}")
+ return await self._get(
+ f"/api/v1/extract/results/{record_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"include_content": include_content}, result_retrieve_params.ResultRetrieveParams
+ ),
+ ),
+ cast_to=ExtractResponse,
+ )
+
+ def list(
+ self,
+ *,
+ page: int | Omit = omit,
+ page_size: int | Omit = omit,
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+ | Omit = omit,
+ sort_order: Literal["asc", "desc"] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncPaginator[ExtractResponse, AsyncPageNumberPagination[ExtractResponse]]:
+ """
+ List all extraction jobs for the authenticated user (paginated).
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get_api_list(
+ "/api/v1/extract/results",
+ page=AsyncPageNumberPagination[ExtractResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "page": page,
+ "page_size": page_size,
+ "sort_by": sort_by,
+ "sort_order": sort_order,
+ },
+ result_list_params.ResultListParams,
+ ),
+ ),
+ model=ExtractResponse,
+ )
+
+
+class ResultsResourceWithRawResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithRawResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_raw_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ results.list,
+ )
+
+
+class ResultsResourceWithStreamingResponse:
+ def __init__(self, results: ResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ results.list,
+ )
+
+
+class AsyncResultsResourceWithStreamingResponse:
+ def __init__(self, results: AsyncResultsResource) -> None:
+ self._results = results
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ results.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ results.list,
+ )
diff --git a/src/docstrange/types/__init__.py b/src/docstrange/types/__init__.py
index fac3955..a18a10a 100644
--- a/src/docstrange/types/__init__.py
+++ b/src/docstrange/types/__init__.py
@@ -4,5 +4,18 @@
from .extract_response import ExtractResponse as ExtractResponse
from .classify_response import ClassifyResponse as ClassifyResponse
+from .extraction_result import ExtractionResult as ExtractionResult
from .extract_sync_params import ExtractSyncParams as ExtractSyncParams
+from .extraction_metadata import ExtractionMetadata as ExtractionMetadata
+from .page_classification import PageClassification as PageClassification
from .classify_sync_params import ClassifySyncParams as ClassifySyncParams
+from .extract_async_params import ExtractAsyncParams as ExtractAsyncParams
+from .extract_batch_params import ExtractBatchParams as ExtractBatchParams
+from .classify_batch_params import ClassifyBatchParams as ClassifyBatchParams
+from .extract_stream_params import ExtractStreamParams as ExtractStreamParams
+from .batch_extract_response import BatchExtractResponse as BatchExtractResponse
+from .batch_classify_response import BatchClassifyResponse as BatchClassifyResponse
+from .extract_stream_response import ExtractStreamResponse as ExtractStreamResponse
+from .extraction_format_result import ExtractionFormatResult as ExtractionFormatResult
+from .file_classification_result import FileClassificationResult as FileClassificationResult
+from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
diff --git a/src/docstrange/types/batch_classify_response.py b/src/docstrange/types/batch_classify_response.py
new file mode 100644
index 0000000..a36e5a8
--- /dev/null
+++ b/src/docstrange/types/batch_classify_response.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .file_classification_result import FileClassificationResult
+
+__all__ = ["BatchClassifyResponse"]
+
+
+class BatchClassifyResponse(BaseModel):
+ batch_id: str
+
+ failed_files: int
+
+ message: str
+
+ results: List[FileClassificationResult]
+
+ success: bool
+
+ successful_files: int
+
+ total_files: int
diff --git a/src/docstrange/types/batch_extract_response.py b/src/docstrange/types/batch_extract_response.py
new file mode 100644
index 0000000..4e73773
--- /dev/null
+++ b/src/docstrange/types/batch_extract_response.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .extract_response import ExtractResponse
+
+__all__ = ["BatchExtractResponse"]
+
+
+class BatchExtractResponse(BaseModel):
+ accepted_files: int
+
+ batch_id: str
+
+ message: str
+
+ records: List[ExtractResponse]
+
+ rejected_files: int
+
+ success: bool
+
+ total_files: int
diff --git a/src/docstrange/types/chat_create_completion_params.py b/src/docstrange/types/chat_create_completion_params.py
new file mode 100644
index 0000000..b7cde5c
--- /dev/null
+++ b/src/docstrange/types/chat_create_completion_params.py
@@ -0,0 +1,45 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ChatCreateCompletionParams", "Message", "MessageContent", "MessageContentFileURL", "MessageContentImageURL"]
+
+
+class ChatCreateCompletionParams(TypedDict, total=False):
+ messages: Required[Iterable[Message]]
+ """Chat messages array"""
+
+ model: Required[str]
+ """Model identifier (e.g., nanonets/Nanonets-OCR-s)"""
+
+ stream: bool
+ """Enable SSE streaming"""
+
+
+class MessageContentFileURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContentImageURL(TypedDict, total=False):
+ url: str
+
+
+class MessageContent(TypedDict, total=False):
+ file_url: MessageContentFileURL
+
+ image_url: MessageContentImageURL
+
+ text: str
+
+ type: str
+
+
+class Message(TypedDict, total=False):
+ content: Required[Iterable[MessageContent]]
+ """Message content as an array of parts (text or file/image URLs)."""
+
+ role: Required[str]
+ """Message role (system, user, assistant)"""
diff --git a/src/docstrange/types/classify_batch_params.py b/src/docstrange/types/classify_batch_params.py
new file mode 100644
index 0000000..5cac9e3
--- /dev/null
+++ b/src/docstrange/types/classify_batch_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ClassifyBatchParams"]
+
+
+class ClassifyBatchParams(TypedDict, total=False):
+ categories: Required[str]
+ """JSON array of category objects (max 50 categories)"""
+
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to classify (max 50)"""
diff --git a/src/docstrange/types/classify_response.py b/src/docstrange/types/classify_response.py
index 5bab3de..fdebbb0 100644
--- a/src/docstrange/types/classify_response.py
+++ b/src/docstrange/types/classify_response.py
@@ -1,6 +1,9 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from typing import Optional
+
from .._models import BaseModel
+from .file_classification_result import FileClassificationResult
__all__ = ["ClassifyResponse"]
@@ -9,3 +12,5 @@ class ClassifyResponse(BaseModel):
message: str
success: bool
+
+ result: Optional[FileClassificationResult] = None
diff --git a/src/docstrange/types/classify_sync_params.py b/src/docstrange/types/classify_sync_params.py
index d0b3e16..772427d 100644
--- a/src/docstrange/types/classify_sync_params.py
+++ b/src/docstrange/types/classify_sync_params.py
@@ -11,7 +11,10 @@
class ClassifySyncParams(TypedDict, total=False):
categories: Required[str]
- """JSON array of category objects"""
+ """
+ JSON array of category objects: [{"name": "Category Name", "description":
+ "Optional description"}]
+ """
file: Required[FileTypes]
- """File to classify"""
+ """File to classify (PDF, PNG, JPG, JPEG, TIFF, BMP, WebP)"""
diff --git a/src/docstrange/types/extract/__init__.py b/src/docstrange/types/extract/__init__.py
index f8ee8b1..387a007 100644
--- a/src/docstrange/types/extract/__init__.py
+++ b/src/docstrange/types/extract/__init__.py
@@ -1,3 +1,8 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from __future__ import annotations
+
+from .pagination_info import PaginationInfo as PaginationInfo
+from .result_list_params import ResultListParams as ResultListParams
+from .result_retrieve_params import ResultRetrieveParams as ResultRetrieveParams
+from .extraction_list_response import ExtractionListResponse as ExtractionListResponse
diff --git a/src/docstrange/types/extract/extraction_list_response.py b/src/docstrange/types/extract/extraction_list_response.py
new file mode 100644
index 0000000..26a12e7
--- /dev/null
+++ b/src/docstrange/types/extract/extraction_list_response.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from .pagination_info import PaginationInfo
+from ..extract_response import ExtractResponse
+
+__all__ = ["ExtractionListResponse"]
+
+
+class ExtractionListResponse(BaseModel):
+ pagination: PaginationInfo
+
+ results: List[ExtractResponse]
+
+ success: bool
diff --git a/src/docstrange/types/extract/pagination_info.py b/src/docstrange/types/extract/pagination_info.py
new file mode 100644
index 0000000..7a678a9
--- /dev/null
+++ b/src/docstrange/types/extract/pagination_info.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["PaginationInfo"]
+
+
+class PaginationInfo(BaseModel):
+ has_next: Optional[bool] = None
+
+ has_previous: Optional[bool] = None
+
+ page: Optional[int] = None
+
+ page_size: Optional[int] = None
+
+ total_count: Optional[int] = None
+
+ total_pages: Optional[int] = None
diff --git a/src/docstrange/types/extract/result_list_params.py b/src/docstrange/types/extract/result_list_params.py
new file mode 100644
index 0000000..7dfe38a
--- /dev/null
+++ b/src/docstrange/types/extract/result_list_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["ResultListParams"]
+
+
+class ResultListParams(TypedDict, total=False):
+ page: int
+
+ page_size: int
+
+ sort_by: Literal["created_at", "updated_at", "original_filename", "file_size", "processing_status"]
+
+ sort_order: Literal["asc", "desc"]
diff --git a/src/docstrange/types/extract/result_retrieve_params.py b/src/docstrange/types/extract/result_retrieve_params.py
new file mode 100644
index 0000000..539b80d
--- /dev/null
+++ b/src/docstrange/types/extract/result_retrieve_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["ResultRetrieveParams"]
+
+
+class ResultRetrieveParams(TypedDict, total=False):
+ include_content: bool
+ """Include full extracted content (default: true)"""
diff --git a/src/docstrange/types/extract_async_params.py b/src/docstrange/types/extract_async_params.py
new file mode 100644
index 0000000..d638b09
--- /dev/null
+++ b/src/docstrange/types/extract_async_params.py
@@ -0,0 +1,45 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractAsyncParams"]
+
+
+class ExtractAsyncParams(TypedDict, total=False):
+ output_format: Required[str]
+ """Output format(s): `markdown`, `html`, `json`, `csv`.
+
+ Comma-separate for multiple (e.g., `markdown,json`).
+ """
+
+ csv_options: str
+ """CSV extraction options (e.g., `table`)"""
+
+ custom_instructions: str
+ """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
+
+ file: FileTypes
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
+
+ json_options: str
+ """JSON extraction options.
+
+ Values: `hierarchy_output`, `table-of-contents`, field list
+ `["field1", "field2"]`, or JSON schema `{...}`
+ """
+
+ prompt_mode: Literal["append", "replace"]
+ """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_batch_params.py b/src/docstrange/types/extract_batch_params.py
new file mode 100644
index 0000000..bdc7b29
--- /dev/null
+++ b/src/docstrange/types/extract_batch_params.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+
+__all__ = ["ExtractBatchParams"]
+
+
+class ExtractBatchParams(TypedDict, total=False):
+ files: Required[SequenceNotStr[FileTypes]]
+ """Files to process (max 50)"""
+
+ output_format: Required[str]
+ """Output format(s) for all files"""
+
+ csv_options: str
+
+ custom_instructions: str
+
+ include_metadata: str
+
+ json_options: str
+
+ prompt_mode: Literal["append", "replace"]
diff --git a/src/docstrange/types/extract_response.py b/src/docstrange/types/extract_response.py
index ba021e0..9d93ead 100644
--- a/src/docstrange/types/extract_response.py
+++ b/src/docstrange/types/extract_response.py
@@ -1,17 +1,38 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
+from .extraction_result import ExtractionResult
__all__ = ["ExtractResponse"]
class ExtractResponse(BaseModel):
+ message: str
+
record_id: str
+ """Job ID for retrieving results"""
- status: str
+ status: Literal["completed", "processing", "failed"]
success: bool
- message: Optional[str] = None
+ created_at: Optional[datetime] = None
+
+ file_size: Optional[int] = None
+ """Size in bytes"""
+
+ filename: Optional[str] = None
+
+ output_format: Optional[str] = None
+
+ pages_processed: Optional[int] = None
+
+ processing_time: Optional[float] = None
+ """Time in seconds"""
+
+ result: Optional[ExtractionResult] = None
+ """Results by format (only requested formats populated)"""
diff --git a/src/docstrange/types/extract_stream_params.py b/src/docstrange/types/extract_stream_params.py
new file mode 100644
index 0000000..2a8e9e3
--- /dev/null
+++ b/src/docstrange/types/extract_stream_params.py
@@ -0,0 +1,47 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ExtractStreamParams"]
+
+
+class ExtractStreamParams(TypedDict, total=False):
+ output_format: Required[str]
+ """Output format(s): `markdown`, `html`, `json`, `csv`.
+
+ Comma-separate for multiple.
+ """
+
+ csv_options: str
+ """CSV extraction options"""
+
+ custom_instructions: str
+ """Custom extraction instructions"""
+
+ enable_streaming: bool
+ """Enable real-time streaming.
+
+ If false, returns complete content via SSE batch mode.
+ """
+
+ file: FileTypes
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
+
+ file_base64: str
+ """Base64-encoded file content"""
+
+ file_url: str
+ """URL to download file from"""
+
+ include_metadata: str
+ """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
+
+ json_options: str
+ """JSON extraction options"""
+
+ prompt_mode: Literal["append", "replace"]
+ """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extract_stream_response.py b/src/docstrange/types/extract_stream_response.py
new file mode 100644
index 0000000..333ff97
--- /dev/null
+++ b/src/docstrange/types/extract_stream_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["ExtractStreamResponse"]
+
+ExtractStreamResponse: TypeAlias = str
diff --git a/src/docstrange/types/extract_sync_params.py b/src/docstrange/types/extract_sync_params.py
index 1f032ea..e3c4bea 100644
--- a/src/docstrange/types/extract_sync_params.py
+++ b/src/docstrange/types/extract_sync_params.py
@@ -10,17 +10,20 @@
class ExtractSyncParams(TypedDict, total=False):
- file: Required[FileTypes]
- """File to upload (PDF, Word, Excel, PowerPoint, images)"""
-
output_format: Required[str]
- """Output format(s): markdown, html, json, csv."""
+ """Output format(s): `markdown`, `html`, `json`, `csv`.
+
+ Comma-separate for multiple (e.g., `markdown,json`).
+ """
csv_options: str
- """CSV extraction options"""
+ """CSV extraction options (e.g., `table`)"""
custom_instructions: str
- """Custom extraction instructions"""
+ """Custom extraction instructions (e.g., `Format dates as YYYY-MM-DD`)"""
+
+ file: FileTypes
+ """File to upload (PDF, Word, Excel, PowerPoint, images)"""
file_base64: str
"""Base64-encoded file content"""
@@ -29,10 +32,14 @@ class ExtractSyncParams(TypedDict, total=False):
"""URL to download file from"""
include_metadata: str
- """Comma-separated metadata types"""
+ """Comma-separated metadata: `bounding_boxes`, `confidence_score`"""
json_options: str
- """JSON extraction options"""
+ """JSON extraction options.
+
+ Values: `hierarchy_output`, `table-of-contents`, field list
+ `["field1", "field2"]`, or JSON schema `{...}`
+ """
prompt_mode: Literal["append", "replace"]
- """append or replace"""
+ """`append`: add to base prompt, `replace`: use only custom instructions"""
diff --git a/src/docstrange/types/extraction_format_result.py b/src/docstrange/types/extraction_format_result.py
new file mode 100644
index 0000000..579500c
--- /dev/null
+++ b/src/docstrange/types/extraction_format_result.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union, Optional
+
+from .._models import BaseModel
+from .extraction_metadata import ExtractionMetadata
+
+__all__ = ["ExtractionFormatResult"]
+
+
+class ExtractionFormatResult(BaseModel):
+ content: Union[str, object]
+ """Extracted content"""
+
+ metadata: Optional[ExtractionMetadata] = None
diff --git a/src/docstrange/types/extraction_metadata.py b/src/docstrange/types/extraction_metadata.py
new file mode 100644
index 0000000..9792ba0
--- /dev/null
+++ b/src/docstrange/types/extraction_metadata.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["ExtractionMetadata"]
+
+
+class ExtractionMetadata(BaseModel):
+ bounding_boxes: Optional[object] = None
+ """Element coordinates with page dimensions"""
+
+ confidence_score: Optional[object] = None
+ """Confidence scores per field"""
diff --git a/src/docstrange/types/extraction_result.py b/src/docstrange/types/extraction_result.py
new file mode 100644
index 0000000..57b2928
--- /dev/null
+++ b/src/docstrange/types/extraction_result.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+from .extraction_format_result import ExtractionFormatResult
+
+__all__ = ["ExtractionResult"]
+
+
+class ExtractionResult(BaseModel):
+ """Results by format (only requested formats populated)"""
+
+ csv: Optional[ExtractionFormatResult] = None
+
+ html: Optional[ExtractionFormatResult] = None
+
+ json_: Optional[ExtractionFormatResult] = FieldInfo(alias="json", default=None)
+
+ markdown: Optional[ExtractionFormatResult] = None
diff --git a/src/docstrange/types/file_classification_result.py b/src/docstrange/types/file_classification_result.py
new file mode 100644
index 0000000..397d924
--- /dev/null
+++ b/src/docstrange/types/file_classification_result.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+from .page_classification import PageClassification
+
+__all__ = ["FileClassificationResult"]
+
+
+class FileClassificationResult(BaseModel):
+ filename: str
+
+ pages: List[PageClassification]
+
+ total_pages: int
+
+ error: Optional[str] = None
+
+ processing_time: Optional[float] = None
+ """Time in seconds"""
+
+ record_id: Optional[str] = None
+ """Record ID for polling results"""
diff --git a/src/docstrange/types/page_classification.py b/src/docstrange/types/page_classification.py
new file mode 100644
index 0000000..2099524
--- /dev/null
+++ b/src/docstrange/types/page_classification.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["PageClassification"]
+
+
+class PageClassification(BaseModel):
+ category: str
+ """Matched category name or 'Other' if no match"""
+
+ confidence: int
+ """Confidence score (0-100)"""
+
+ page_number: int
+
+ reasoning: str
+ """Explanation for the classification"""
+
+ identified_category: Optional[str] = None
+ """
+ Specific document type identified by the model (e.g.,
+ 'Invoice_Amazon_Electronics'). Always provided - contains a more detailed
+ classification than the category.
+ """
diff --git a/tests/api_resources/extract/test_results.py b/tests/api_resources/extract/test_results.py
new file mode 100644
index 0000000..ee1d5f5
--- /dev/null
+++ b/tests/api_resources/extract/test_results.py
@@ -0,0 +1,205 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+from docstrange.types import ExtractResponse
+from docstrange.pagination import SyncPageNumberPagination, AsyncPageNumberPagination
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestResults:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Docstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Docstrange) -> None:
+ result = client.extract.results.list()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Docstrange) -> None:
+ result = client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Docstrange) -> None:
+ response = client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Docstrange) -> None:
+ with client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = response.parse()
+ assert_matches_type(SyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncResults:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.retrieve(
+ record_id="record_id",
+ include_content=True,
+ )
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.retrieve(
+ record_id="record_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.retrieve(
+ record_id="record_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(ExtractResponse, result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncDocstrange) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `record_id` but received ''"):
+ await async_client.extract.results.with_raw_response.retrieve(
+ record_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ result = await async_client.extract.results.list(
+ page=1,
+ page_size=1,
+ sort_by="created_at",
+ sort_order="asc",
+ )
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.results.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.results.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ result = await response.parse()
+ assert_matches_type(AsyncPageNumberPagination[ExtractResponse], result, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
new file mode 100644
index 0000000..cbcd7c3
--- /dev/null
+++ b/tests/api_resources/test_chat.py
@@ -0,0 +1,183 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from docstrange import Docstrange, AsyncDocstrange
+from tests.utils import assert_matches_type
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestChat:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_create_completion_with_all_params(self, client: Docstrange) -> None:
+ chat = client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "https://example.com/doc.pdf"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "file_url",
+ },
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "Extract the text from the document.",
+ "type": "text",
+ },
+ ],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ stream=False,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_create_completion(self, client: Docstrange) -> None:
+ response = client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_create_completion(self, client: Docstrange) -> None:
+ with client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncChat:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_create_completion_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ chat = await async_client.chat.create_completion(
+ messages=[
+ {
+ "content": [
+ {
+ "file_url": {"url": "https://example.com/doc.pdf"},
+ "image_url": {"url": "url"},
+ "text": "text",
+ "type": "file_url",
+ },
+ {
+ "file_url": {"url": "url"},
+ "image_url": {"url": "url"},
+ "text": "Extract the text from the document.",
+ "type": "text",
+ },
+ ],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ stream=False,
+ )
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.chat.with_raw_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_create_completion(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.chat.with_streaming_response.create_completion(
+ messages=[
+ {
+ "content": [{}, {}],
+ "role": "user",
+ }
+ ],
+ model="nanonets/Nanonets-OCR-s",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(object, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_classify.py b/tests/api_resources/test_classify.py
index 63539df..b4377f6 100644
--- a/tests/api_resources/test_classify.py
+++ b/tests/api_resources/test_classify.py
@@ -9,7 +9,7 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ClassifyResponse
+from docstrange.types import ClassifyResponse, BatchClassifyResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,11 +17,48 @@
class TestClassify:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ classify = client.classify.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.classify.with_raw_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.classify.with_streaming_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
classify = client.classify.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -30,7 +67,7 @@ def test_method_sync(self, client: Docstrange) -> None:
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.classify.with_raw_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
@@ -43,7 +80,7 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.classify.with_streaming_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
) as response:
assert not response.is_closed
@@ -60,11 +97,48 @@ class TestAsyncClassify:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ classify = await async_client.classify.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.classify.with_raw_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.classify.with_streaming_response.batch(
+ categories='[{"name": "Invoice"}, {"name": "Contract"}, {"name": "Receipt"}]',
+ files=[b"raw file contents"],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ classify = await response.parse()
+ assert_matches_type(BatchClassifyResponse, classify, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
classify = await async_client.classify.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
assert_matches_type(ClassifyResponse, classify, path=["response"])
@@ -73,7 +147,7 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.classify.with_raw_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
)
@@ -86,7 +160,7 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.classify.with_streaming_response.sync(
- categories="categories",
+ categories='[{"name": "Invoice", "description": "Bills and invoices"}, {"name": "Contract", "description": "Legal agreements"}]',
file=b"raw file contents",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_extract.py b/tests/api_resources/test_extract.py
index d911970..ffdac33 100644
--- a/tests/api_resources/test_extract.py
+++ b/tests/api_resources/test_extract.py
@@ -9,7 +9,10 @@
from docstrange import Docstrange, AsyncDocstrange
from tests.utils import assert_matches_type
-from docstrange.types import ExtractResponse
+from docstrange.types import (
+ ExtractResponse,
+ BatchExtractResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,11 +20,161 @@
class TestExtract:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_async_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.async_(
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file=b"raw file contents",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_async(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.async_(
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_async(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.async_(
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_batch_with_all_params(self, client: Docstrange) -> None:
+ extract = client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_batch(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_batch(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ output_format="markdown",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_method_stream_with_all_params(self, client: Docstrange) -> None:
+ extract_stream = client.extract.stream(
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file=b"raw file contents",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ extract_stream.response.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_raw_response_stream(self, client: Docstrange) -> None:
+ response = client.extract.with_raw_response.stream(
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = response.parse()
+ stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ def test_streaming_response_stream(self, client: Docstrange) -> None:
+ with client.extract.with_streaming_response.stream(
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = response.parse()
+ stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_sync(self, client: Docstrange) -> None:
extract = client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -30,10 +183,10 @@ def test_method_sync(self, client: Docstrange) -> None:
@parametrize
def test_method_sync_with_all_params(self, client: Docstrange) -> None:
extract = client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
csv_options="",
custom_instructions="",
+ file=b"raw file contents",
file_base64="",
file_url="",
include_metadata="",
@@ -46,7 +199,6 @@ def test_method_sync_with_all_params(self, client: Docstrange) -> None:
@parametrize
def test_raw_response_sync(self, client: Docstrange) -> None:
response = client.extract.with_raw_response.sync(
- file=b"raw file contents",
output_format="markdown",
)
@@ -59,7 +211,6 @@ def test_raw_response_sync(self, client: Docstrange) -> None:
@parametrize
def test_streaming_response_sync(self, client: Docstrange) -> None:
with client.extract.with_streaming_response.sync(
- file=b"raw file contents",
output_format="markdown",
) as response:
assert not response.is_closed
@@ -76,11 +227,161 @@ class TestAsyncExtract:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ output_format="markdown",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_async_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.async_(
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ file=b"raw file contents",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_async(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.async_(
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_async(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.async_(
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(ExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_batch_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract = await async_client.extract.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ csv_options="csv_options",
+ custom_instructions="custom_instructions",
+ include_metadata="include_metadata",
+ json_options="json_options",
+ prompt_mode="append",
+ )
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_batch(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_batch(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.batch(
+ files=[b"raw file contents"],
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ extract = await response.parse()
+ assert_matches_type(BatchExtractResponse, extract, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ output_format="markdown",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_method_stream_with_all_params(self, async_client: AsyncDocstrange) -> None:
+ extract_stream = await async_client.extract.stream(
+ output_format="markdown",
+ csv_options="",
+ custom_instructions="",
+ enable_streaming=True,
+ file=b"raw file contents",
+ file_base64="",
+ file_url="",
+ include_metadata="",
+ json_options="",
+ prompt_mode="append",
+ )
+ await extract_stream.response.aclose()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_raw_response_stream(self, async_client: AsyncDocstrange) -> None:
+ response = await async_client.extract.with_raw_response.stream(
+ output_format="markdown",
+ )
+
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ stream = await response.parse()
+ await stream.close()
+
+ @pytest.mark.skip(reason="Prism doesn't support text/event-stream responses")
+ @parametrize
+ async def test_streaming_response_stream(self, async_client: AsyncDocstrange) -> None:
+ async with async_client.extract.with_streaming_response.stream(
+ output_format="markdown",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ stream = await response.parse()
+ await stream.close()
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
)
assert_matches_type(ExtractResponse, extract, path=["response"])
@@ -89,10 +390,10 @@ async def test_method_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange) -> None:
extract = await async_client.extract.sync(
- file=b"raw file contents",
output_format="markdown",
csv_options="",
custom_instructions="",
+ file=b"raw file contents",
file_base64="",
file_url="",
include_metadata="",
@@ -105,7 +406,6 @@ async def test_method_sync_with_all_params(self, async_client: AsyncDocstrange)
@parametrize
async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
response = await async_client.extract.with_raw_response.sync(
- file=b"raw file contents",
output_format="markdown",
)
@@ -118,7 +418,6 @@ async def test_raw_response_sync(self, async_client: AsyncDocstrange) -> None:
@parametrize
async def test_streaming_response_sync(self, async_client: AsyncDocstrange) -> None:
async with async_client.extract.with_streaming_response.sync(
- file=b"raw file contents",
output_format="markdown",
) as response:
assert not response.is_closed
diff --git a/tests/test_client.py b/tests/test_client.py
index 719c826..3d576f6 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -862,7 +862,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter, clien
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@@ -872,7 +872,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter, client
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- client.extract.with_streaming_response.sync(file=b"raw file contents", output_format="markdown").__enter__()
+ client.extract.with_streaming_response.sync(output_format="markdown").__enter__()
assert _get_open_connections(client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -901,7 +901,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
+ response = client.extract.with_raw_response.sync(output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -926,7 +926,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
+ output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -951,7 +951,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
+ output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
@@ -1768,9 +1768,7 @@ async def test_retrying_timeout_errors_doesnt_leak(
respx_mock.post("/api/v1/extract/sync").mock(side_effect=httpx.TimeoutException("Test timeout error"))
with pytest.raises(APITimeoutError):
- await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="markdown"
- ).__aenter__()
+ await async_client.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
assert _get_open_connections(async_client) == 0
@@ -1782,9 +1780,7 @@ async def test_retrying_status_errors_doesnt_leak(
respx_mock.post("/api/v1/extract/sync").mock(return_value=httpx.Response(500))
with pytest.raises(APIStatusError):
- await async_client.extract.with_streaming_response.sync(
- file=b"raw file contents", output_format="markdown"
- ).__aenter__()
+ await async_client.extract.with_streaming_response.sync(output_format="markdown").__aenter__()
assert _get_open_connections(async_client) == 0
@pytest.mark.parametrize("failures_before_success", [0, 2, 4])
@@ -1813,7 +1809,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
- response = await client.extract.with_raw_response.sync(file=b"raw file contents", output_format="markdown")
+ response = await client.extract.with_raw_response.sync(output_format="markdown")
assert response.retries_taken == failures_before_success
assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success
@@ -1838,7 +1834,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
+ output_format="markdown", extra_headers={"x-stainless-retry-count": Omit()}
)
assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0
@@ -1863,7 +1859,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
respx_mock.post("/api/v1/extract/sync").mock(side_effect=retry_handler)
response = await client.extract.with_raw_response.sync(
- file=b"raw file contents", output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
+ output_format="markdown", extra_headers={"x-stainless-retry-count": "42"}
)
assert response.http_request.headers.get("x-stainless-retry-count") == "42"
From e672affb60919120a36dac2ddb58c52ab8c80ded Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 22:34:29 +0000
Subject: [PATCH 24/26] codegen metadata
---
.stats.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.stats.yml b/.stats.yml
index 6864372..7d71630 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 1804754b97b5ccf95ad31183c74527bc
+config_hash: 61ade82f6ddf75edd008789d19f04a3a
From 8e487a02975b8b2873fdcbf51df22a2c7f04275d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 01:10:33 +0000
Subject: [PATCH 25/26] chore: update SDK settings
---
.github/workflows/publish-pypi.yml | 5 ++---
.github/workflows/release-doctor.yml | 2 ++
.stats.yml | 2 +-
bin/check-release-environment | 4 ++++
bin/publish-pypi | 6 +-----
5 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml
index e1fd4b7..1be9543 100644
--- a/.github/workflows/publish-pypi.yml
+++ b/.github/workflows/publish-pypi.yml
@@ -12,9 +12,6 @@ jobs:
publish:
name: publish
runs-on: ubuntu-latest
- permissions:
- contents: read
- id-token: write
steps:
- uses: actions/checkout@v6
@@ -27,3 +24,5 @@ jobs:
- name: Publish to PyPI
run: |
bash ./bin/publish-pypi
+ env:
+ PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml
index 5be741d..7f49e8e 100644
--- a/.github/workflows/release-doctor.yml
+++ b/.github/workflows/release-doctor.yml
@@ -17,3 +17,5 @@ jobs:
- name: Check release environment
run: |
bash ./bin/check-release-environment
+ env:
+ PYPI_TOKEN: ${{ secrets.DOCSTRANGE_PYPI_TOKEN || secrets.PYPI_TOKEN }}
diff --git a/.stats.yml b/.stats.yml
index 7d71630..e4e127d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 9
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nanonets%2Fdocstrange-a418fe45369669cc2d14b549ee010f3a7ee52f6e47fea3489e560d33064be099.yml
openapi_spec_hash: 02f7f52faae1eb42188c290c32c25f10
-config_hash: 61ade82f6ddf75edd008789d19f04a3a
+config_hash: b1979c16c99baf59cbbf8c7944a47297
diff --git a/bin/check-release-environment b/bin/check-release-environment
index 1e951e9..b845b0f 100644
--- a/bin/check-release-environment
+++ b/bin/check-release-environment
@@ -2,6 +2,10 @@
errors=()
+if [ -z "${PYPI_TOKEN}" ]; then
+ errors+=("The PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
+fi
+
lenErrors=${#errors[@]}
if [[ lenErrors -gt 0 ]]; then
diff --git a/bin/publish-pypi b/bin/publish-pypi
index 5895700..e72ca2f 100644
--- a/bin/publish-pypi
+++ b/bin/publish-pypi
@@ -4,8 +4,4 @@ set -eux
rm -rf dist
mkdir -p dist
uv build
-if [ -n "${PYPI_TOKEN:-}" ]; then
- uv publish --token=$PYPI_TOKEN
-else
- uv publish
-fi
+uv publish --token=$PYPI_TOKEN
From f0813d5b6bca11bc5db2f9f12b5b1418792f7392 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 01:10:50 +0000
Subject: [PATCH 26/26] release: 0.1.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 30 ++++++++++++++++++++++++++++++
pyproject.toml | 2 +-
src/docstrange/_version.py | 2 +-
4 files changed, 33 insertions(+), 3 deletions(-)
create mode 100644 CHANGELOG.md
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 1332969..3d2ac0b 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.0.1"
+ ".": "0.1.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..1da4dde
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,30 @@
+# Changelog
+
+## 0.1.0 (2026-02-13)
+
+Full Changelog: [v0.0.1...v0.1.0](https://github.com/NanoNets/docstrange-python/compare/v0.0.1...v0.1.0)
+
+### Features
+
+* **api:** api update ([b03ae9b](https://github.com/NanoNets/docstrange-python/commit/b03ae9b0d7d5940df2aaff8b4cfa22c163a31b6b))
+* **api:** api update ([5d5fe8c](https://github.com/NanoNets/docstrange-python/commit/5d5fe8c9980e169a262eeed5601a568b8688a666))
+* **api:** api update ([f6e304a](https://github.com/NanoNets/docstrange-python/commit/f6e304ad4aea0364c89273b1a17f53cf730c9f09))
+* **api:** api update ([55c65e1](https://github.com/NanoNets/docstrange-python/commit/55c65e11f1cbfcd60df5ec2d65c503330bc29a3c))
+* **api:** api update ([0cb4863](https://github.com/NanoNets/docstrange-python/commit/0cb48631aa0c08788f26a3abb051fef2c12aaa20))
+* **api:** api update ([cee4e51](https://github.com/NanoNets/docstrange-python/commit/cee4e51ef55edee2402626eeb04dfe74f41c4676))
+* **api:** api update ([9cfaf51](https://github.com/NanoNets/docstrange-python/commit/9cfaf51d7c188ab63fc6352d6a689e5c0a8dbe58))
+* **api:** api update ([9da26d4](https://github.com/NanoNets/docstrange-python/commit/9da26d4a173539f2a94608833b3002c5bf4d7f37))
+* **api:** api update ([a3d7c23](https://github.com/NanoNets/docstrange-python/commit/a3d7c23e4f6027cb4eabb422a08aae1f1f4db511))
+* **api:** api update ([a1ada95](https://github.com/NanoNets/docstrange-python/commit/a1ada95fffb116ab7c5a59f5d69eb24fa69f5827))
+* **api:** api update ([3d12679](https://github.com/NanoNets/docstrange-python/commit/3d12679a9c3ff3c58563bc17c15fab514dd3aa36))
+
+
+### Chores
+
+* **internal:** fix lint error on Python 3.14 ([e1b836c](https://github.com/NanoNets/docstrange-python/commit/e1b836c1338d0c34eeae2156a19ae1a9a68b9269))
+* update SDK settings ([8e487a0](https://github.com/NanoNets/docstrange-python/commit/8e487a02975b8b2873fdcbf51df22a2c7f04275d))
+* update SDK settings ([e231259](https://github.com/NanoNets/docstrange-python/commit/e231259dabdfcb1ee3d818f5720d484dbc48d7fd))
+* update SDK settings ([ec90172](https://github.com/NanoNets/docstrange-python/commit/ec90172800803c48e72e6105e265ccd757f80314))
+* update SDK settings ([c2d9004](https://github.com/NanoNets/docstrange-python/commit/c2d9004668a9eb79f6cc5a19879ed8d9928f316f))
+* update SDK settings ([2c177c7](https://github.com/NanoNets/docstrange-python/commit/2c177c784f8492fd77ae6371e2cf229f5fd6d151))
+* update SDK settings ([19fe0dd](https://github.com/NanoNets/docstrange-python/commit/19fe0ddf024bf761e50dc300b02903068ea3a2cf))
diff --git a/pyproject.toml b/pyproject.toml
index 0d11a7e..de2c1db 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "docstrange-api"
-version = "0.0.1"
+version = "0.1.0"
description = "The official Python library for the docstrange API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/docstrange/_version.py b/src/docstrange/_version.py
index fc8a3e5..3393853 100644
--- a/src/docstrange/_version.py
+++ b/src/docstrange/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "docstrange"
-__version__ = "0.0.1" # x-release-please-version
+__version__ = "0.1.0" # x-release-please-version