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..3d2ac0b --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.1.0" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 2d4c88e..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: e00c8070feb190d613cf77e700818950 +config_hash: b1979c16c99baf59cbbf8c7944a47297 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/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..917f116 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Docstrange Python API library -[![PyPI version](https://img.shields.io/pypi/v/docstrange.svg?label=pypi%20(stable))](https://pypi.org/project/docstrange/) +[![PyPI version](https://img.shields.io/pypi/v/docstrange-api.svg?label=pypi%20(stable))](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, @@ -11,18 +11,15 @@ 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 ```sh -# install from this staging repo -pip install git+ssh://git@github.com/stainless-sdks/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). @@ -35,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) @@ -61,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) @@ -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 this staging repo -pip install 'docstrange[aiohttp] @ git+ssh://git@github.com/stainless-sdks/docstrange-python.git' +# install from PyPI +pip install docstrange-api[aiohttp] ``` Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`: @@ -97,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) @@ -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)`. @@ -125,7 +183,7 @@ from docstrange import Docstrange client = Docstrange() -client.api.v1.extract.sync( +client.extract.sync( output_format="markdown", file=Path("/path/to/file"), ) @@ -149,7 +207,7 @@ from docstrange import Docstrange client = Docstrange() try: - client.api.v1.extract.sync( + client.extract.sync( output_format="markdown", ) except docstrange.APIConnectionError as e: @@ -194,7 +252,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", ) ``` @@ -219,7 +277,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", ) ``` @@ -262,18 +320,18 @@ 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) ``` -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` @@ -282,7 +340,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")) @@ -379,7 +437,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/api.md b/api.md index 3b4eeb8..df1bce4 100644 --- a/api.md +++ b/api.md @@ -1,60 +1,64 @@ -# API - -## V1 - -### Extract +# Extract Types: ```python -from docstrange.types.api.v1 import ( - ExtractRequestBody, +from docstrange.types import ( + BatchExtractResponse, ExtractResponse, ExtractionFormatResult, - ExtractBatchResponse, + ExtractionMetadata, + ExtractionResult, 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) -> SyncPageNumberPagination[ExtractResponse] -### Classify +# Classify Types: ```python -from docstrange.types.api.v1 import ( +from docstrange.types import ( + BatchClassifyResponse, + 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/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..de2c1db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] -name = "docstrange" -version = "0.0.1" +name = "docstrange-api" +version = "0.1.0" description = "The official Python library for the docstrange API" dynamic = ["readme"] license = "Apache-2.0" @@ -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/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/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/_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/_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: diff --git a/src/docstrange/_version.py b/src/docstrange/_version.py index 7b3567a..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" +__version__ = "0.1.0" # x-release-please-version 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 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 2156132..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/stainless-sdks/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/stainless-sdks/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/stainless-sdks/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/stainless-sdks/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 496bd48..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/stainless-sdks/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/stainless-sdks/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/stainless-sdks/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/stainless-sdks/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/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) diff --git a/src/docstrange/resources/api/v1/classify.py b/src/docstrange/resources/classify.py similarity index 89% rename from src/docstrange/resources/api/v1/classify.py rename to src/docstrange/resources/classify.py index b31e9d9..797bf65 100644 --- a/src/docstrange/resources/api/v1/classify.py +++ b/src/docstrange/resources/classify.py @@ -6,28 +6,20 @@ 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 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.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"] @@ -39,7 +31,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 +40,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) @@ -63,7 +55,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). @@ -101,7 +93,7 @@ def batch( 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 +107,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. @@ -155,7 +147,7 @@ def sync( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ClassifySyncResponse, + cast_to=ClassifyResponse, ) @@ -166,7 +158,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 +167,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) @@ -190,7 +182,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). @@ -228,7 +220,7 @@ async def batch( 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 +234,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. @@ -282,7 +274,7 @@ async def sync( 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 88% rename from src/docstrange/resources/api/v1/extract/extract.py rename to src/docstrange/resources/extract/extract.py index adc79ea..5a0f0fa 100644 --- a/src/docstrange/resources/api/v1/extract/extract.py +++ b/src/docstrange/resources/extract/extract.py @@ -7,6 +7,7 @@ import httpx +from ...types import extract_sync_params, extract_async_params, extract_batch_params, extract_stream_params from .results import ( ResultsResource, AsyncResultsResource, @@ -15,7 +16,7 @@ ResultsResourceWithStreamingResponse, AsyncResultsResourceWithStreamingResponse, ) -from ....._types import ( +from ..._types import ( Body, Omit, Query, @@ -26,21 +27,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 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 ....._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"] @@ -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) @@ -124,26 +124,28 @@ def async_( 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( - { - "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, - ), + 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 ), @@ -166,7 +168,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 @@ -208,7 +210,7 @@ def batch( 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( @@ -363,26 +365,28 @@ def sync( 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( - { - "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, - ), + 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 ), @@ -401,7 +405,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 +414,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) @@ -469,26 +473,28 @@ async def async_( 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( - { - "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, - ), + 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 ), @@ -511,7 +517,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 @@ -553,7 +559,7 @@ async def batch( 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( @@ -708,26 +714,28 @@ async def sync( 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( - { - "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, - ), + 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 ), diff --git a/src/docstrange/resources/api/v1/extract/results.py b/src/docstrange/resources/extract/results.py similarity index 86% rename from src/docstrange/resources/api/v1/extract/results.py rename to src/docstrange/resources/extract/results.py index 434ba0b..1533ac2 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 ...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"] @@ -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) @@ -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: + ) -> 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=ResultListResponse, + model=ExtractResponse, ) @@ -141,7 +142,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 +151,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) @@ -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, - ) -> ResultListResponse: + ) -> 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=ResultListResponse, + model=ExtractResponse, ) 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 75% rename from tests/api_resources/api/v1/extract/test_results.py rename to tests/api_resources/extract/test_results.py index 5c842cc..ee1d5f5 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.pagination import SyncPageNumberPagination, AsyncPageNumberPagination 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(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.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(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.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(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.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(SyncPageNumberPagination[ExtractResponse], 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(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.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(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.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(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.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(AsyncPageNumberPagination[ExtractResponse], 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"} ) 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 = [