channel3-sdk 0.2.2__tar.gz → 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of channel3-sdk might be problematic. Click here for more details.
- channel3_sdk-0.2.2/README.md → channel3_sdk-1.0.0/PKG-INFO +99 -17
- channel3_sdk-0.2.2/PKG-INFO → channel3_sdk-1.0.0/README.md +70 -42
- channel3_sdk-1.0.0/channel3_sdk/__init__.py +52 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/.gitignore +23 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/README.md +124 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/__init__.py +8 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/__init__.py +1 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/channel3_api/__init__.py +1 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/channel3_api/get_brand_detail_v0_brands_brand_id_get.py +179 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/channel3_api/get_brands_v0_brands_get.py +218 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/channel3_api/get_product_detail_v0_products_product_id_get.py +179 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/channel3_api/search_v0_search_post.py +193 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/default/__init__.py +1 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/api/default/root_get.py +79 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/client.py +268 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/errors.py +16 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/__init__.py +35 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/availability_status.py +15 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/brand.py +109 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/error_response.py +59 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/paginated_response_brand.py +83 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/pagination_meta.py +84 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/price.py +89 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/product.py +166 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/product_detail.py +306 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/product_detail_gender_type_0.py +10 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/search_config.py +69 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/search_filter_price.py +92 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/search_filters.py +191 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/search_filters_gender_type_0.py +10 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/search_request.py +191 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/models/variant.py +75 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/py.typed +1 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/fast_api_client/types.py +54 -0
- channel3_sdk-1.0.0/channel3_sdk/_gen/pyproject.toml +26 -0
- channel3_sdk-1.0.0/channel3_sdk/client.py +361 -0
- channel3_sdk-1.0.0/pyproject.toml +55 -0
- channel3_sdk-0.2.2/channel3_sdk/__init__.py +0 -46
- channel3_sdk-0.2.2/channel3_sdk/client.py +0 -574
- channel3_sdk-0.2.2/channel3_sdk/models.py +0 -135
- channel3_sdk-0.2.2/pyproject.toml +0 -40
- {channel3_sdk-0.2.2 → channel3_sdk-1.0.0}/channel3_sdk/exceptions.py +0 -0
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: channel3-sdk
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: The official Python SDK for Channel3
|
|
5
|
+
Home-page: https://github.com/channel3-ai/sdk-python
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: ai,shopping,ecommerce,search,api
|
|
8
|
+
Author: Channel3
|
|
9
|
+
Author-email: alex@trychannel3.com
|
|
10
|
+
Requires-Python: >=3.9,<4.0
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Dist: attrs (>=22.2.0)
|
|
23
|
+
Requires-Dist: httpx (>=0.23.0,<0.29.0)
|
|
24
|
+
Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
|
|
25
|
+
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
26
|
+
Project-URL: Repository, https://github.com/channel3-ai/sdk-python
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
1
29
|
# Channel3 Python SDK
|
|
2
30
|
|
|
3
31
|
The official Python SDK for the [Channel3](https://trychannel3.com) AI Shopping API.
|
|
@@ -39,10 +67,7 @@ if product_detail.key_features:
|
|
|
39
67
|
|
|
40
68
|
# Get all brands
|
|
41
69
|
brands = client.get_brands()
|
|
42
|
-
|
|
43
|
-
print(f"Brand: {brand.name}")
|
|
44
|
-
if brand.description:
|
|
45
|
-
print(f"Description: {brand.description}")
|
|
70
|
+
print(f"Found {len(brands.items)} brands")
|
|
46
71
|
|
|
47
72
|
# Get specific brand details
|
|
48
73
|
brand = client.get_brand("brand_123")
|
|
@@ -58,23 +83,23 @@ from channel3_sdk import AsyncChannel3Client
|
|
|
58
83
|
async def main():
|
|
59
84
|
# Initialize the async client
|
|
60
85
|
client = AsyncChannel3Client(api_key="your_api_key_here")
|
|
61
|
-
|
|
86
|
+
|
|
62
87
|
# Search for products
|
|
63
88
|
products = await client.search(query="running shoes")
|
|
64
|
-
|
|
89
|
+
|
|
65
90
|
for product in products:
|
|
66
91
|
print(f"Product: {product.title}")
|
|
67
92
|
print(f"Score: {product.score}")
|
|
68
93
|
print(f"Price: {product.price.currency} {product.price.price}")
|
|
69
|
-
|
|
94
|
+
|
|
70
95
|
# Get detailed product information
|
|
71
96
|
if products:
|
|
72
97
|
product_detail = await client.get_product(products[0].id)
|
|
73
98
|
print(f"Availability: {product_detail.availability}")
|
|
74
|
-
|
|
99
|
+
|
|
75
100
|
# Get brands
|
|
76
101
|
brands = await client.get_brands()
|
|
77
|
-
print(f"Found {len(brands)} brands")
|
|
102
|
+
print(f"Found {len(brands.items)} brands")
|
|
78
103
|
|
|
79
104
|
# Run the async function
|
|
80
105
|
asyncio.run(main())
|
|
@@ -126,11 +151,39 @@ products = client.search(
|
|
|
126
151
|
)
|
|
127
152
|
```
|
|
128
153
|
|
|
154
|
+
### Search configuration and context
|
|
155
|
+
|
|
156
|
+
You can control how search behaves using `SearchConfig`, and add optional `context` to guide results.
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from channel3_sdk import SearchConfig
|
|
160
|
+
|
|
161
|
+
config = SearchConfig(enrich_query=True, semantic_search=False)
|
|
162
|
+
|
|
163
|
+
products = client.search(
|
|
164
|
+
query="running shoes",
|
|
165
|
+
limit=5,
|
|
166
|
+
config=config, # or a dict: {"enrich_query": True, "semantic_search": False}
|
|
167
|
+
context="Marathon training on road surfaces"
|
|
168
|
+
)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Async usage is identical:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
products = await async_client.search(
|
|
175
|
+
query="hiking boots",
|
|
176
|
+
config={"enrich_query": False, "semantic_search": True},
|
|
177
|
+
context="Waterproof boots for alpine conditions"
|
|
178
|
+
)
|
|
179
|
+
```
|
|
180
|
+
|
|
129
181
|
### Brand Management
|
|
130
182
|
|
|
131
183
|
```python
|
|
132
184
|
# Get all brands with pagination
|
|
133
185
|
brands = client.get_brands(page=1, size=50)
|
|
186
|
+
print(brands.pagination.total_count)
|
|
134
187
|
|
|
135
188
|
# Search for specific brands
|
|
136
189
|
nike_brands = client.get_brands(query="nike")
|
|
@@ -146,26 +199,31 @@ print(f"Logo: {brand_detail.logo_url}")
|
|
|
146
199
|
### Client Classes
|
|
147
200
|
|
|
148
201
|
#### `Channel3Client`
|
|
202
|
+
|
|
149
203
|
Synchronous client for the Channel3 API.
|
|
150
204
|
|
|
151
205
|
**Methods:**
|
|
152
|
-
|
|
206
|
+
|
|
207
|
+
- `search(query=None, image_url=None, base64_image=None, filters=None, limit=20, config=None, context=None)` → `List[Product]`
|
|
153
208
|
- `get_product(product_id)` → `ProductDetail`
|
|
154
|
-
- `get_brands(query=None, page=1, size=100)` → `
|
|
209
|
+
- `get_brands(query=None, page=1, size=100)` → `PaginatedResponseBrand`
|
|
155
210
|
- `get_brand(brand_id)` → `Brand`
|
|
156
211
|
|
|
157
|
-
#### `AsyncChannel3Client`
|
|
212
|
+
#### `AsyncChannel3Client`
|
|
213
|
+
|
|
158
214
|
Asynchronous client for the Channel3 API.
|
|
159
215
|
|
|
160
216
|
**Methods:**
|
|
161
|
-
|
|
217
|
+
|
|
218
|
+
- `async search(query=None, image_url=None, base64_image=None, filters=None, limit=20, config=None, context=None)` → `List[Product]`
|
|
162
219
|
- `async get_product(product_id)` → `ProductDetail`
|
|
163
|
-
- `async get_brands(query=None, page=1, size=100)` → `
|
|
220
|
+
- `async get_brands(query=None, page=1, size=100)` → `PaginatedResponseBrand`
|
|
164
221
|
- `async get_brand(brand_id)` → `Brand`
|
|
165
222
|
|
|
166
223
|
### Models
|
|
167
224
|
|
|
168
225
|
#### `Product`
|
|
226
|
+
|
|
169
227
|
- `id: str` - Unique product identifier
|
|
170
228
|
- `score: float` - Search relevance score
|
|
171
229
|
- `title: str` - Product title
|
|
@@ -177,6 +235,7 @@ Asynchronous client for the Channel3 API.
|
|
|
177
235
|
- `variants: List[Variant]` - Product variants
|
|
178
236
|
|
|
179
237
|
#### `ProductDetail`
|
|
238
|
+
|
|
180
239
|
- `title: str` - Product title
|
|
181
240
|
- `description: Optional[str]` - Product description
|
|
182
241
|
- `brand_id: Optional[str]` - Brand identifier
|
|
@@ -188,34 +247,57 @@ Asynchronous client for the Channel3 API.
|
|
|
188
247
|
- `variants: List[Variant]` - Product variants
|
|
189
248
|
|
|
190
249
|
#### `Brand`
|
|
250
|
+
|
|
191
251
|
- `id: str` - Unique brand identifier
|
|
192
252
|
- `name: str` - Brand name
|
|
193
253
|
- `logo_url: Optional[str]` - Brand logo URL
|
|
194
254
|
- `description: Optional[str]` - Brand description
|
|
195
255
|
|
|
196
256
|
#### `Variant`
|
|
257
|
+
|
|
197
258
|
- `product_id: str` - Associated product identifier
|
|
198
259
|
- `title: str` - Variant title
|
|
199
260
|
- `image_url: str` - Variant image URL
|
|
200
261
|
|
|
201
262
|
#### `SearchFilters`
|
|
263
|
+
|
|
202
264
|
- `brand_ids: Optional[List[str]]` - Brand ID filters
|
|
203
265
|
- `gender: Optional[Literal["male", "female", "unisex"]]` - Gender filter
|
|
204
266
|
- `price: Optional[SearchFilterPrice]` - Price range filter
|
|
205
267
|
- `availability: Optional[List[AvailabilityStatus]]` - Availability filters
|
|
206
268
|
|
|
207
269
|
#### `SearchFilterPrice`
|
|
270
|
+
|
|
208
271
|
- `min_price: Optional[float]` - Minimum price
|
|
209
272
|
- `max_price: Optional[float]` - Maximum price
|
|
210
273
|
|
|
274
|
+
#### `SearchConfig`
|
|
275
|
+
|
|
276
|
+
- `enrich_query: bool = True` — enable query rewriting/enrichment
|
|
277
|
+
- `semantic_search: bool = True` — enable semantic ranking
|
|
278
|
+
|
|
211
279
|
#### `Price`
|
|
280
|
+
|
|
212
281
|
- `price: float` - Current price
|
|
213
282
|
- `compare_at_price: Optional[float]` - Original price (if discounted)
|
|
214
283
|
- `currency: str` - Currency code
|
|
215
284
|
|
|
216
285
|
#### `AvailabilityStatus`
|
|
286
|
+
|
|
217
287
|
Enum with values: `IN_STOCK`, `OUT_OF_STOCK`, `PRE_ORDER`, `LIMITED_AVAILABILITY`, `BACK_ORDER`, `DISCONTINUED`, `SOLD_OUT`, `UNKNOWN`
|
|
218
288
|
|
|
289
|
+
#### `PaginatedResponseBrand`
|
|
290
|
+
|
|
291
|
+
- `items: List[Brand]` — page of brands
|
|
292
|
+
- `pagination: PaginationMeta` — pagination info
|
|
293
|
+
|
|
294
|
+
#### `PaginationMeta`
|
|
295
|
+
|
|
296
|
+
- `current_page: int`
|
|
297
|
+
- `page_size: int`
|
|
298
|
+
- `total_count: int`
|
|
299
|
+
- `total_pages: int`
|
|
300
|
+
|
|
219
301
|
## Error Handling
|
|
220
302
|
|
|
221
303
|
The SDK provides specific exception types for different error conditions:
|
|
@@ -249,11 +331,11 @@ except Channel3ConnectionError:
|
|
|
249
331
|
|
|
250
332
|
## Requirements
|
|
251
333
|
|
|
252
|
-
- Python 3.
|
|
334
|
+
- Python 3.9+
|
|
253
335
|
- requests
|
|
254
|
-
-
|
|
255
|
-
- pydantic
|
|
336
|
+
- httpx
|
|
256
337
|
|
|
257
338
|
## License
|
|
258
339
|
|
|
259
340
|
MIT License
|
|
341
|
+
|
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: channel3-sdk
|
|
3
|
-
Version: 0.2.2
|
|
4
|
-
Summary: The official Python SDK for Channel3 AI Shopping API
|
|
5
|
-
Home-page: https://github.com/channel3/sdk-python
|
|
6
|
-
License: MIT
|
|
7
|
-
Keywords: ai,shopping,ecommerce,search,api
|
|
8
|
-
Author: Channel3
|
|
9
|
-
Author-email: alex@trychannel3.com
|
|
10
|
-
Requires-Python: >=3.8,<4.0
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
-
Requires-Dist: aiohttp (>=3.9.0,<4.0.0)
|
|
20
|
-
Requires-Dist: pydantic (>=2.5.0,<3.0.0)
|
|
21
|
-
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
22
|
-
Project-URL: Repository, https://github.com/channel3/sdk-python
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
|
|
25
1
|
# Channel3 Python SDK
|
|
26
2
|
|
|
27
3
|
The official Python SDK for the [Channel3](https://trychannel3.com) AI Shopping API.
|
|
@@ -63,10 +39,7 @@ if product_detail.key_features:
|
|
|
63
39
|
|
|
64
40
|
# Get all brands
|
|
65
41
|
brands = client.get_brands()
|
|
66
|
-
|
|
67
|
-
print(f"Brand: {brand.name}")
|
|
68
|
-
if brand.description:
|
|
69
|
-
print(f"Description: {brand.description}")
|
|
42
|
+
print(f"Found {len(brands.items)} brands")
|
|
70
43
|
|
|
71
44
|
# Get specific brand details
|
|
72
45
|
brand = client.get_brand("brand_123")
|
|
@@ -82,23 +55,23 @@ from channel3_sdk import AsyncChannel3Client
|
|
|
82
55
|
async def main():
|
|
83
56
|
# Initialize the async client
|
|
84
57
|
client = AsyncChannel3Client(api_key="your_api_key_here")
|
|
85
|
-
|
|
58
|
+
|
|
86
59
|
# Search for products
|
|
87
60
|
products = await client.search(query="running shoes")
|
|
88
|
-
|
|
61
|
+
|
|
89
62
|
for product in products:
|
|
90
63
|
print(f"Product: {product.title}")
|
|
91
64
|
print(f"Score: {product.score}")
|
|
92
65
|
print(f"Price: {product.price.currency} {product.price.price}")
|
|
93
|
-
|
|
66
|
+
|
|
94
67
|
# Get detailed product information
|
|
95
68
|
if products:
|
|
96
69
|
product_detail = await client.get_product(products[0].id)
|
|
97
70
|
print(f"Availability: {product_detail.availability}")
|
|
98
|
-
|
|
71
|
+
|
|
99
72
|
# Get brands
|
|
100
73
|
brands = await client.get_brands()
|
|
101
|
-
print(f"Found {len(brands)} brands")
|
|
74
|
+
print(f"Found {len(brands.items)} brands")
|
|
102
75
|
|
|
103
76
|
# Run the async function
|
|
104
77
|
asyncio.run(main())
|
|
@@ -150,11 +123,39 @@ products = client.search(
|
|
|
150
123
|
)
|
|
151
124
|
```
|
|
152
125
|
|
|
126
|
+
### Search configuration and context
|
|
127
|
+
|
|
128
|
+
You can control how search behaves using `SearchConfig`, and add optional `context` to guide results.
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from channel3_sdk import SearchConfig
|
|
132
|
+
|
|
133
|
+
config = SearchConfig(enrich_query=True, semantic_search=False)
|
|
134
|
+
|
|
135
|
+
products = client.search(
|
|
136
|
+
query="running shoes",
|
|
137
|
+
limit=5,
|
|
138
|
+
config=config, # or a dict: {"enrich_query": True, "semantic_search": False}
|
|
139
|
+
context="Marathon training on road surfaces"
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Async usage is identical:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
products = await async_client.search(
|
|
147
|
+
query="hiking boots",
|
|
148
|
+
config={"enrich_query": False, "semantic_search": True},
|
|
149
|
+
context="Waterproof boots for alpine conditions"
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
153
|
### Brand Management
|
|
154
154
|
|
|
155
155
|
```python
|
|
156
156
|
# Get all brands with pagination
|
|
157
157
|
brands = client.get_brands(page=1, size=50)
|
|
158
|
+
print(brands.pagination.total_count)
|
|
158
159
|
|
|
159
160
|
# Search for specific brands
|
|
160
161
|
nike_brands = client.get_brands(query="nike")
|
|
@@ -170,26 +171,31 @@ print(f"Logo: {brand_detail.logo_url}")
|
|
|
170
171
|
### Client Classes
|
|
171
172
|
|
|
172
173
|
#### `Channel3Client`
|
|
174
|
+
|
|
173
175
|
Synchronous client for the Channel3 API.
|
|
174
176
|
|
|
175
177
|
**Methods:**
|
|
176
|
-
|
|
178
|
+
|
|
179
|
+
- `search(query=None, image_url=None, base64_image=None, filters=None, limit=20, config=None, context=None)` → `List[Product]`
|
|
177
180
|
- `get_product(product_id)` → `ProductDetail`
|
|
178
|
-
- `get_brands(query=None, page=1, size=100)` → `
|
|
181
|
+
- `get_brands(query=None, page=1, size=100)` → `PaginatedResponseBrand`
|
|
179
182
|
- `get_brand(brand_id)` → `Brand`
|
|
180
183
|
|
|
181
|
-
#### `AsyncChannel3Client`
|
|
184
|
+
#### `AsyncChannel3Client`
|
|
185
|
+
|
|
182
186
|
Asynchronous client for the Channel3 API.
|
|
183
187
|
|
|
184
188
|
**Methods:**
|
|
185
|
-
|
|
189
|
+
|
|
190
|
+
- `async search(query=None, image_url=None, base64_image=None, filters=None, limit=20, config=None, context=None)` → `List[Product]`
|
|
186
191
|
- `async get_product(product_id)` → `ProductDetail`
|
|
187
|
-
- `async get_brands(query=None, page=1, size=100)` → `
|
|
192
|
+
- `async get_brands(query=None, page=1, size=100)` → `PaginatedResponseBrand`
|
|
188
193
|
- `async get_brand(brand_id)` → `Brand`
|
|
189
194
|
|
|
190
195
|
### Models
|
|
191
196
|
|
|
192
197
|
#### `Product`
|
|
198
|
+
|
|
193
199
|
- `id: str` - Unique product identifier
|
|
194
200
|
- `score: float` - Search relevance score
|
|
195
201
|
- `title: str` - Product title
|
|
@@ -201,6 +207,7 @@ Asynchronous client for the Channel3 API.
|
|
|
201
207
|
- `variants: List[Variant]` - Product variants
|
|
202
208
|
|
|
203
209
|
#### `ProductDetail`
|
|
210
|
+
|
|
204
211
|
- `title: str` - Product title
|
|
205
212
|
- `description: Optional[str]` - Product description
|
|
206
213
|
- `brand_id: Optional[str]` - Brand identifier
|
|
@@ -212,34 +219,57 @@ Asynchronous client for the Channel3 API.
|
|
|
212
219
|
- `variants: List[Variant]` - Product variants
|
|
213
220
|
|
|
214
221
|
#### `Brand`
|
|
222
|
+
|
|
215
223
|
- `id: str` - Unique brand identifier
|
|
216
224
|
- `name: str` - Brand name
|
|
217
225
|
- `logo_url: Optional[str]` - Brand logo URL
|
|
218
226
|
- `description: Optional[str]` - Brand description
|
|
219
227
|
|
|
220
228
|
#### `Variant`
|
|
229
|
+
|
|
221
230
|
- `product_id: str` - Associated product identifier
|
|
222
231
|
- `title: str` - Variant title
|
|
223
232
|
- `image_url: str` - Variant image URL
|
|
224
233
|
|
|
225
234
|
#### `SearchFilters`
|
|
235
|
+
|
|
226
236
|
- `brand_ids: Optional[List[str]]` - Brand ID filters
|
|
227
237
|
- `gender: Optional[Literal["male", "female", "unisex"]]` - Gender filter
|
|
228
238
|
- `price: Optional[SearchFilterPrice]` - Price range filter
|
|
229
239
|
- `availability: Optional[List[AvailabilityStatus]]` - Availability filters
|
|
230
240
|
|
|
231
241
|
#### `SearchFilterPrice`
|
|
242
|
+
|
|
232
243
|
- `min_price: Optional[float]` - Minimum price
|
|
233
244
|
- `max_price: Optional[float]` - Maximum price
|
|
234
245
|
|
|
246
|
+
#### `SearchConfig`
|
|
247
|
+
|
|
248
|
+
- `enrich_query: bool = True` — enable query rewriting/enrichment
|
|
249
|
+
- `semantic_search: bool = True` — enable semantic ranking
|
|
250
|
+
|
|
235
251
|
#### `Price`
|
|
252
|
+
|
|
236
253
|
- `price: float` - Current price
|
|
237
254
|
- `compare_at_price: Optional[float]` - Original price (if discounted)
|
|
238
255
|
- `currency: str` - Currency code
|
|
239
256
|
|
|
240
257
|
#### `AvailabilityStatus`
|
|
258
|
+
|
|
241
259
|
Enum with values: `IN_STOCK`, `OUT_OF_STOCK`, `PRE_ORDER`, `LIMITED_AVAILABILITY`, `BACK_ORDER`, `DISCONTINUED`, `SOLD_OUT`, `UNKNOWN`
|
|
242
260
|
|
|
261
|
+
#### `PaginatedResponseBrand`
|
|
262
|
+
|
|
263
|
+
- `items: List[Brand]` — page of brands
|
|
264
|
+
- `pagination: PaginationMeta` — pagination info
|
|
265
|
+
|
|
266
|
+
#### `PaginationMeta`
|
|
267
|
+
|
|
268
|
+
- `current_page: int`
|
|
269
|
+
- `page_size: int`
|
|
270
|
+
- `total_count: int`
|
|
271
|
+
- `total_pages: int`
|
|
272
|
+
|
|
243
273
|
## Error Handling
|
|
244
274
|
|
|
245
275
|
The SDK provides specific exception types for different error conditions:
|
|
@@ -273,12 +303,10 @@ except Channel3ConnectionError:
|
|
|
273
303
|
|
|
274
304
|
## Requirements
|
|
275
305
|
|
|
276
|
-
- Python 3.
|
|
306
|
+
- Python 3.9+
|
|
277
307
|
- requests
|
|
278
|
-
-
|
|
279
|
-
- pydantic
|
|
308
|
+
- httpx
|
|
280
309
|
|
|
281
310
|
## License
|
|
282
311
|
|
|
283
312
|
MIT License
|
|
284
|
-
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Channel3 SDK for Python - Official SDK for the Channel3 AI Shopping API."""
|
|
2
|
+
|
|
3
|
+
from ._gen.fast_api_client.models.availability_status import AvailabilityStatus
|
|
4
|
+
from ._gen.fast_api_client.models.brand import Brand
|
|
5
|
+
from ._gen.fast_api_client.models.paginated_response_brand import (
|
|
6
|
+
PaginatedResponseBrand,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
# Re-export generated models so the public API returns exactly what the OpenAPI returns
|
|
10
|
+
from ._gen.fast_api_client.models.pagination_meta import PaginationMeta
|
|
11
|
+
from ._gen.fast_api_client.models.price import Price
|
|
12
|
+
from ._gen.fast_api_client.models.product import Product
|
|
13
|
+
from ._gen.fast_api_client.models.product_detail import ProductDetail
|
|
14
|
+
from ._gen.fast_api_client.models.search_config import SearchConfig
|
|
15
|
+
from ._gen.fast_api_client.models.search_filters import SearchFilters
|
|
16
|
+
from ._gen.fast_api_client.models.search_request import SearchRequest
|
|
17
|
+
from ._gen.fast_api_client.models.variant import Variant
|
|
18
|
+
from .client import AsyncChannel3Client, Channel3Client
|
|
19
|
+
from .exceptions import (
|
|
20
|
+
Channel3AuthenticationError,
|
|
21
|
+
Channel3ConnectionError,
|
|
22
|
+
Channel3Error,
|
|
23
|
+
Channel3NotFoundError,
|
|
24
|
+
Channel3ServerError,
|
|
25
|
+
Channel3ValidationError,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
__version__ = "1.0.0"
|
|
29
|
+
__all__ = [
|
|
30
|
+
# Clients
|
|
31
|
+
"Channel3Client",
|
|
32
|
+
"AsyncChannel3Client",
|
|
33
|
+
# Models (generated)
|
|
34
|
+
"Product",
|
|
35
|
+
"ProductDetail",
|
|
36
|
+
"SearchFilters",
|
|
37
|
+
"SearchConfig",
|
|
38
|
+
"SearchRequest",
|
|
39
|
+
"Brand",
|
|
40
|
+
"Variant",
|
|
41
|
+
"Price",
|
|
42
|
+
"AvailabilityStatus",
|
|
43
|
+
"PaginatedResponseBrand",
|
|
44
|
+
"PaginationMeta",
|
|
45
|
+
# Exceptions
|
|
46
|
+
"Channel3Error",
|
|
47
|
+
"Channel3AuthenticationError",
|
|
48
|
+
"Channel3ValidationError",
|
|
49
|
+
"Channel3NotFoundError",
|
|
50
|
+
"Channel3ServerError",
|
|
51
|
+
"Channel3ConnectionError",
|
|
52
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
build/
|
|
3
|
+
dist/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
|
|
7
|
+
# pyenv
|
|
8
|
+
.python-version
|
|
9
|
+
|
|
10
|
+
# Environments
|
|
11
|
+
.env
|
|
12
|
+
.venv
|
|
13
|
+
|
|
14
|
+
# mypy
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.dmypy.json
|
|
17
|
+
dmypy.json
|
|
18
|
+
|
|
19
|
+
# JetBrains
|
|
20
|
+
.idea/
|
|
21
|
+
|
|
22
|
+
/coverage.xml
|
|
23
|
+
/.coverage
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# fast-api-client
|
|
2
|
+
A client library for accessing FastAPI
|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
First, create a client:
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from fast_api_client import Client
|
|
9
|
+
|
|
10
|
+
client = Client(base_url="https://api.example.com")
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If the endpoints you're going to hit require authentication, use `AuthenticatedClient` instead:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from fast_api_client import AuthenticatedClient
|
|
17
|
+
|
|
18
|
+
client = AuthenticatedClient(base_url="https://api.example.com", token="SuperSecretToken")
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Now call your endpoint and use your models:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from fast_api_client.models import MyDataModel
|
|
25
|
+
from fast_api_client.api.my_tag import get_my_data_model
|
|
26
|
+
from fast_api_client.types import Response
|
|
27
|
+
|
|
28
|
+
with client as client:
|
|
29
|
+
my_data: MyDataModel = get_my_data_model.sync(client=client)
|
|
30
|
+
# or if you need more info (e.g. status_code)
|
|
31
|
+
response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or do the same thing with an async version:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from fast_api_client.models import MyDataModel
|
|
38
|
+
from fast_api_client.api.my_tag import get_my_data_model
|
|
39
|
+
from fast_api_client.types import Response
|
|
40
|
+
|
|
41
|
+
async with client as client:
|
|
42
|
+
my_data: MyDataModel = await get_my_data_model.asyncio(client=client)
|
|
43
|
+
response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
By default, when you're calling an HTTPS API it will attempt to verify that SSL is working correctly. Using certificate verification is highly recommended most of the time, but sometimes you may need to authenticate to a server (especially an internal server) using a custom certificate bundle.
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
client = AuthenticatedClient(
|
|
50
|
+
base_url="https://internal_api.example.com",
|
|
51
|
+
token="SuperSecretToken",
|
|
52
|
+
verify_ssl="/path/to/certificate_bundle.pem",
|
|
53
|
+
)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
You can also disable certificate validation altogether, but beware that **this is a security risk**.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
client = AuthenticatedClient(
|
|
60
|
+
base_url="https://internal_api.example.com",
|
|
61
|
+
token="SuperSecretToken",
|
|
62
|
+
verify_ssl=False
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Things to know:
|
|
67
|
+
1. Every path/method combo becomes a Python module with four functions:
|
|
68
|
+
1. `sync`: Blocking request that returns parsed data (if successful) or `None`
|
|
69
|
+
1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful.
|
|
70
|
+
1. `asyncio`: Like `sync` but async instead of blocking
|
|
71
|
+
1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking
|
|
72
|
+
|
|
73
|
+
1. All path/query params, and bodies become method arguments.
|
|
74
|
+
1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above)
|
|
75
|
+
1. Any endpoint which did not have a tag will be in `fast_api_client.api.default`
|
|
76
|
+
|
|
77
|
+
## Advanced customizations
|
|
78
|
+
|
|
79
|
+
There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx.Client` or `httpx.AsyncClient` (depending on your use-case):
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from fast_api_client import Client
|
|
83
|
+
|
|
84
|
+
def log_request(request):
|
|
85
|
+
print(f"Request event hook: {request.method} {request.url} - Waiting for response")
|
|
86
|
+
|
|
87
|
+
def log_response(response):
|
|
88
|
+
request = response.request
|
|
89
|
+
print(f"Response event hook: {request.method} {request.url} - Status {response.status_code}")
|
|
90
|
+
|
|
91
|
+
client = Client(
|
|
92
|
+
base_url="https://api.example.com",
|
|
93
|
+
httpx_args={"event_hooks": {"request": [log_request], "response": [log_response]}},
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Or get the underlying httpx client to modify directly with client.get_httpx_client() or client.get_async_httpx_client()
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url):
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import httpx
|
|
103
|
+
from fast_api_client import Client
|
|
104
|
+
|
|
105
|
+
client = Client(
|
|
106
|
+
base_url="https://api.example.com",
|
|
107
|
+
)
|
|
108
|
+
# Note that base_url needs to be re-set, as would any shared cookies, headers, etc.
|
|
109
|
+
client.set_httpx_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030"))
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Building / publishing this package
|
|
113
|
+
This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics:
|
|
114
|
+
1. Update the metadata in pyproject.toml (e.g. authors, version)
|
|
115
|
+
1. If you're using a private repository, configure it with Poetry
|
|
116
|
+
1. `poetry config repositories.<your-repository-name> <url-to-your-repository>`
|
|
117
|
+
1. `poetry config http-basic.<your-repository-name> <username> <password>`
|
|
118
|
+
1. Publish the client with `poetry publish --build -r <your-repository-name>` or, if for public PyPI, just `poetry publish --build`
|
|
119
|
+
|
|
120
|
+
If you want to install this client into another project without publishing it (e.g. for development) then:
|
|
121
|
+
1. If that project **is using Poetry**, you can simply do `poetry add <path-to-this-client>` from that project
|
|
122
|
+
1. If that project is not using Poetry:
|
|
123
|
+
1. Build a wheel with `poetry build -f wheel`
|
|
124
|
+
1. Install that wheel from the other project `pip install <path-to-wheel>`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains methods for accessing the API"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains endpoint functions for accessing the API"""
|