channel3-sdk 0.2.2__py3-none-any.whl → 2.0.0__py3-none-any.whl

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.

Files changed (54) hide show
  1. channel3_sdk/__init__.py +94 -38
  2. channel3_sdk/_base_client.py +1995 -0
  3. channel3_sdk/_client.py +549 -0
  4. channel3_sdk/_compat.py +219 -0
  5. channel3_sdk/_constants.py +14 -0
  6. channel3_sdk/_exceptions.py +108 -0
  7. channel3_sdk/_files.py +123 -0
  8. channel3_sdk/_models.py +829 -0
  9. channel3_sdk/_qs.py +150 -0
  10. channel3_sdk/_resource.py +43 -0
  11. channel3_sdk/_response.py +832 -0
  12. channel3_sdk/_streaming.py +333 -0
  13. channel3_sdk/_types.py +253 -0
  14. channel3_sdk/_utils/__init__.py +64 -0
  15. channel3_sdk/_utils/_compat.py +45 -0
  16. channel3_sdk/_utils/_datetime_parse.py +136 -0
  17. channel3_sdk/_utils/_logs.py +25 -0
  18. channel3_sdk/_utils/_proxy.py +65 -0
  19. channel3_sdk/_utils/_reflection.py +42 -0
  20. channel3_sdk/_utils/_resources_proxy.py +24 -0
  21. channel3_sdk/_utils/_streams.py +12 -0
  22. channel3_sdk/_utils/_sync.py +86 -0
  23. channel3_sdk/_utils/_transform.py +457 -0
  24. channel3_sdk/_utils/_typing.py +156 -0
  25. channel3_sdk/_utils/_utils.py +421 -0
  26. channel3_sdk/_version.py +4 -0
  27. channel3_sdk/lib/.keep +4 -0
  28. channel3_sdk/py.typed +0 -0
  29. channel3_sdk/resources/__init__.py +61 -0
  30. channel3_sdk/resources/brands.py +268 -0
  31. channel3_sdk/resources/enrich.py +167 -0
  32. channel3_sdk/resources/products.py +163 -0
  33. channel3_sdk/resources/search.py +227 -0
  34. channel3_sdk/types/__init__.py +15 -0
  35. channel3_sdk/types/availability_status.py +9 -0
  36. channel3_sdk/types/brand.py +17 -0
  37. channel3_sdk/types/brand_list_params.py +16 -0
  38. channel3_sdk/types/brand_list_response.py +25 -0
  39. channel3_sdk/types/enrich_enrich_url_params.py +12 -0
  40. channel3_sdk/types/enrich_enrich_url_response.py +20 -0
  41. channel3_sdk/types/price.py +18 -0
  42. channel3_sdk/types/product_retrieve_response.py +39 -0
  43. channel3_sdk/types/search_perform_params.py +61 -0
  44. channel3_sdk/types/search_perform_response.py +36 -0
  45. channel3_sdk/types/variant.py +13 -0
  46. channel3_sdk-2.0.0.dist-info/METADATA +414 -0
  47. channel3_sdk-2.0.0.dist-info/RECORD +49 -0
  48. {channel3_sdk-0.2.2.dist-info → channel3_sdk-2.0.0.dist-info}/WHEEL +1 -1
  49. channel3_sdk-2.0.0.dist-info/licenses/LICENSE +201 -0
  50. channel3_sdk/client.py +0 -574
  51. channel3_sdk/exceptions.py +0 -48
  52. channel3_sdk/models.py +0 -135
  53. channel3_sdk-0.2.2.dist-info/METADATA +0 -284
  54. channel3_sdk-0.2.2.dist-info/RECORD +0 -7
channel3_sdk/models.py DELETED
@@ -1,135 +0,0 @@
1
- """Pydantic models for the Channel3 API."""
2
-
3
- from enum import Enum
4
- from typing import List, Optional, Literal
5
- from pydantic import BaseModel, Field
6
-
7
-
8
- class AvailabilityStatus(str, Enum):
9
- """Availability status of a product."""
10
-
11
- IN_STOCK = "InStock"
12
- OUT_OF_STOCK = "OutOfStock"
13
- PRE_ORDER = "PreOrder"
14
- LIMITED_AVAILABILITY = "LimitedAvailability"
15
- BACK_ORDER = "BackOrder"
16
- DISCONTINUED = "Discontinued"
17
- SOLD_OUT = "SoldOut"
18
- UNKNOWN = "Unknown"
19
-
20
-
21
- class Price(BaseModel):
22
- """Price information for a product."""
23
-
24
- price: float = Field(
25
- ..., description="The current price of the product, including any discounts."
26
- )
27
- compare_at_price: Optional[float] = Field(
28
- None, description="The original price of the product before any discounts."
29
- )
30
- currency: str = Field(..., description="The currency code of the product.")
31
-
32
-
33
- class Brand(BaseModel):
34
- """A brand."""
35
-
36
- id: str = Field(..., description="Unique identifier for the brand")
37
- name: str = Field(..., description="Name of the brand")
38
- logo_url: Optional[str] = Field(None, description="Logo URL for the brand")
39
- description: Optional[str] = Field(None, description="Description of the brand")
40
-
41
-
42
- class Variant(BaseModel):
43
- """A product variant."""
44
-
45
- product_id: str = Field(..., description="Unique identifier for the product")
46
- title: str = Field(..., description="Title of the variant")
47
- image_url: str = Field(..., description="Image URL for the variant")
48
-
49
-
50
- class Product(BaseModel):
51
- """A product returned from search."""
52
-
53
- id: str = Field(..., description="Unique identifier for the product")
54
- url: str = Field(..., description="URL for the product")
55
- score: float = Field(..., description="Relevance score for the search query")
56
- title: str = Field(..., description="Product title")
57
- description: Optional[str] = Field(None, description="Product description")
58
- brand_name: str = Field(..., description="Brand name for the product")
59
- image_url: str = Field(..., description="Main product image URL")
60
- price: Price = Field(..., description="Price information")
61
- availability: AvailabilityStatus = Field(
62
- ..., description="Product availability status"
63
- )
64
- variants: List[Variant] = Field(
65
- default_factory=list, description="Product variants"
66
- )
67
-
68
-
69
- class ProductDetail(BaseModel):
70
- """Detailed information about a product."""
71
-
72
- id: str = Field(..., description="Unique identifier for the product")
73
- url: str = Field(..., description="URL for the product")
74
- score: float = Field(..., description="Relevance score for the search query")
75
- title: str = Field(..., description="Product title")
76
- description: Optional[str] = Field(None, description="Product description")
77
- brand_id: Optional[str] = Field(None, description="Unique identifier for the brand")
78
- brand_name: Optional[str] = Field(None, description="Brand name of the product")
79
- image_urls: Optional[List[str]] = Field(
80
- None, description="List of product image URLs"
81
- )
82
- price: Price = Field(..., description="Price information")
83
- availability: AvailabilityStatus = Field(
84
- ..., description="Product availability status"
85
- )
86
- gender: Optional[Literal["unisex", "men", "women"]] = Field(
87
- None, description="Gender of the product, if applicable"
88
- )
89
- materials: Optional[List[str]] = Field(
90
- None, description="List of materials, if applicable"
91
- )
92
- key_features: Optional[List[str]] = Field(
93
- None, description="List of key product features"
94
- )
95
- variants: List[Variant] = Field(
96
- default_factory=list, description="Product variants"
97
- )
98
-
99
-
100
- class SearchFilterPrice(BaseModel):
101
- """Price filter for product search."""
102
-
103
- min_price: Optional[float] = Field(None, description="Minimum price filter")
104
- max_price: Optional[float] = Field(None, description="Maximum price filter")
105
-
106
-
107
- class SearchFilters(BaseModel):
108
- """Search filters for product search."""
109
-
110
- brand_ids: Optional[List[str]] = Field(
111
- None, description="List of brand IDs to filter by"
112
- )
113
- gender: Optional[Literal["male", "female", "unisex"]] = Field(
114
- None, description="Gender to filter by"
115
- )
116
- price: Optional[SearchFilterPrice] = Field(
117
- None, description="Price range to filter by"
118
- )
119
- availability: Optional[List[AvailabilityStatus]] = Field(
120
- None, description="Availability statuses to filter by"
121
- )
122
-
123
-
124
- class SearchRequest(BaseModel):
125
- """Request model for product search."""
126
-
127
- query: Optional[str] = Field(None, description="Text search query")
128
- image_url: Optional[str] = Field(None, description="URL of image for visual search")
129
- base64_image: Optional[str] = Field(
130
- None, description="Base64-encoded image for visual search"
131
- )
132
- limit: Optional[int] = Field(
133
- default=20, description="Maximum number of results to return"
134
- )
135
- filters: Optional[SearchFilters] = Field(default=None, description="Search filters")
@@ -1,284 +0,0 @@
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
- # Channel3 Python SDK
26
-
27
- The official Python SDK for the [Channel3](https://trychannel3.com) AI Shopping API.
28
-
29
- ## Installation
30
-
31
- ```bash
32
- pip install channel3-sdk
33
- ```
34
-
35
- ## Quick Start
36
-
37
- ### Synchronous Client
38
-
39
- ```python
40
- import os
41
- from channel3_sdk import Channel3Client
42
-
43
- # Initialize the client
44
- client = Channel3Client(api_key="your_api_key_here")
45
- # Or use environment variable: CHANNEL3_API_KEY
46
-
47
- # Search for products
48
- products = client.search(query="blue denim jacket")
49
-
50
- for product in products:
51
- print(f"Product: {product.title}")
52
- print(f"Brand: {product.brand_name}")
53
- print(f"Price: {product.price.currency} {product.price.price}")
54
- print(f"Availability: {product.availability}")
55
- print("---")
56
-
57
- # Get detailed product information
58
- product_detail = client.get_product("prod_123456")
59
- print(f"Detailed info for: {product_detail.title}")
60
- print(f"Brand: {product_detail.brand_name}")
61
- if product_detail.key_features:
62
- print(f"Key features: {product_detail.key_features}")
63
-
64
- # Get all brands
65
- brands = client.get_brands()
66
- for brand in brands:
67
- print(f"Brand: {brand.name}")
68
- if brand.description:
69
- print(f"Description: {brand.description}")
70
-
71
- # Get specific brand details
72
- brand = client.get_brand("brand_123")
73
- print(f"Brand: {brand.name}")
74
- ```
75
-
76
- ### Asynchronous Client
77
-
78
- ```python
79
- import asyncio
80
- from channel3_sdk import AsyncChannel3Client
81
-
82
- async def main():
83
- # Initialize the async client
84
- client = AsyncChannel3Client(api_key="your_api_key_here")
85
-
86
- # Search for products
87
- products = await client.search(query="running shoes")
88
-
89
- for product in products:
90
- print(f"Product: {product.title}")
91
- print(f"Score: {product.score}")
92
- print(f"Price: {product.price.currency} {product.price.price}")
93
-
94
- # Get detailed product information
95
- if products:
96
- product_detail = await client.get_product(products[0].id)
97
- print(f"Availability: {product_detail.availability}")
98
-
99
- # Get brands
100
- brands = await client.get_brands()
101
- print(f"Found {len(brands)} brands")
102
-
103
- # Run the async function
104
- asyncio.run(main())
105
- ```
106
-
107
- ## Advanced Usage
108
-
109
- ### Visual Search
110
-
111
- ```python
112
- # Search by image URL
113
- products = client.search(image_url="https://example.com/image.jpg")
114
-
115
- # Search by base64 image
116
- with open("image.jpg", "rb") as f:
117
- import base64
118
- base64_image = base64.b64encode(f.read()).decode()
119
- products = client.search(base64_image=base64_image)
120
- ```
121
-
122
- ### Multimodal Search
123
-
124
- ```python
125
- # Combine text and image search
126
- products = client.search(
127
- query="blue denim jacket",
128
- image_url="https://example.com/jacket.jpg"
129
- )
130
- ```
131
-
132
- ### Search with Filters
133
-
134
- ```python
135
- from channel3_sdk import SearchFilters, AvailabilityStatus
136
-
137
- # Create search filters
138
- filters = SearchFilters(
139
- brand_ids=["brand_123", "brand_456"],
140
- gender="male",
141
- availability=[AvailabilityStatus.IN_STOCK],
142
- price={"min_price": 50.0, "max_price": 200.0}
143
- )
144
-
145
- # Search with filters
146
- products = client.search(
147
- query="jacket",
148
- filters=filters,
149
- limit=10
150
- )
151
- ```
152
-
153
- ### Brand Management
154
-
155
- ```python
156
- # Get all brands with pagination
157
- brands = client.get_brands(page=1, size=50)
158
-
159
- # Search for specific brands
160
- nike_brands = client.get_brands(query="nike")
161
-
162
- # Get detailed brand information
163
- brand_detail = client.get_brand("brand_123")
164
- print(f"Brand: {brand_detail.name}")
165
- print(f"Logo: {brand_detail.logo_url}")
166
- ```
167
-
168
- ## API Reference
169
-
170
- ### Client Classes
171
-
172
- #### `Channel3Client`
173
- Synchronous client for the Channel3 API.
174
-
175
- **Methods:**
176
- - `search(query=None, image_url=None, base64_image=None, filters=None, limit=20)` → `List[Product]`
177
- - `get_product(product_id)` → `ProductDetail`
178
- - `get_brands(query=None, page=1, size=100)` → `List[Brand]`
179
- - `get_brand(brand_id)` → `Brand`
180
-
181
- #### `AsyncChannel3Client`
182
- Asynchronous client for the Channel3 API.
183
-
184
- **Methods:**
185
- - `async search(query=None, image_url=None, base64_image=None, filters=None, limit=20)` → `List[Product]`
186
- - `async get_product(product_id)` → `ProductDetail`
187
- - `async get_brands(query=None, page=1, size=100)` → `List[Brand]`
188
- - `async get_brand(brand_id)` → `Brand`
189
-
190
- ### Models
191
-
192
- #### `Product`
193
- - `id: str` - Unique product identifier
194
- - `score: float` - Search relevance score
195
- - `title: str` - Product title
196
- - `description: Optional[str]` - Product description
197
- - `brand_name: str` - Brand name
198
- - `image_url: str` - Main product image URL
199
- - `price: Price` - Price information
200
- - `availability: AvailabilityStatus` - Availability status
201
- - `variants: List[Variant]` - Product variants
202
-
203
- #### `ProductDetail`
204
- - `title: str` - Product title
205
- - `description: Optional[str]` - Product description
206
- - `brand_id: Optional[str]` - Brand identifier
207
- - `brand_name: Optional[str]` - Brand name
208
- - `image_urls: Optional[List[str]]` - Product image URLs
209
- - `price: Price` - Price information
210
- - `availability: AvailabilityStatus` - Availability status
211
- - `key_features: Optional[List[str]]` - Key product features
212
- - `variants: List[Variant]` - Product variants
213
-
214
- #### `Brand`
215
- - `id: str` - Unique brand identifier
216
- - `name: str` - Brand name
217
- - `logo_url: Optional[str]` - Brand logo URL
218
- - `description: Optional[str]` - Brand description
219
-
220
- #### `Variant`
221
- - `product_id: str` - Associated product identifier
222
- - `title: str` - Variant title
223
- - `image_url: str` - Variant image URL
224
-
225
- #### `SearchFilters`
226
- - `brand_ids: Optional[List[str]]` - Brand ID filters
227
- - `gender: Optional[Literal["male", "female", "unisex"]]` - Gender filter
228
- - `price: Optional[SearchFilterPrice]` - Price range filter
229
- - `availability: Optional[List[AvailabilityStatus]]` - Availability filters
230
-
231
- #### `SearchFilterPrice`
232
- - `min_price: Optional[float]` - Minimum price
233
- - `max_price: Optional[float]` - Maximum price
234
-
235
- #### `Price`
236
- - `price: float` - Current price
237
- - `compare_at_price: Optional[float]` - Original price (if discounted)
238
- - `currency: str` - Currency code
239
-
240
- #### `AvailabilityStatus`
241
- Enum with values: `IN_STOCK`, `OUT_OF_STOCK`, `PRE_ORDER`, `LIMITED_AVAILABILITY`, `BACK_ORDER`, `DISCONTINUED`, `SOLD_OUT`, `UNKNOWN`
242
-
243
- ## Error Handling
244
-
245
- The SDK provides specific exception types for different error conditions:
246
-
247
- ```python
248
- from channel3_sdk import (
249
- Channel3AuthenticationError,
250
- Channel3ValidationError,
251
- Channel3NotFoundError,
252
- Channel3ServerError,
253
- Channel3ConnectionError
254
- )
255
-
256
- try:
257
- products = client.search(query="shoes")
258
- except Channel3AuthenticationError:
259
- print("Invalid API key")
260
- except Channel3ValidationError as e:
261
- print(f"Invalid request: {e.message}")
262
- except Channel3NotFoundError:
263
- print("Resource not found")
264
- except Channel3ServerError:
265
- print("Server error - please try again later")
266
- except Channel3ConnectionError:
267
- print("Connection error - check your internet connection")
268
- ```
269
-
270
- ## Environment Variables
271
-
272
- - `CHANNEL3_API_KEY` - Your Channel3 API key
273
-
274
- ## Requirements
275
-
276
- - Python 3.8+
277
- - requests
278
- - aiohttp
279
- - pydantic
280
-
281
- ## License
282
-
283
- MIT License
284
-
@@ -1,7 +0,0 @@
1
- channel3_sdk/__init__.py,sha256=vMrsZwY59OoYmoPwEnZ0kuAuWFkOIERUaoy0lWpGIlc,976
2
- channel3_sdk/client.py,sha256=wNqM9d7M2eiWOZ0Xp9rJGjINUrsaHYXiBJktBfPD-18,20776
3
- channel3_sdk/exceptions.py,sha256=5HJgrhir4-_b4XKyWAB9qp-CjVZeigXSkyM9fbcB1IA,1044
4
- channel3_sdk/models.py,sha256=Qzq4evy1LAyekw9KU8VfV_yn9qeTf6rPj9x_R2ANeH4,5039
5
- channel3_sdk-0.2.2.dist-info/METADATA,sha256=IM9BZe8al3570-PczGj8PhQHJHlFU0uyCZnMl60a8f0,7799
6
- channel3_sdk-0.2.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
- channel3_sdk-0.2.2.dist-info/RECORD,,