From da4d3b62d69a910983fc0ff1b928aa36026e7608 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 11:28:11 +0000 Subject: [PATCH 1/3] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1b0430f8..1595cfa2 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 61 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-34b8fc657696023cc3a74eee6febe0d2fc0decda668f874bfa42abe6222d8566.yml -openapi_spec_hash: dcd015b362c3fcb4ef449606a8027873 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-2b47fdec8c177fb55b563457ef8e3e972177a8d395a341b77112a26909e98d43.yml +openapi_spec_hash: d818396c05166e73b409c28893e790b7 config_hash: 2de40c343cf7b242d5925e3405ee8908 From 153269ec4c3f5ae1d4d7353d592b1a6bdcc58b01 Mon Sep 17 00:00:00 2001 From: Joel Dierkes Date: Wed, 1 Oct 2025 17:43:29 +0200 Subject: [PATCH 2/3] chore: add the stores helper functions --- src/mixedbread/resources/stores/files.py | 222 ++++++++++++++++++++++- 1 file changed, 220 insertions(+), 2 deletions(-) diff --git a/src/mixedbread/resources/stores/files.py b/src/mixedbread/resources/stores/files.py index 9fc14bb6..8b70d26e 100644 --- a/src/mixedbread/resources/stores/files.py +++ b/src/mixedbread/resources/stores/files.py @@ -2,11 +2,13 @@ from __future__ import annotations -from typing import List, Union, Iterable, Optional +import functools +from typing import Any, List, Union, Iterable, Optional import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given +from ...lib import polling +from ..._types import Body, FileTypes, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -340,6 +342,112 @@ def search( cast_to=FileSearchResponse, ) + def poll( + self, + file_id: str, + *, + store_identifier: str, + poll_interval_ms: int | NotGiven = not_given, + poll_timeout_ms: float | NotGiven = not_given, + **kwargs: Any, + ) -> StoreFile: + """ + Poll for a file's status until it reaches a terminal state. + Args: + file_id: The ID of the file to poll + store_identifier: The ID of the store + poll_interval_ms: The interval between polls in milliseconds + poll_timeout_ms: The maximum time to poll for in milliseconds + Returns: + The file object once it reaches a terminal state + """ + polling_interval_ms = poll_interval_ms or 500 + polling_timeout_ms = poll_timeout_ms or None + return polling.poll( + fn=functools.partial(self.retrieve, file_id, store_identifier=store_identifier, **kwargs), + condition=lambda res: res.status == "completed" or res.status == "failed" or res.status == "cancelled", + interval_seconds=polling_interval_ms / 1000, + timeout_seconds=polling_timeout_ms / 1000 if polling_timeout_ms else None, + ) + + def create_and_poll( + self, + file_id: str, + *, + store_identifier: str, + metadata: Optional[object] | NotGiven = not_given, + experimental: file_create_params.Experimental | Omit = omit, + poll_interval_ms: int | NotGiven = not_given, + poll_timeout_ms: float | NotGiven = not_given, + **kwargs: Any, + ) -> StoreFile: + """ + Attach a file to the given store and wait for it to be processed. + Args: + file_id: The ID of the file to poll + store_identifier: The ID of the store + metadata: The metadata to attach to the file + poll_interval_ms: The interval between polls in milliseconds + poll_timeout_ms: The maximum time to poll for in milliseconds + Returns: + The file object once it reaches a terminal state + """ + self.create( + store_identifier=store_identifier, file_id=file_id, metadata=metadata, experimental=experimental, **kwargs + ) + return self.poll( + file_id, + store_identifier=store_identifier, + poll_interval_ms=poll_interval_ms, + poll_timeout_ms=poll_timeout_ms, + **kwargs, + ) + + def upload( + self, + *, + store_identifier: str, + file: FileTypes, + metadata: Optional[object] | Omit = omit, + experimental: file_create_params.Experimental | Omit = omit, + **kwargs: Any, + ) -> StoreFile: + """Upload a file to the `files` API and then attach it to the given store. + Note the file will be asynchronously processed (you can use the alternative + polling helper method to wait for processing to complete). + """ + file_obj = self._client.files.create(file=file, **kwargs) + return self.create( + store_identifier=store_identifier, + file_id=file_obj.id, + metadata=metadata, + experimental=experimental, + **kwargs, + ) + + def upload_and_poll( + self, + *, + store_identifier: str, + file: FileTypes, + metadata: Optional[object] | NotGiven = not_given, + experimental: file_create_params.Experimental | Omit = omit, + poll_interval_ms: int | NotGiven = not_given, + poll_timeout_ms: float | NotGiven = not_given, + **kwargs: Any, + ) -> StoreFile: + """Add a file to a store and poll until processing is complete.""" + file_obj = self._client.files.create(file=file, **kwargs) + return self.create_and_poll( + store_identifier=store_identifier, + file_id=file_obj.id, + metadata=metadata, + experimental=experimental, + poll_interval_ms=poll_interval_ms, + poll_timeout_ms=poll_timeout_ms, + **kwargs, + ) + class AsyncFilesResource(AsyncAPIResource): @cached_property @@ -656,6 +764,116 @@ async def search( cast_to=FileSearchResponse, ) + async def poll( + self, + file_id: str, + *, + store_identifier: str, + poll_interval_ms: int | NotGiven = not_given, + poll_timeout_ms: float | NotGiven = not_given, + **kwargs: Any, + ) -> StoreFile: + """ + Poll for a file's status until it reaches a terminal state. + Args: + file_id: The ID of the file to poll + store_identifier: The ID of the store + poll_interval_ms: The interval between polls in milliseconds + poll_timeout_ms: The maximum time to poll for in milliseconds + Returns: + The file object once it reaches a terminal state + """ + polling_interval_ms = poll_interval_ms or 500 + polling_timeout_ms = poll_timeout_ms or None + return await polling.poll_async( + fn=functools.partial(self.retrieve, file_id, store_identifier=store_identifier, **kwargs), + condition=lambda res: res.status == "completed" or res.status == "failed" or res.status == "cancelled", + interval_seconds=polling_interval_ms / 1000, + timeout_seconds=polling_timeout_ms / 1000 if polling_timeout_ms else None, + ) + + async def create_and_poll( + self, + file_id: str, + *, + store_identifier: str, + metadata: Optional[object] | NotGiven = not_given, + experimental: file_create_params.Experimental | Omit = omit, + poll_interval_ms: int | NotGiven = not_given, + poll_timeout_ms: float | NotGiven = not_given, + **kwargs: Any, + ) -> StoreFile: + """ + Attach a file to the given vector store and wait for it to be processed. + Args: + file_id: The ID of the file to poll + store_identifier: The ID of the store + metadata: The metadata to attach to the file + poll_interval_ms: The interval between polls in milliseconds + poll_timeout_ms: The maximum time to poll for in milliseconds + Returns: + The file object once it reaches a terminal state + """ + await self.create( + store_identifier=store_identifier, + file_id=file_id, + metadata=metadata, + experimental=experimental, + **kwargs, + ) + return await self.poll( + file_id, + store_identifier=store_identifier, + poll_interval_ms=poll_interval_ms, + poll_timeout_ms=poll_timeout_ms, + **kwargs, + ) + + async def upload( + self, + *, + store_identifier: str, + file: FileTypes, + metadata: Optional[object] | NotGiven = not_given, + experimental: file_create_params.Experimental | Omit = omit, + **kwargs: Any, + ) -> StoreFile: + """Upload a file to the `files` API and then attach it to the given vector store. + Note the file will be asynchronously processed (you can use the alternative + polling helper method to wait for processing to complete). + """ + file_obj = await self._client.files.create(file=file, **kwargs) + return await self.create( + store_identifier=store_identifier, + file_id=file_obj.id, + metadata=metadata, + experimental=experimental, + **kwargs, + ) + + async def upload_and_poll( + self, + *, + store_identifier: str, + file: FileTypes, + metadata: Optional[object] | NotGiven = not_given, + experimental: file_create_params.Experimental | Omit = omit, + poll_interval_ms: int | NotGiven = not_given, + poll_timeout_ms: float | NotGiven = not_given, + **kwargs: Any, + ) -> StoreFile: + """Add a file to a store and poll until processing is complete.""" + file_obj = await self._client.files.create(file=file, **kwargs) + return await self.create_and_poll( + store_identifier=store_identifier, + file_id=file_obj.id, + metadata=metadata, + experimental=experimental, + poll_interval_ms=poll_interval_ms, + poll_timeout_ms=poll_timeout_ms, + **kwargs, + ) + class FilesResourceWithRawResponse: def __init__(self, files: FilesResource) -> None: From 4e6b968f5fdca33ef1e676ca04b0bf27d1548a7a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:44:44 +0000 Subject: [PATCH 3/3] release: 0.32.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ pyproject.toml | 2 +- src/mixedbread/_version.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f04d0896..12d488c3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.32.0" + ".": "0.32.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a2bac45..a1923082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.32.1 (2025-10-01) + +Full Changelog: [v0.32.0...v0.32.1](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.32.0...v0.32.1) + +### Chores + +* add the stores helper functions ([153269e](https://github.com/mixedbread-ai/mixedbread-python/commit/153269ec4c3f5ae1d4d7353d592b1a6bdcc58b01)) + ## 0.32.0 (2025-10-01) Full Changelog: [v0.31.0...v0.32.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.31.0...v0.32.0) diff --git a/pyproject.toml b/pyproject.toml index f9ec7480..4fa80431 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mixedbread" -version = "0.32.0" +version = "0.32.1" description = "The official Python library for the Mixedbread API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/mixedbread/_version.py b/src/mixedbread/_version.py index 6c91f797..7ffd30e4 100644 --- a/src/mixedbread/_version.py +++ b/src/mixedbread/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "mixedbread" -__version__ = "0.32.0" # x-release-please-version +__version__ = "0.32.1" # x-release-please-version