From fd4e3479579f62d6f4ef1c463d13bc1909ed2ad2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:13:35 +0000 Subject: [PATCH 1/5] feat(api): api update --- .stats.yml | 4 +- src/getimg/resources/images.py | 6 ++ src/getimg/resources/models.py | 6 +- src/getimg/resources/videos/generations.py | 12 ++-- src/getimg/types/image_generate_params.py | 12 +++- src/getimg/types/model_list_response.py | 60 ++++++++++++++++++- .../types/videos/generation_create_params.py | 8 ++- .../videos/generation_retrieve_response.py | 2 +- .../api_resources/videos/test_generations.py | 12 ++-- 9 files changed, 99 insertions(+), 23 deletions(-) diff --git a/.stats.yml b/.stats.yml index de779ca..dafe84e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-5655d05e420e9ee5f197024dca432b82756e2702c6293dc2d3150c58c032ab6e.yml -openapi_spec_hash: b217b38232f6d021b72a9d15fd5061e9 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-501595b3c3450dca589c65bd07e9da1e64e805a2d1ec2cae37c80b082dd470f0.yml +openapi_spec_hash: 53a16dc5329902608ef3281325c3961a config_hash: ff9d4a2e74425c1066cc2c21a9dc1315 diff --git a/src/getimg/resources/images.py b/src/getimg/resources/images.py index 7a1f799..2a8a6f5 100644 --- a/src/getimg/resources/images.py +++ b/src/getimg/resources/images.py @@ -74,6 +74,9 @@ def generate( aspect_ratio: Optional output aspect ratio. See [supported values by model](https://getimg.ai/app/developer/models). + images: Optional reference images. See + [supported values by model](https://getimg.ai/app/developer/models). + output_format: Output image format. resolution: Optional output resolution. See @@ -157,6 +160,9 @@ async def generate( aspect_ratio: Optional output aspect ratio. See [supported values by model](https://getimg.ai/app/developer/models). + images: Optional reference images. See + [supported values by model](https://getimg.ai/app/developer/models). + output_format: Output image format. resolution: Optional output resolution. See diff --git a/src/getimg/resources/models.py b/src/getimg/resources/models.py index fc4ad71..270c3c4 100644 --- a/src/getimg/resources/models.py +++ b/src/getimg/resources/models.py @@ -57,7 +57,8 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ModelListResponse: """ - List available developer models for the authenticated project. + List the models available to your project with their supported parameters and + pricing. Args: type: Optional model type filter. @@ -117,7 +118,8 @@ async def list( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ModelListResponse: """ - List available developer models for the authenticated project. + List the models available to your project with their supported parameters and + pricing. Args: type: Optional model type filter. diff --git a/src/getimg/resources/videos/generations.py b/src/getimg/resources/videos/generations.py index bd19aee..24536f1 100644 --- a/src/getimg/resources/videos/generations.py +++ b/src/getimg/resources/videos/generations.py @@ -124,10 +124,8 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> GenerationRetrieveResponse: - """Retrieve the current status for a video generation request. - - The response status - is `pending`, `failed`, or `completed`. + """ + Retrieve the current status of a video generation request. Args: extra_headers: Send extra headers @@ -254,10 +252,8 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> GenerationRetrieveResponse: - """Retrieve the current status for a video generation request. - - The response status - is `pending`, `failed`, or `completed`. + """ + Retrieve the current status of a video generation request. Args: extra_headers: Send extra headers diff --git a/src/getimg/types/image_generate_params.py b/src/getimg/types/image_generate_params.py index 4c7deb1..9f46f60 100644 --- a/src/getimg/types/image_generate_params.py +++ b/src/getimg/types/image_generate_params.py @@ -22,6 +22,10 @@ class ImageGenerateParams(TypedDict, total=False): """ images: Iterable[Image] + """Optional reference images. + + See [supported values by model](https://getimg.ai/app/developer/models). + """ output_format: Literal["png", "jpeg", "webp"] """Output image format.""" @@ -35,4 +39,10 @@ class ImageGenerateParams(TypedDict, total=False): class Image(TypedDict, total=False): url: Required[str] - """Publicly accessible reference image URL.""" + """ + Publicly accessible HTTPS image URL or a base64 data URL + (`data:image/png;base64,...`). Inline formats: PNG, JPEG, and WebP. Bare base64 + is not accepted. The default decoded image limit is 10 MiB; the entire JSON + request must fit within 25 MiB. Base64 adds approximately 33% to the original + file size. + """ diff --git a/src/getimg/types/model_list_response.py b/src/getimg/types/model_list_response.py index 7717a08..1f3de93 100644 --- a/src/getimg/types/model_list_response.py +++ b/src/getimg/types/model_list_response.py @@ -1,12 +1,45 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal, TypeAlias from .._models import BaseModel -__all__ = ["ModelListResponse", "ModelListResponseItem"] +__all__ = [ + "ModelListResponse", + "ModelListResponseItem", + "ModelListResponseItemPricing", + "ModelListResponseItemPricingRate", +] + + +class ModelListResponseItemPricingRate(BaseModel): + billable_unit: str + """Unit billed, such as image or video_second.""" + + resolution: Optional[str] = None + """Resolution this rate applies to, or null for a resolution-independent rate.""" + + sound: Literal["sound_on", "sound_off", "not_applicable"] + """ + Sound setting this rate applies to; not_applicable also serves as a video + fallback. + """ + + unit_price: str + """USD price per billable unit, represented as a decimal string.""" + + +class ModelListResponseItemPricing(BaseModel): + currency: Literal["USD"] + + rates: List[ModelListResponseItemPricingRate] + """Currently effective catalog rates, ordered by unit price. + + Empty when no active rates are configured; this does not mean generation is + free. + """ class ModelListResponseItem(BaseModel): @@ -19,6 +52,29 @@ class ModelListResponseItem(BaseModel): name: str """The model display name.""" + pricing: ModelListResponseItemPricing + + supported_aspect_ratios: List[str] + """Supported aspect ratios in default order; the first is used when omitted.""" + + supported_durations: List[float] + """Supported durations in seconds; empty for image models. + + The first is the default. + """ + + supported_references: Dict[str, int] + """ + Maximum reference count per supported role (reference_image, first_frame, + last_frame). + """ + + supported_resolutions: List[str] + """Supported resolutions in default order; the first is used when omitted.""" + + supports_sound: bool + """Whether sound generation is supported.""" + type: Literal["image", "video"] """The generation type supported by the model.""" diff --git a/src/getimg/types/videos/generation_create_params.py b/src/getimg/types/videos/generation_create_params.py index b6488ac..7332f9e 100644 --- a/src/getimg/types/videos/generation_create_params.py +++ b/src/getimg/types/videos/generation_create_params.py @@ -48,4 +48,10 @@ class Image(TypedDict, total=False): """The role of the reference image.""" url: Required[str] - """Publicly accessible reference image URL.""" + """ + Publicly accessible HTTPS image URL or a base64 data URL + (`data:image/png;base64,...`). Inline formats: PNG, JPEG, and WebP. Bare base64 + is not accepted. The default decoded image limit is 10 MiB; the entire JSON + request must fit within 25 MiB. Base64 adds approximately 33% to the original + file size. + """ diff --git a/src/getimg/types/videos/generation_retrieve_response.py b/src/getimg/types/videos/generation_retrieve_response.py index e5a7d74..c3f52c0 100644 --- a/src/getimg/types/videos/generation_retrieve_response.py +++ b/src/getimg/types/videos/generation_retrieve_response.py @@ -61,7 +61,7 @@ class VideoGenerationCompletedResponseData(BaseModel): """The frame rate of the video.""" has_sound: Optional[bool] = None - """Whether the video has and audio track.""" + """Whether the video has an audio track.""" height: Optional[int] = None """The height of the video in pixels.""" diff --git a/tests/api_resources/videos/test_generations.py b/tests/api_resources/videos/test_generations.py index 60f84af..1fc6399 100644 --- a/tests/api_resources/videos/test_generations.py +++ b/tests/api_resources/videos/test_generations.py @@ -77,7 +77,7 @@ def test_streaming_response_create(self, client: GetimgAI) -> None: @parametrize def test_method_retrieve(self, client: GetimgAI) -> None: generation = client.videos.generations.retrieve( - "x", + "req-01HXYZVIDEO1234", ) assert_matches_type(GenerationRetrieveResponse, generation, path=["response"]) @@ -85,7 +85,7 @@ def test_method_retrieve(self, client: GetimgAI) -> None: @parametrize def test_raw_response_retrieve(self, client: GetimgAI) -> None: response = client.videos.generations.with_raw_response.retrieve( - "x", + "req-01HXYZVIDEO1234", ) assert response.is_closed is True @@ -97,7 +97,7 @@ def test_raw_response_retrieve(self, client: GetimgAI) -> None: @parametrize def test_streaming_response_retrieve(self, client: GetimgAI) -> None: with client.videos.generations.with_streaming_response.retrieve( - "x", + "req-01HXYZVIDEO1234", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -181,7 +181,7 @@ async def test_streaming_response_create(self, async_client: AsyncGetimgAI) -> N @parametrize async def test_method_retrieve(self, async_client: AsyncGetimgAI) -> None: generation = await async_client.videos.generations.retrieve( - "x", + "req-01HXYZVIDEO1234", ) assert_matches_type(GenerationRetrieveResponse, generation, path=["response"]) @@ -189,7 +189,7 @@ async def test_method_retrieve(self, async_client: AsyncGetimgAI) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncGetimgAI) -> None: response = await async_client.videos.generations.with_raw_response.retrieve( - "x", + "req-01HXYZVIDEO1234", ) assert response.is_closed is True @@ -201,7 +201,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncGetimgAI) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncGetimgAI) -> None: async with async_client.videos.generations.with_streaming_response.retrieve( - "x", + "req-01HXYZVIDEO1234", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" From 2b551f582c547015beadb1ba8cdea1eb8cb23025 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:15:10 +0000 Subject: [PATCH 2/5] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index dafe84e..75c2dad 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-501595b3c3450dca589c65bd07e9da1e64e805a2d1ec2cae37c80b082dd470f0.yml -openapi_spec_hash: 53a16dc5329902608ef3281325c3961a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-550d7c003196b068f6c8a1c44977563f14362bd963f475da8bcdcb360479e2b2.yml +openapi_spec_hash: 4df36400cbddc79dd3844ae2cc5153bf config_hash: ff9d4a2e74425c1066cc2c21a9dc1315 From 5ada41a959650e0e71bcbbc98e5c2124840db22c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:16:03 +0000 Subject: [PATCH 3/5] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 75c2dad..dafe84e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-550d7c003196b068f6c8a1c44977563f14362bd963f475da8bcdcb360479e2b2.yml -openapi_spec_hash: 4df36400cbddc79dd3844ae2cc5153bf +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-501595b3c3450dca589c65bd07e9da1e64e805a2d1ec2cae37c80b082dd470f0.yml +openapi_spec_hash: 53a16dc5329902608ef3281325c3961a config_hash: ff9d4a2e74425c1066cc2c21a9dc1315 From 390d72f8d53e503101dffd3f74b3914d25235905 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:18:57 +0000 Subject: [PATCH 4/5] feat(api): new endpoints --- .stats.yml | 6 +- api.md | 16 +- src/getimg/_client.py | 45 +++- src/getimg/resources/__init__.py | 14 + src/getimg/resources/billing.py | 251 ++++++++++++++++++ src/getimg/resources/models.py | 81 +++++- src/getimg/types/__init__.py | 5 + src/getimg/types/billing_list_costs_params.py | 22 ++ .../types/billing_list_costs_response.py | 33 +++ .../billing_retrieve_balance_response.py | 14 + src/getimg/types/developer_model_rate.py | 25 ++ src/getimg/types/model_list_response.py | 29 +- src/getimg/types/model_retrieve_response.py | 58 ++++ tests/api_resources/test_billing.py | 155 +++++++++++ tests/api_resources/test_models.py | 86 +++++- 15 files changed, 808 insertions(+), 32 deletions(-) create mode 100644 src/getimg/resources/billing.py create mode 100644 src/getimg/types/billing_list_costs_params.py create mode 100644 src/getimg/types/billing_list_costs_response.py create mode 100644 src/getimg/types/billing_retrieve_balance_response.py create mode 100644 src/getimg/types/developer_model_rate.py create mode 100644 src/getimg/types/model_retrieve_response.py create mode 100644 tests/api_resources/test_billing.py diff --git a/.stats.yml b/.stats.yml index dafe84e..e23cd51 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-501595b3c3450dca589c65bd07e9da1e64e805a2d1ec2cae37c80b082dd470f0.yml +configured_endpoints: 7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/webrockets/getimg-87f26d31cc003fcf1ddfdf0155297591d05e897500069b72195d4ec229681831.yml openapi_spec_hash: 53a16dc5329902608ef3281325c3961a -config_hash: ff9d4a2e74425c1066cc2c21a9dc1315 +config_hash: 06038f5bbbe41f0c0b56de45d3687512 diff --git a/api.md b/api.md index ea92542..e9c5475 100644 --- a/api.md +++ b/api.md @@ -30,9 +30,23 @@ Methods: Types: ```python -from getimg.types import ModelListResponse +from getimg.types import DeveloperModelRate, ModelRetrieveResponse, ModelListResponse ``` Methods: +- client.models.retrieve(model) -> ModelRetrieveResponse - client.models.list(\*\*params) -> ModelListResponse + +# Billing + +Types: + +```python +from getimg.types import BillingListCostsResponse, BillingRetrieveBalanceResponse +``` + +Methods: + +- client.billing.list_costs(\*\*params) -> BillingListCostsResponse +- client.billing.retrieve_balance() -> BillingRetrieveBalanceResponse diff --git a/src/getimg/_client.py b/src/getimg/_client.py index bebb117..307d3c7 100644 --- a/src/getimg/_client.py +++ b/src/getimg/_client.py @@ -36,9 +36,10 @@ ) if TYPE_CHECKING: - from .resources import images, models, videos + from .resources import images, models, videos, billing from .resources.images import ImagesResource, AsyncImagesResource from .resources.models import ModelsResource, AsyncModelsResource + from .resources.billing import BillingResource, AsyncBillingResource from .resources.videos.videos import VideosResource, AsyncVideosResource __all__ = [ @@ -137,6 +138,13 @@ def models(self) -> ModelsResource: return ModelsResource(self) + @cached_property + def billing(self) -> BillingResource: + """Developer API balance and usage costs.""" + from .resources.billing import BillingResource + + return BillingResource(self) + @cached_property def with_raw_response(self) -> GetimgAIWithRawResponse: return GetimgAIWithRawResponse(self) @@ -341,6 +349,13 @@ def models(self) -> AsyncModelsResource: return AsyncModelsResource(self) + @cached_property + def billing(self) -> AsyncBillingResource: + """Developer API balance and usage costs.""" + from .resources.billing import AsyncBillingResource + + return AsyncBillingResource(self) + @cached_property def with_raw_response(self) -> AsyncGetimgAIWithRawResponse: return AsyncGetimgAIWithRawResponse(self) @@ -487,6 +502,13 @@ def models(self) -> models.ModelsResourceWithRawResponse: return ModelsResourceWithRawResponse(self._client.models) + @cached_property + def billing(self) -> billing.BillingResourceWithRawResponse: + """Developer API balance and usage costs.""" + from .resources.billing import BillingResourceWithRawResponse + + return BillingResourceWithRawResponse(self._client.billing) + class AsyncGetimgAIWithRawResponse: _client: AsyncGetimgAI @@ -514,6 +536,13 @@ def models(self) -> models.AsyncModelsResourceWithRawResponse: return AsyncModelsResourceWithRawResponse(self._client.models) + @cached_property + def billing(self) -> billing.AsyncBillingResourceWithRawResponse: + """Developer API balance and usage costs.""" + from .resources.billing import AsyncBillingResourceWithRawResponse + + return AsyncBillingResourceWithRawResponse(self._client.billing) + class GetimgAIWithStreamedResponse: _client: GetimgAI @@ -541,6 +570,13 @@ def models(self) -> models.ModelsResourceWithStreamingResponse: return ModelsResourceWithStreamingResponse(self._client.models) + @cached_property + def billing(self) -> billing.BillingResourceWithStreamingResponse: + """Developer API balance and usage costs.""" + from .resources.billing import BillingResourceWithStreamingResponse + + return BillingResourceWithStreamingResponse(self._client.billing) + class AsyncGetimgAIWithStreamedResponse: _client: AsyncGetimgAI @@ -568,6 +604,13 @@ def models(self) -> models.AsyncModelsResourceWithStreamingResponse: return AsyncModelsResourceWithStreamingResponse(self._client.models) + @cached_property + def billing(self) -> billing.AsyncBillingResourceWithStreamingResponse: + """Developer API balance and usage costs.""" + from .resources.billing import AsyncBillingResourceWithStreamingResponse + + return AsyncBillingResourceWithStreamingResponse(self._client.billing) + Client = GetimgAI diff --git a/src/getimg/resources/__init__.py b/src/getimg/resources/__init__.py index 3dad800..0072bde 100644 --- a/src/getimg/resources/__init__.py +++ b/src/getimg/resources/__init__.py @@ -24,6 +24,14 @@ VideosResourceWithStreamingResponse, AsyncVideosResourceWithStreamingResponse, ) +from .billing import ( + BillingResource, + AsyncBillingResource, + BillingResourceWithRawResponse, + AsyncBillingResourceWithRawResponse, + BillingResourceWithStreamingResponse, + AsyncBillingResourceWithStreamingResponse, +) __all__ = [ "ImagesResource", @@ -44,4 +52,10 @@ "AsyncModelsResourceWithRawResponse", "ModelsResourceWithStreamingResponse", "AsyncModelsResourceWithStreamingResponse", + "BillingResource", + "AsyncBillingResource", + "BillingResourceWithRawResponse", + "AsyncBillingResourceWithRawResponse", + "BillingResourceWithStreamingResponse", + "AsyncBillingResourceWithStreamingResponse", ] diff --git a/src/getimg/resources/billing.py b/src/getimg/resources/billing.py new file mode 100644 index 0000000..adfbed0 --- /dev/null +++ b/src/getimg/resources/billing.py @@ -0,0 +1,251 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime + +import httpx + +from ..types import billing_list_costs_params +from .._types import Body, Query, Headers, NotGiven, 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.billing_list_costs_response import BillingListCostsResponse +from ..types.billing_retrieve_balance_response import BillingRetrieveBalanceResponse + +__all__ = ["BillingResource", "AsyncBillingResource"] + + +class BillingResource(SyncAPIResource): + """Developer API balance and usage costs.""" + + @cached_property + def with_raw_response(self) -> BillingResourceWithRawResponse: + """ + 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/getimg-ai/getimg-python#accessing-raw-response-data-eg-headers + """ + return BillingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BillingResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/getimg-ai/getimg-python#with_streaming_response + """ + return BillingResourceWithStreamingResponse(self) + + def list_costs( + self, + *, + end: Union[str, datetime], + start: Union[str, datetime], + # 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, + ) -> BillingListCostsResponse: + """ + Retrieve daily API costs and the range total for your developer project. + + Args: + end: Inclusive ISO 8601 end timestamp. Must include a time zone, fall after `start`, + and sit within 180 days of it. + + start: Inclusive ISO 8601 start timestamp. Must include a time zone. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v2/billing/costs", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "end": end, + "start": start, + }, + billing_list_costs_params.BillingListCostsParams, + ), + ), + cast_to=BillingListCostsResponse, + ) + + def retrieve_balance( + self, + *, + # 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, + ) -> BillingRetrieveBalanceResponse: + """Retrieve the current API balance shared by the API key's workspace.""" + return self._get( + "/v2/billing/balance", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BillingRetrieveBalanceResponse, + ) + + +class AsyncBillingResource(AsyncAPIResource): + """Developer API balance and usage costs.""" + + @cached_property + def with_raw_response(self) -> AsyncBillingResourceWithRawResponse: + """ + 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/getimg-ai/getimg-python#accessing-raw-response-data-eg-headers + """ + return AsyncBillingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBillingResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/getimg-ai/getimg-python#with_streaming_response + """ + return AsyncBillingResourceWithStreamingResponse(self) + + async def list_costs( + self, + *, + end: Union[str, datetime], + start: Union[str, datetime], + # 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, + ) -> BillingListCostsResponse: + """ + Retrieve daily API costs and the range total for your developer project. + + Args: + end: Inclusive ISO 8601 end timestamp. Must include a time zone, fall after `start`, + and sit within 180 days of it. + + start: Inclusive ISO 8601 start timestamp. Must include a time zone. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v2/billing/costs", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "end": end, + "start": start, + }, + billing_list_costs_params.BillingListCostsParams, + ), + ), + cast_to=BillingListCostsResponse, + ) + + async def retrieve_balance( + self, + *, + # 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, + ) -> BillingRetrieveBalanceResponse: + """Retrieve the current API balance shared by the API key's workspace.""" + return await self._get( + "/v2/billing/balance", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BillingRetrieveBalanceResponse, + ) + + +class BillingResourceWithRawResponse: + def __init__(self, billing: BillingResource) -> None: + self._billing = billing + + self.list_costs = to_raw_response_wrapper( + billing.list_costs, + ) + self.retrieve_balance = to_raw_response_wrapper( + billing.retrieve_balance, + ) + + +class AsyncBillingResourceWithRawResponse: + def __init__(self, billing: AsyncBillingResource) -> None: + self._billing = billing + + self.list_costs = async_to_raw_response_wrapper( + billing.list_costs, + ) + self.retrieve_balance = async_to_raw_response_wrapper( + billing.retrieve_balance, + ) + + +class BillingResourceWithStreamingResponse: + def __init__(self, billing: BillingResource) -> None: + self._billing = billing + + self.list_costs = to_streamed_response_wrapper( + billing.list_costs, + ) + self.retrieve_balance = to_streamed_response_wrapper( + billing.retrieve_balance, + ) + + +class AsyncBillingResourceWithStreamingResponse: + def __init__(self, billing: AsyncBillingResource) -> None: + self._billing = billing + + self.list_costs = async_to_streamed_response_wrapper( + billing.list_costs, + ) + self.retrieve_balance = async_to_streamed_response_wrapper( + billing.retrieve_balance, + ) diff --git a/src/getimg/resources/models.py b/src/getimg/resources/models.py index 270c3c4..22c317d 100644 --- a/src/getimg/resources/models.py +++ b/src/getimg/resources/models.py @@ -8,7 +8,7 @@ from ..types import model_list_params from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from .._utils import maybe_transform, async_maybe_transform +from .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( @@ -19,6 +19,7 @@ ) from .._base_client import make_request_options from ..types.model_list_response import ModelListResponse +from ..types.model_retrieve_response import ModelRetrieveResponse __all__ = ["ModelsResource", "AsyncModelsResource"] @@ -45,6 +46,39 @@ def with_streaming_response(self) -> ModelsResourceWithStreamingResponse: """ return ModelsResourceWithStreamingResponse(self) + def retrieve( + self, + model: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ModelRetrieveResponse: + """ + Retrieve a single model with its supported parameters and pricing. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not model: + raise ValueError(f"Expected a non-empty value for `model` but received {model!r}") + return self._get( + path_template("/v2/models/{model}", model=model), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ModelRetrieveResponse, + ) + def list( self, *, @@ -106,6 +140,39 @@ def with_streaming_response(self) -> AsyncModelsResourceWithStreamingResponse: """ return AsyncModelsResourceWithStreamingResponse(self) + async def retrieve( + self, + model: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ModelRetrieveResponse: + """ + Retrieve a single model with its supported parameters and pricing. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not model: + raise ValueError(f"Expected a non-empty value for `model` but received {model!r}") + return await self._get( + path_template("/v2/models/{model}", model=model), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ModelRetrieveResponse, + ) + async def list( self, *, @@ -149,6 +216,9 @@ class ModelsResourceWithRawResponse: def __init__(self, models: ModelsResource) -> None: self._models = models + self.retrieve = to_raw_response_wrapper( + models.retrieve, + ) self.list = to_raw_response_wrapper( models.list, ) @@ -158,6 +228,9 @@ class AsyncModelsResourceWithRawResponse: def __init__(self, models: AsyncModelsResource) -> None: self._models = models + self.retrieve = async_to_raw_response_wrapper( + models.retrieve, + ) self.list = async_to_raw_response_wrapper( models.list, ) @@ -167,6 +240,9 @@ class ModelsResourceWithStreamingResponse: def __init__(self, models: ModelsResource) -> None: self._models = models + self.retrieve = to_streamed_response_wrapper( + models.retrieve, + ) self.list = to_streamed_response_wrapper( models.list, ) @@ -176,6 +252,9 @@ class AsyncModelsResourceWithStreamingResponse: def __init__(self, models: AsyncModelsResource) -> None: self._models = models + self.retrieve = async_to_streamed_response_wrapper( + models.retrieve, + ) self.list = async_to_streamed_response_wrapper( models.list, ) diff --git a/src/getimg/types/__init__.py b/src/getimg/types/__init__.py index 79e1467..355a0fe 100644 --- a/src/getimg/types/__init__.py +++ b/src/getimg/types/__init__.py @@ -5,5 +5,10 @@ from .usage import Usage as Usage from .model_list_params import ModelListParams as ModelListParams from .model_list_response import ModelListResponse as ModelListResponse +from .developer_model_rate import DeveloperModelRate as DeveloperModelRate from .image_generate_params import ImageGenerateParams as ImageGenerateParams from .image_generate_response import ImageGenerateResponse as ImageGenerateResponse +from .model_retrieve_response import ModelRetrieveResponse as ModelRetrieveResponse +from .billing_list_costs_params import BillingListCostsParams as BillingListCostsParams +from .billing_list_costs_response import BillingListCostsResponse as BillingListCostsResponse +from .billing_retrieve_balance_response import BillingRetrieveBalanceResponse as BillingRetrieveBalanceResponse diff --git a/src/getimg/types/billing_list_costs_params.py b/src/getimg/types/billing_list_costs_params.py new file mode 100644 index 0000000..b1ab16f --- /dev/null +++ b/src/getimg/types/billing_list_costs_params.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["BillingListCostsParams"] + + +class BillingListCostsParams(TypedDict, total=False): + end: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] + """Inclusive ISO 8601 end timestamp. + + Must include a time zone, fall after `start`, and sit within 180 days of it. + """ + + start: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] + """Inclusive ISO 8601 start timestamp. Must include a time zone.""" diff --git a/src/getimg/types/billing_list_costs_response.py b/src/getimg/types/billing_list_costs_response.py new file mode 100644 index 0000000..ee23afe --- /dev/null +++ b/src/getimg/types/billing_list_costs_response.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import datetime +from typing import List +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["BillingListCostsResponse", "Data"] + + +class Data(BaseModel): + cost: float + """Cost for the bucket in USD.""" + + date: datetime.date + """UTC calendar date for the bucket.""" + + +class BillingListCostsResponse(BaseModel): + currency: Literal["USD"] + + data: List[Data] + """One bucket per UTC calendar date in the range.""" + + end: datetime.datetime + """End of the requested range.""" + + start: datetime.datetime + """Start of the requested range.""" + + total_cost: float + """Total cost for the range in USD.""" diff --git a/src/getimg/types/billing_retrieve_balance_response.py b/src/getimg/types/billing_retrieve_balance_response.py new file mode 100644 index 0000000..000bb9d --- /dev/null +++ b/src/getimg/types/billing_retrieve_balance_response.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["BillingRetrieveBalanceResponse"] + + +class BillingRetrieveBalanceResponse(BaseModel): + balance: str + """Current balance in USD.""" + + currency: Literal["USD"] diff --git a/src/getimg/types/developer_model_rate.py b/src/getimg/types/developer_model_rate.py new file mode 100644 index 0000000..00121fb --- /dev/null +++ b/src/getimg/types/developer_model_rate.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DeveloperModelRate"] + + +class DeveloperModelRate(BaseModel): + billable_unit: str + """Unit billed, such as image or video_second.""" + + resolution: Optional[str] = None + """Resolution this rate applies to, or null for a resolution-independent rate.""" + + sound: Literal["sound_on", "sound_off", "not_applicable"] + """ + Sound setting this rate applies to; not_applicable also serves as a video + fallback. + """ + + unit_price: str + """USD price per billable unit, represented as a decimal string.""" diff --git a/src/getimg/types/model_list_response.py b/src/getimg/types/model_list_response.py index 1f3de93..ac23fbe 100644 --- a/src/getimg/types/model_list_response.py +++ b/src/getimg/types/model_list_response.py @@ -1,40 +1,19 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, List from datetime import datetime from typing_extensions import Literal, TypeAlias from .._models import BaseModel +from .developer_model_rate import DeveloperModelRate -__all__ = [ - "ModelListResponse", - "ModelListResponseItem", - "ModelListResponseItemPricing", - "ModelListResponseItemPricingRate", -] - - -class ModelListResponseItemPricingRate(BaseModel): - billable_unit: str - """Unit billed, such as image or video_second.""" - - resolution: Optional[str] = None - """Resolution this rate applies to, or null for a resolution-independent rate.""" - - sound: Literal["sound_on", "sound_off", "not_applicable"] - """ - Sound setting this rate applies to; not_applicable also serves as a video - fallback. - """ - - unit_price: str - """USD price per billable unit, represented as a decimal string.""" +__all__ = ["ModelListResponse", "ModelListResponseItem", "ModelListResponseItemPricing"] class ModelListResponseItemPricing(BaseModel): currency: Literal["USD"] - rates: List[ModelListResponseItemPricingRate] + rates: List[DeveloperModelRate] """Currently effective catalog rates, ordered by unit price. Empty when no active rates are configured; this does not mean generation is diff --git a/src/getimg/types/model_retrieve_response.py b/src/getimg/types/model_retrieve_response.py new file mode 100644 index 0000000..a88c304 --- /dev/null +++ b/src/getimg/types/model_retrieve_response.py @@ -0,0 +1,58 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .developer_model_rate import DeveloperModelRate + +__all__ = ["ModelRetrieveResponse", "Pricing"] + + +class Pricing(BaseModel): + currency: Literal["USD"] + + rates: List[DeveloperModelRate] + """Currently effective catalog rates, ordered by unit price. + + Empty when no active rates are configured; this does not mean generation is + free. + """ + + +class ModelRetrieveResponse(BaseModel): + id: str + """The model identifier.""" + + created_at: datetime + """Timestamp when the model was created.""" + + name: str + """The model display name.""" + + pricing: Pricing + + supported_aspect_ratios: List[str] + """Supported aspect ratios in default order; the first is used when omitted.""" + + supported_durations: List[float] + """Supported durations in seconds; empty for image models. + + The first is the default. + """ + + supported_references: Dict[str, int] + """ + Maximum reference count per supported role (reference_image, first_frame, + last_frame). + """ + + supported_resolutions: List[str] + """Supported resolutions in default order; the first is used when omitted.""" + + supports_sound: bool + """Whether sound generation is supported.""" + + type: Literal["image", "video"] + """The generation type supported by the model.""" diff --git a/tests/api_resources/test_billing.py b/tests/api_resources/test_billing.py new file mode 100644 index 0000000..ae57bba --- /dev/null +++ b/tests/api_resources/test_billing.py @@ -0,0 +1,155 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from getimg import GetimgAI, AsyncGetimgAI +from tests.utils import assert_matches_type +from getimg.types import BillingListCostsResponse, BillingRetrieveBalanceResponse +from getimg._utils import parse_datetime + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBilling: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_costs(self, client: GetimgAI) -> None: + billing = client.billing.list_costs( + end=parse_datetime("2019-12-27T18:11:19.117Z"), + start=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(BillingListCostsResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_costs(self, client: GetimgAI) -> None: + response = client.billing.with_raw_response.list_costs( + end=parse_datetime("2019-12-27T18:11:19.117Z"), + start=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + billing = response.parse() + assert_matches_type(BillingListCostsResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_costs(self, client: GetimgAI) -> None: + with client.billing.with_streaming_response.list_costs( + end=parse_datetime("2019-12-27T18:11:19.117Z"), + start=parse_datetime("2019-12-27T18:11:19.117Z"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + billing = response.parse() + assert_matches_type(BillingListCostsResponse, billing, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_balance(self, client: GetimgAI) -> None: + billing = client.billing.retrieve_balance() + assert_matches_type(BillingRetrieveBalanceResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_balance(self, client: GetimgAI) -> None: + response = client.billing.with_raw_response.retrieve_balance() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + billing = response.parse() + assert_matches_type(BillingRetrieveBalanceResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_balance(self, client: GetimgAI) -> None: + with client.billing.with_streaming_response.retrieve_balance() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + billing = response.parse() + assert_matches_type(BillingRetrieveBalanceResponse, billing, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBilling: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_costs(self, async_client: AsyncGetimgAI) -> None: + billing = await async_client.billing.list_costs( + end=parse_datetime("2019-12-27T18:11:19.117Z"), + start=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(BillingListCostsResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_costs(self, async_client: AsyncGetimgAI) -> None: + response = await async_client.billing.with_raw_response.list_costs( + end=parse_datetime("2019-12-27T18:11:19.117Z"), + start=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + billing = await response.parse() + assert_matches_type(BillingListCostsResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_costs(self, async_client: AsyncGetimgAI) -> None: + async with async_client.billing.with_streaming_response.list_costs( + end=parse_datetime("2019-12-27T18:11:19.117Z"), + start=parse_datetime("2019-12-27T18:11:19.117Z"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + billing = await response.parse() + assert_matches_type(BillingListCostsResponse, billing, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_balance(self, async_client: AsyncGetimgAI) -> None: + billing = await async_client.billing.retrieve_balance() + assert_matches_type(BillingRetrieveBalanceResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_balance(self, async_client: AsyncGetimgAI) -> None: + response = await async_client.billing.with_raw_response.retrieve_balance() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + billing = await response.parse() + assert_matches_type(BillingRetrieveBalanceResponse, billing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_balance(self, async_client: AsyncGetimgAI) -> None: + async with async_client.billing.with_streaming_response.retrieve_balance() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + billing = await response.parse() + assert_matches_type(BillingRetrieveBalanceResponse, billing, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_models.py b/tests/api_resources/test_models.py index 50cb61e..f747c4e 100644 --- a/tests/api_resources/test_models.py +++ b/tests/api_resources/test_models.py @@ -9,7 +9,7 @@ from getimg import GetimgAI, AsyncGetimgAI from tests.utils import assert_matches_type -from getimg.types import ModelListResponse +from getimg.types import ModelListResponse, ModelRetrieveResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -17,6 +17,48 @@ class TestModels: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: GetimgAI) -> None: + model = client.models.retrieve( + "seedream-5-lite", + ) + assert_matches_type(ModelRetrieveResponse, model, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: GetimgAI) -> None: + response = client.models.with_raw_response.retrieve( + "seedream-5-lite", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + model = response.parse() + assert_matches_type(ModelRetrieveResponse, model, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: GetimgAI) -> None: + with client.models.with_streaming_response.retrieve( + "seedream-5-lite", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + model = response.parse() + assert_matches_type(ModelRetrieveResponse, model, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: GetimgAI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `model` but received ''"): + client.models.with_raw_response.retrieve( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: GetimgAI) -> None: @@ -59,6 +101,48 @@ class TestAsyncModels: "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncGetimgAI) -> None: + model = await async_client.models.retrieve( + "seedream-5-lite", + ) + assert_matches_type(ModelRetrieveResponse, model, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncGetimgAI) -> None: + response = await async_client.models.with_raw_response.retrieve( + "seedream-5-lite", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + model = await response.parse() + assert_matches_type(ModelRetrieveResponse, model, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncGetimgAI) -> None: + async with async_client.models.with_streaming_response.retrieve( + "seedream-5-lite", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + model = await response.parse() + assert_matches_type(ModelRetrieveResponse, model, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncGetimgAI) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `model` but received ''"): + await async_client.models.with_raw_response.retrieve( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncGetimgAI) -> None: From 28570184a8a9742f659a3ccac1cab536ac96eab7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 13:19:20 +0000 Subject: [PATCH 5/5] release: 0.4.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ pyproject.toml | 2 +- src/getimg/_version.py | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6b7b74c..da59f99 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.3.0" + ".": "0.4.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a15493..601482c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.4.0 (2026-09-08) + +Full Changelog: [v0.3.0...v0.4.0](https://github.com/getimg-ai/getimg-python/compare/v0.3.0...v0.4.0) + +### Features + +* **api:** api update ([fd4e347](https://github.com/getimg-ai/getimg-python/commit/fd4e3479579f62d6f4ef1c463d13bc1909ed2ad2)) +* **api:** new endpoints ([390d72f](https://github.com/getimg-ai/getimg-python/commit/390d72f8d53e503101dffd3f74b3914d25235905)) + ## 0.3.0 (2026-07-18) Full Changelog: [v0.2.1...v0.3.0](https://github.com/getimg-ai/getimg-python/compare/v0.2.1...v0.3.0) diff --git a/pyproject.toml b/pyproject.toml index 6dda264..d7633cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "getimg" -version = "0.3.0" +version = "0.4.0" description = "The official Python library for the getimg.ai API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/getimg/_version.py b/src/getimg/_version.py index 9dcc2db..fe0da1b 100644 --- a/src/getimg/_version.py +++ b/src/getimg/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "getimg" -__version__ = "0.3.0" # x-release-please-version +__version__ = "0.4.0" # x-release-please-version