diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fe87cd91..cc51f6f8 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.43.0" + ".": "0.44.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 80816b46..026befc1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 62 +configured_endpoints: 63 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-8a9abf45fe3e0db8c9ba59803ff9ef4ce5d0bb780765d3c1a9587dde2a8d6c93.yml openapi_spec_hash: 0f3af27e4fc27bcbfbb17f0a2c45c060 -config_hash: 6fa04d08d4e1a3a45f562e37fab0ea71 +config_hash: 557219db19e51f791a1727eac53d506c diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe4e4fa..3b6a53c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.44.0 (2025-12-17) + +Full Changelog: [v0.43.0...v0.44.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.43.0...v0.44.0) + +### Features + +* **api:** manual updates ([06e7106](https://github.com/mixedbread-ai/mixedbread-python/commit/06e7106befea286d1f7e05268f08fe824aed3631)) + ## 0.43.0 (2025-12-17) Full Changelog: [v0.42.0...v0.43.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.42.0...v0.43.0) diff --git a/api.md b/api.md index 4332059c..090bbc6c 100644 --- a/api.md +++ b/api.md @@ -122,6 +122,7 @@ Methods: - client.stores.files.create(store_identifier, \*\*params) -> StoreFile - client.stores.files.retrieve(file_identifier, \*, store_identifier, \*\*params) -> StoreFile +- client.stores.files.update(file_identifier, \*, store_identifier, \*\*params) -> StoreFile - client.stores.files.list(store_identifier, \*\*params) -> FileListResponse - client.stores.files.delete(file_identifier, \*, store_identifier) -> FileDeleteResponse - client.stores.files.search(\*\*params) -> FileSearchResponse diff --git a/pyproject.toml b/pyproject.toml index 00a3fb3a..2cba3dd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mixedbread" -version = "0.43.0" +version = "0.44.0" 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 3f42a5c2..1e202f99 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.43.0" # x-release-please-version +__version__ = "0.44.0" # x-release-please-version diff --git a/src/mixedbread/resources/stores/files.py b/src/mixedbread/resources/stores/files.py index 2f303d68..cd131e06 100644 --- a/src/mixedbread/resources/stores/files.py +++ b/src/mixedbread/resources/stores/files.py @@ -3,7 +3,7 @@ from __future__ import annotations import functools -from typing import Any, List, Union, Iterable, Optional +from typing import Any, Dict, List, Union, Iterable, Optional import httpx @@ -19,7 +19,13 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.stores import file_list_params, file_create_params, file_search_params, file_retrieve_params +from ...types.stores import ( + file_list_params, + file_create_params, + file_search_params, + file_update_params, + file_retrieve_params, +) from ...types.stores.store_file import StoreFile from ...types.stores.store_file_status import StoreFileStatus from ...types.stores.file_list_response import FileListResponse @@ -173,6 +179,55 @@ def retrieve( cast_to=StoreFile, ) + def update( + self, + file_identifier: str, + *, + store_identifier: str, + metadata: Optional[Dict[str, object]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> StoreFile: + """ + Update metadata on a file within a store. + + Args: store_identifier: The ID or name of the store. file_identifier: The ID or + name of the file to update. update_params: Metadata update payload. + + Returns: StoreFile: The updated file details. + + Args: + store_identifier: The ID or name of the store + + file_identifier: The ID or name of the file to update + + metadata: Updated metadata for the file + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not store_identifier: + raise ValueError(f"Expected a non-empty value for `store_identifier` but received {store_identifier!r}") + if not file_identifier: + raise ValueError(f"Expected a non-empty value for `file_identifier` but received {file_identifier!r}") + return self._patch( + f"/v1/stores/{store_identifier}/files/{file_identifier}", + body=maybe_transform({"metadata": metadata}, file_update_params.FileUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=StoreFile, + ) + def list( self, store_identifier: str, @@ -663,6 +718,55 @@ async def retrieve( cast_to=StoreFile, ) + async def update( + self, + file_identifier: str, + *, + store_identifier: str, + metadata: Optional[Dict[str, object]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> StoreFile: + """ + Update metadata on a file within a store. + + Args: store_identifier: The ID or name of the store. file_identifier: The ID or + name of the file to update. update_params: Metadata update payload. + + Returns: StoreFile: The updated file details. + + Args: + store_identifier: The ID or name of the store + + file_identifier: The ID or name of the file to update + + metadata: Updated metadata for the file + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not store_identifier: + raise ValueError(f"Expected a non-empty value for `store_identifier` but received {store_identifier!r}") + if not file_identifier: + raise ValueError(f"Expected a non-empty value for `file_identifier` but received {file_identifier!r}") + return await self._patch( + f"/v1/stores/{store_identifier}/files/{file_identifier}", + body=await async_maybe_transform({"metadata": metadata}, file_update_params.FileUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=StoreFile, + ) + async def list( self, store_identifier: str, @@ -1019,6 +1123,9 @@ def __init__(self, files: FilesResource) -> None: self.retrieve = to_raw_response_wrapper( files.retrieve, ) + self.update = to_raw_response_wrapper( + files.update, + ) self.list = to_raw_response_wrapper( files.list, ) @@ -1040,6 +1147,9 @@ def __init__(self, files: AsyncFilesResource) -> None: self.retrieve = async_to_raw_response_wrapper( files.retrieve, ) + self.update = async_to_raw_response_wrapper( + files.update, + ) self.list = async_to_raw_response_wrapper( files.list, ) @@ -1061,6 +1171,9 @@ def __init__(self, files: FilesResource) -> None: self.retrieve = to_streamed_response_wrapper( files.retrieve, ) + self.update = to_streamed_response_wrapper( + files.update, + ) self.list = to_streamed_response_wrapper( files.list, ) @@ -1082,6 +1195,9 @@ def __init__(self, files: AsyncFilesResource) -> None: self.retrieve = async_to_streamed_response_wrapper( files.retrieve, ) + self.update = async_to_streamed_response_wrapper( + files.update, + ) self.list = async_to_streamed_response_wrapper( files.list, ) diff --git a/src/mixedbread/types/stores/__init__.py b/src/mixedbread/types/stores/__init__.py index 3dee7dac..50862586 100644 --- a/src/mixedbread/types/stores/__init__.py +++ b/src/mixedbread/types/stores/__init__.py @@ -9,6 +9,7 @@ from .file_create_params import FileCreateParams as FileCreateParams from .file_list_response import FileListResponse as FileListResponse from .file_search_params import FileSearchParams as FileSearchParams +from .file_update_params import FileUpdateParams as FileUpdateParams from .file_delete_response import FileDeleteResponse as FileDeleteResponse from .file_retrieve_params import FileRetrieveParams as FileRetrieveParams from .file_search_response import FileSearchResponse as FileSearchResponse diff --git a/src/mixedbread/types/stores/file_update_params.py b/src/mixedbread/types/stores/file_update_params.py new file mode 100644 index 00000000..d8dc45e7 --- /dev/null +++ b/src/mixedbread/types/stores/file_update_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Optional +from typing_extensions import Required, TypedDict + +__all__ = ["FileUpdateParams"] + + +class FileUpdateParams(TypedDict, total=False): + store_identifier: Required[str] + """The ID or name of the store""" + + metadata: Optional[Dict[str, object]] + """Updated metadata for the file""" diff --git a/tests/api_resources/stores/test_files.py b/tests/api_resources/stores/test_files.py index 16f130cf..df1c6598 100644 --- a/tests/api_resources/stores/test_files.py +++ b/tests/api_resources/stores/test_files.py @@ -134,6 +134,63 @@ def test_path_params_retrieve(self, client: Mixedbread) -> None: store_identifier="store_identifier", ) + @parametrize + def test_method_update(self, client: Mixedbread) -> None: + file = client.stores.files.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + ) + assert_matches_type(StoreFile, file, path=["response"]) + + @parametrize + def test_method_update_with_all_params(self, client: Mixedbread) -> None: + file = client.stores.files.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + metadata={"foo": "bar"}, + ) + assert_matches_type(StoreFile, file, path=["response"]) + + @parametrize + def test_raw_response_update(self, client: Mixedbread) -> None: + response = client.stores.files.with_raw_response.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = response.parse() + assert_matches_type(StoreFile, file, path=["response"]) + + @parametrize + def test_streaming_response_update(self, client: Mixedbread) -> None: + with client.stores.files.with_streaming_response.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = response.parse() + assert_matches_type(StoreFile, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update(self, client: Mixedbread) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"): + client.stores.files.with_raw_response.update( + file_identifier="file_identifier", + store_identifier="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_identifier` but received ''"): + client.stores.files.with_raw_response.update( + file_identifier="", + store_identifier="store_identifier", + ) + @parametrize def test_method_list(self, client: Mixedbread) -> None: file = client.stores.files.list( @@ -414,6 +471,63 @@ async def test_path_params_retrieve(self, async_client: AsyncMixedbread) -> None store_identifier="store_identifier", ) + @parametrize + async def test_method_update(self, async_client: AsyncMixedbread) -> None: + file = await async_client.stores.files.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + ) + assert_matches_type(StoreFile, file, path=["response"]) + + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncMixedbread) -> None: + file = await async_client.stores.files.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + metadata={"foo": "bar"}, + ) + assert_matches_type(StoreFile, file, path=["response"]) + + @parametrize + async def test_raw_response_update(self, async_client: AsyncMixedbread) -> None: + response = await async_client.stores.files.with_raw_response.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + file = await response.parse() + assert_matches_type(StoreFile, file, path=["response"]) + + @parametrize + async def test_streaming_response_update(self, async_client: AsyncMixedbread) -> None: + async with async_client.stores.files.with_streaming_response.update( + file_identifier="file_identifier", + store_identifier="store_identifier", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + file = await response.parse() + assert_matches_type(StoreFile, file, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update(self, async_client: AsyncMixedbread) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `store_identifier` but received ''"): + await async_client.stores.files.with_raw_response.update( + file_identifier="file_identifier", + store_identifier="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_identifier` but received ''"): + await async_client.stores.files.with_raw_response.update( + file_identifier="", + store_identifier="store_identifier", + ) + @parametrize async def test_method_list(self, async_client: AsyncMixedbread) -> None: file = await async_client.stores.files.list(