Skip to content

Commit e0d9d6b

Browse files
authored
Merge pull request #7 from channel3-ai/release-please--branches--main--changes--next
release: 2.4.0
2 parents bc2c3e8 + b165528 commit e0d9d6b

21 files changed

+312
-446
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "2.3.0"
2+
".": "2.4.0"
33
}

.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 6
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/channel3%2Fpublic-sdk-a86114ce098255360b65356eedfe9c93f9db44aa99cb90d8c36756d39c2c2de0.yml
3-
openapi_spec_hash: 113158785b160e8b67d66e2820137df8
1+
configured_endpoints: 5
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/channel3%2Fpublic-sdk-3366fbfe5ea0c833c184c33d00d301e23e23c0cfa7398b0ebc34a90ab03f65fd.yml
3+
openapi_spec_hash: e428021f51d697d779a5ddd3ee7109b7
44
config_hash: 0ec132fef7cbcef12aebece85f2ef2b1

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Changelog
22

3+
## 2.4.0 (2025-11-10)
4+
5+
Full Changelog: [v2.3.0...v2.4.0](https://github.com/channel3-ai/sdk-python/compare/v2.3.0...v2.4.0)
6+
7+
### Features
8+
9+
* **api:** api update ([f50613e](https://github.com/channel3-ai/sdk-python/commit/f50613e9cf5d2067b282896dfafcb73ef99ee0ae))
10+
11+
12+
### Bug Fixes
13+
14+
* **client:** close streams without requiring full consumption ([4d44bb1](https://github.com/channel3-ai/sdk-python/commit/4d44bb1d045d7d2447bc305dd8463e27dd170175))
15+
16+
17+
### Chores
18+
19+
* **internal/tests:** avoid race condition with implicit client cleanup ([ef7fe91](https://github.com/channel3-ai/sdk-python/commit/ef7fe91e5e5c14e15172642362aee07b96f19b3d))
20+
* **internal:** grammar fix (it's -> its) ([ae7ab14](https://github.com/channel3-ai/sdk-python/commit/ae7ab1494bc21b8b5aeefb91af3353b696949bcb))
21+
322
## 2.3.0 (2025-10-28)
423

524
Full Changelog: [v2.2.1...v2.3.0](https://github.com/channel3-ai/sdk-python/compare/v2.2.1...v2.3.0)

api.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@ Methods:
3333
Types:
3434

3535
```python
36-
from channel3_sdk.types import Brand, BrandListResponse
36+
from channel3_sdk.types import Brand
3737
```
3838

3939
Methods:
4040

41-
- <code title="get /v0/brands/{brand_id}">client.brands.<a href="./src/channel3_sdk/resources/brands.py">retrieve</a>(brand_id) -> <a href="./src/channel3_sdk/types/brand.py">Brand</a></code>
42-
- <code title="get /v0/brands">client.brands.<a href="./src/channel3_sdk/resources/brands.py">list</a>(\*\*<a href="src/channel3_sdk/types/brand_list_params.py">params</a>) -> <a href="./src/channel3_sdk/types/brand_list_response.py">BrandListResponse</a></code>
41+
- <code title="get /v0/brands">client.brands.<a href="./src/channel3_sdk/resources/brands.py">list</a>(\*\*<a href="src/channel3_sdk/types/brand_list_params.py">params</a>) -> <a href="./src/channel3_sdk/types/brand.py">Brand</a></code>
4342

4443
# Enrich
4544

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "channel3_sdk"
3-
version = "2.3.0"
3+
version = "2.4.0"
44
description = "The official Python library for the channel3 API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"

src/channel3_sdk/_streaming.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ def __stream__(self) -> Iterator[_T]:
5757
for sse in iterator:
5858
yield process_data(data=sse.json(), cast_to=cast_to, response=response)
5959

60-
# Ensure the entire stream is consumed
61-
for _sse in iterator:
62-
...
60+
# As we might not fully consume the response stream, we need to close it explicitly
61+
response.close()
6362

6463
def __enter__(self) -> Self:
6564
return self
@@ -121,9 +120,8 @@ async def __stream__(self) -> AsyncIterator[_T]:
121120
async for sse in iterator:
122121
yield process_data(data=sse.json(), cast_to=cast_to, response=response)
123122

124-
# Ensure the entire stream is consumed
125-
async for _sse in iterator:
126-
...
123+
# As we might not fully consume the response stream, we need to close it explicitly
124+
await response.aclose()
127125

128126
async def __aenter__(self) -> Self:
129127
return self

src/channel3_sdk/_utils/_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def is_given(obj: _T | NotGiven | Omit) -> TypeGuard[_T]:
133133
# Type safe methods for narrowing types with TypeVars.
134134
# The default narrowing for isinstance(obj, dict) is dict[unknown, unknown],
135135
# however this cause Pyright to rightfully report errors. As we know we don't
136-
# care about the contained types we can safely use `object` in it's place.
136+
# care about the contained types we can safely use `object` in its place.
137137
#
138138
# There are two separate functions defined, `is_*` and `is_*_t` for different use cases.
139139
# `is_*` is for when you're dealing with an unknown input

src/channel3_sdk/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

33
__title__ = "channel3_sdk"
4-
__version__ = "2.3.0" # x-release-please-version
4+
__version__ = "2.4.0" # x-release-please-version

src/channel3_sdk/resources/brands.py

Lines changed: 11 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
from __future__ import annotations
44

5-
from typing import Optional
6-
75
import httpx
86

97
from ..types import brand_list_params
10-
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
8+
from .._types import Body, Query, Headers, NotGiven, not_given
119
from .._utils import maybe_transform, async_maybe_transform
1210
from .._compat import cached_property
1311
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -19,7 +17,6 @@
1917
)
2018
from ..types.brand import Brand
2119
from .._base_client import make_request_options
22-
from ..types.brand_list_response import BrandListResponse
2320

2421
__all__ = ["BrandsResource", "AsyncBrandsResource"]
2522

@@ -44,54 +41,19 @@ def with_streaming_response(self) -> BrandsResourceWithStreamingResponse:
4441
"""
4542
return BrandsResourceWithStreamingResponse(self)
4643

47-
def retrieve(
48-
self,
49-
brand_id: str,
50-
*,
51-
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
52-
# The extra values given here take precedence over values defined on the client or passed to this method.
53-
extra_headers: Headers | None = None,
54-
extra_query: Query | None = None,
55-
extra_body: Body | None = None,
56-
timeout: float | httpx.Timeout | None | NotGiven = not_given,
57-
) -> Brand:
58-
"""
59-
Get detailed information for a specific brand by its ID.
60-
61-
Args:
62-
extra_headers: Send extra headers
63-
64-
extra_query: Add additional query parameters to the request
65-
66-
extra_body: Add additional JSON properties to the request
67-
68-
timeout: Override the client-level default timeout for this request, in seconds
69-
"""
70-
if not brand_id:
71-
raise ValueError(f"Expected a non-empty value for `brand_id` but received {brand_id!r}")
72-
return self._get(
73-
f"/v0/brands/{brand_id}",
74-
options=make_request_options(
75-
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
76-
),
77-
cast_to=Brand,
78-
)
79-
8044
def list(
8145
self,
8246
*,
83-
page: int | Omit = omit,
84-
query: Optional[str] | Omit = omit,
85-
size: int | Omit = omit,
47+
query: str,
8648
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
8749
# The extra values given here take precedence over values defined on the client or passed to this method.
8850
extra_headers: Headers | None = None,
8951
extra_query: Query | None = None,
9052
extra_body: Body | None = None,
9153
timeout: float | httpx.Timeout | None | NotGiven = not_given,
92-
) -> BrandListResponse:
54+
) -> Brand:
9355
"""
94-
Get all brands that the vendor currently sells.
56+
Find a brand by name.
9557
9658
Args:
9759
extra_headers: Send extra headers
@@ -109,16 +71,9 @@ def list(
10971
extra_query=extra_query,
11072
extra_body=extra_body,
11173
timeout=timeout,
112-
query=maybe_transform(
113-
{
114-
"page": page,
115-
"query": query,
116-
"size": size,
117-
},
118-
brand_list_params.BrandListParams,
119-
),
74+
query=maybe_transform({"query": query}, brand_list_params.BrandListParams),
12075
),
121-
cast_to=BrandListResponse,
76+
cast_to=Brand,
12277
)
12378

12479

@@ -142,54 +97,19 @@ def with_streaming_response(self) -> AsyncBrandsResourceWithStreamingResponse:
14297
"""
14398
return AsyncBrandsResourceWithStreamingResponse(self)
14499

145-
async def retrieve(
146-
self,
147-
brand_id: str,
148-
*,
149-
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
150-
# The extra values given here take precedence over values defined on the client or passed to this method.
151-
extra_headers: Headers | None = None,
152-
extra_query: Query | None = None,
153-
extra_body: Body | None = None,
154-
timeout: float | httpx.Timeout | None | NotGiven = not_given,
155-
) -> Brand:
156-
"""
157-
Get detailed information for a specific brand by its ID.
158-
159-
Args:
160-
extra_headers: Send extra headers
161-
162-
extra_query: Add additional query parameters to the request
163-
164-
extra_body: Add additional JSON properties to the request
165-
166-
timeout: Override the client-level default timeout for this request, in seconds
167-
"""
168-
if not brand_id:
169-
raise ValueError(f"Expected a non-empty value for `brand_id` but received {brand_id!r}")
170-
return await self._get(
171-
f"/v0/brands/{brand_id}",
172-
options=make_request_options(
173-
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
174-
),
175-
cast_to=Brand,
176-
)
177-
178100
async def list(
179101
self,
180102
*,
181-
page: int | Omit = omit,
182-
query: Optional[str] | Omit = omit,
183-
size: int | Omit = omit,
103+
query: str,
184104
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
185105
# The extra values given here take precedence over values defined on the client or passed to this method.
186106
extra_headers: Headers | None = None,
187107
extra_query: Query | None = None,
188108
extra_body: Body | None = None,
189109
timeout: float | httpx.Timeout | None | NotGiven = not_given,
190-
) -> BrandListResponse:
110+
) -> Brand:
191111
"""
192-
Get all brands that the vendor currently sells.
112+
Find a brand by name.
193113
194114
Args:
195115
extra_headers: Send extra headers
@@ -207,26 +127,16 @@ async def list(
207127
extra_query=extra_query,
208128
extra_body=extra_body,
209129
timeout=timeout,
210-
query=await async_maybe_transform(
211-
{
212-
"page": page,
213-
"query": query,
214-
"size": size,
215-
},
216-
brand_list_params.BrandListParams,
217-
),
130+
query=await async_maybe_transform({"query": query}, brand_list_params.BrandListParams),
218131
),
219-
cast_to=BrandListResponse,
132+
cast_to=Brand,
220133
)
221134

222135

223136
class BrandsResourceWithRawResponse:
224137
def __init__(self, brands: BrandsResource) -> None:
225138
self._brands = brands
226139

227-
self.retrieve = to_raw_response_wrapper(
228-
brands.retrieve,
229-
)
230140
self.list = to_raw_response_wrapper(
231141
brands.list,
232142
)
@@ -236,9 +146,6 @@ class AsyncBrandsResourceWithRawResponse:
236146
def __init__(self, brands: AsyncBrandsResource) -> None:
237147
self._brands = brands
238148

239-
self.retrieve = async_to_raw_response_wrapper(
240-
brands.retrieve,
241-
)
242149
self.list = async_to_raw_response_wrapper(
243150
brands.list,
244151
)
@@ -248,9 +155,6 @@ class BrandsResourceWithStreamingResponse:
248155
def __init__(self, brands: BrandsResource) -> None:
249156
self._brands = brands
250157

251-
self.retrieve = to_streamed_response_wrapper(
252-
brands.retrieve,
253-
)
254158
self.list = to_streamed_response_wrapper(
255159
brands.list,
256160
)
@@ -260,9 +164,6 @@ class AsyncBrandsResourceWithStreamingResponse:
260164
def __init__(self, brands: AsyncBrandsResource) -> None:
261165
self._brands = brands
262166

263-
self.retrieve = async_to_streamed_response_wrapper(
264-
brands.retrieve,
265-
)
266167
self.list = async_to_streamed_response_wrapper(
267168
brands.list,
268169
)

src/channel3_sdk/resources/enrich.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ def enrich_url(
5353
timeout: float | httpx.Timeout | None | NotGiven = not_given,
5454
) -> EnrichEnrichURLResponse:
5555
"""
56-
Enrich a product URL with additional information.
56+
Search by product URL, get back full product information from Channel3’s product
57+
database.
5758
5859
Args:
5960
url: The URL of the product to enrich
@@ -108,7 +109,8 @@ async def enrich_url(
108109
timeout: float | httpx.Timeout | None | NotGiven = not_given,
109110
) -> EnrichEnrichURLResponse:
110111
"""
111-
Enrich a product URL with additional information.
112+
Search by product URL, get back full product information from Channel3’s product
113+
database.
112114
113115
Args:
114116
url: The URL of the product to enrich

0 commit comments

Comments
 (0)