colacloud 0.1.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.
@@ -0,0 +1,153 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+
72
+ # PyBuilder
73
+ .pybuilder/
74
+ target/
75
+
76
+ # Jupyter Notebook
77
+ .ipynb_checkpoints
78
+
79
+ # IPython
80
+ profile_default/
81
+ ipython_config.py
82
+
83
+ # pyenv
84
+ .python-version
85
+
86
+ # pipenv
87
+ Pipfile.lock
88
+
89
+ # UV
90
+ uv.lock
91
+
92
+ # PEP 582
93
+ __pypackages__/
94
+
95
+ # Celery stuff
96
+ celerybeat-schedule
97
+ celerybeat.pid
98
+
99
+ # SageMath parsed files
100
+ *.sage.py
101
+
102
+ # Environments
103
+ .env
104
+ .venv
105
+ env/
106
+ venv/
107
+ ENV/
108
+ env.bak/
109
+ venv.bak/
110
+
111
+ # Spyder project settings
112
+ .spyderproject
113
+ .spyproject
114
+
115
+ # Rope project settings
116
+ .ropeproject
117
+
118
+ # mkdocs documentation
119
+ /site
120
+
121
+ # mypy
122
+ .mypy_cache/
123
+ .dmypy.json
124
+ dmypy.json
125
+
126
+ # Pyre type checker
127
+ .pyre/
128
+
129
+ # pytype static type analyzer
130
+ .pytype/
131
+
132
+ # Cython debug symbols
133
+ cython_debug/
134
+
135
+ # IDE
136
+ .idea/
137
+ .vscode/
138
+ *.swp
139
+ *.swo
140
+ *~
141
+
142
+ # OS
143
+ .DS_Store
144
+ .DS_Store?
145
+ ._*
146
+ .Spotlight-V100
147
+ .Trashes
148
+ ehthumbs.db
149
+ Thumbs.db
150
+
151
+ # Project specific
152
+ .env.local
153
+ .env.*.local
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 COLA Cloud
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,387 @@
1
+ Metadata-Version: 2.4
2
+ Name: colacloud
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the COLA Cloud API - Access the TTB COLA Registry of alcohol product label approvals
5
+ Project-URL: Homepage, https://colacloud.us
6
+ Project-URL: Documentation, https://colacloud.us/docs/api
7
+ Project-URL: Repository, https://github.com/cola-cloud-us/colacloud-python
8
+ Project-URL: Issues, https://github.com/cola-cloud-us/colacloud-python/issues
9
+ Author-email: COLA Cloud <support@colacloud.us>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: alcohol,api,beer,beverages,cola,labels,sdk,spirits,ttb,wine
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: httpx>=0.25.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: black>=24.0.0; extra == 'dev'
29
+ Requires-Dist: isort>=5.13.0; extra == 'dev'
30
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
32
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
33
+ Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
34
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
35
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # COLA Cloud Python SDK
39
+
40
+ Official Python SDK for the [COLA Cloud API](https://colacloud.us) - Access the TTB COLA Registry of alcohol product label approvals.
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ pip install colacloud
46
+ ```
47
+
48
+ Or with `uv`:
49
+
50
+ ```bash
51
+ uv add colacloud
52
+ ```
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ from colacloud import ColaCloud
58
+
59
+ # Initialize the client
60
+ client = ColaCloud(api_key="your-api-key")
61
+
62
+ # Search COLAs
63
+ colas = client.colas.list(q="bourbon", product_type="distilled spirits")
64
+ for cola in colas.data:
65
+ print(f"{cola.brand_name}: {cola.product_name}")
66
+
67
+ # Get a single COLA by TTB ID
68
+ cola = client.colas.get("12345678")
69
+ print(f"ABV: {cola.abv}%")
70
+ print(f"Images: {len(cola.images)}")
71
+
72
+ # Iterate through all results with automatic pagination
73
+ for cola in client.colas.iterate(q="whiskey"):
74
+ print(cola.ttb_id)
75
+
76
+ # Don't forget to close when done
77
+ client.close()
78
+ ```
79
+
80
+ ## Features
81
+
82
+ - **Sync and Async Clients**: Use `ColaCloud` for synchronous code or `AsyncColaCloud` for async/await
83
+ - **Type Hints**: Full type annotations with Pydantic models
84
+ - **Automatic Pagination**: Iterate through large result sets effortlessly
85
+ - **Rate Limit Handling**: Access rate limit info from response headers
86
+ - **Custom Exceptions**: Specific exceptions for different error types
87
+
88
+ ## Synchronous Client
89
+
90
+ ```python
91
+ from colacloud import ColaCloud
92
+
93
+ # Using context manager (recommended)
94
+ with ColaCloud(api_key="your-api-key") as client:
95
+ # Search COLAs
96
+ response = client.colas.list(
97
+ q="cabernet",
98
+ product_type="wine",
99
+ origin="California",
100
+ abv_min=12.0,
101
+ abv_max=15.0,
102
+ page=1,
103
+ per_page=50
104
+ )
105
+
106
+ print(f"Found {response.pagination.total} COLAs")
107
+ for cola in response.data:
108
+ print(f"- {cola.brand_name}: {cola.product_name}")
109
+
110
+ # Or manage lifecycle manually
111
+ client = ColaCloud(api_key="your-api-key")
112
+ try:
113
+ colas = client.colas.list(q="bourbon")
114
+ finally:
115
+ client.close()
116
+ ```
117
+
118
+ ## Asynchronous Client
119
+
120
+ ```python
121
+ import asyncio
122
+ from colacloud import AsyncColaCloud
123
+
124
+ async def main():
125
+ async with AsyncColaCloud(api_key="your-api-key") as client:
126
+ # Search COLAs
127
+ response = await client.colas.list(q="bourbon")
128
+
129
+ # Async iteration
130
+ async for cola in client.colas.iterate(q="whiskey"):
131
+ print(cola.ttb_id)
132
+
133
+ asyncio.run(main())
134
+ ```
135
+
136
+ ## API Reference
137
+
138
+ ### COLAs
139
+
140
+ #### List/Search COLAs
141
+
142
+ ```python
143
+ response = client.colas.list(
144
+ q="search query", # Full-text search
145
+ product_type="wine", # malt beverage, wine, distilled spirits
146
+ origin="France", # Country or state
147
+ brand_name="Chateau", # Partial match
148
+ approval_date_from="2024-01-01",
149
+ approval_date_to="2024-12-31",
150
+ abv_min=10.0,
151
+ abv_max=20.0,
152
+ page=1,
153
+ per_page=20 # Max 100
154
+ )
155
+
156
+ # Access results
157
+ for cola in response.data:
158
+ print(cola.ttb_id, cola.brand_name)
159
+
160
+ # Pagination info
161
+ print(f"Page {response.pagination.page} of {response.pagination.pages}")
162
+ print(f"Total results: {response.pagination.total}")
163
+ ```
164
+
165
+ #### Get Single COLA
166
+
167
+ ```python
168
+ cola = client.colas.get("12345678")
169
+
170
+ # Basic info
171
+ print(cola.ttb_id)
172
+ print(cola.brand_name)
173
+ print(cola.product_name)
174
+ print(cola.product_type)
175
+ print(cola.abv)
176
+
177
+ # Images
178
+ for image in cola.images:
179
+ print(f"{image.container_position}: {image.image_url}")
180
+
181
+ # Barcodes
182
+ for barcode in cola.barcodes:
183
+ print(f"{barcode.barcode_type}: {barcode.barcode_value}")
184
+
185
+ # LLM-enriched data
186
+ print(cola.llm_product_description)
187
+ print(cola.llm_category_path)
188
+ print(cola.llm_tasting_note_flavors)
189
+ ```
190
+
191
+ #### Iterate All Results
192
+
193
+ ```python
194
+ # Automatically handles pagination
195
+ for cola in client.colas.iterate(q="bourbon", per_page=100):
196
+ print(cola.ttb_id)
197
+
198
+ # With filters
199
+ for cola in client.colas.iterate(
200
+ product_type="distilled spirits",
201
+ origin="Kentucky",
202
+ abv_min=40.0
203
+ ):
204
+ process_cola(cola)
205
+ ```
206
+
207
+ ### Permittees
208
+
209
+ #### List/Search Permittees
210
+
211
+ ```python
212
+ response = client.permittees.list(
213
+ q="distillery", # Search by company name
214
+ state="CA", # Two-letter state code
215
+ is_active=True, # Active permit status
216
+ page=1,
217
+ per_page=20
218
+ )
219
+
220
+ for permittee in response.data:
221
+ print(f"{permittee.company_name}: {permittee.colas} COLAs")
222
+ ```
223
+
224
+ #### Get Single Permittee
225
+
226
+ ```python
227
+ permittee = client.permittees.get("CA-I-12345")
228
+
229
+ print(permittee.company_name)
230
+ print(permittee.company_state)
231
+ print(permittee.colas) # Total COLAs
232
+ print(permittee.is_active)
233
+
234
+ # Recent COLAs from this permittee
235
+ for cola in permittee.recent_colas:
236
+ print(f"- {cola.brand_name}")
237
+ ```
238
+
239
+ #### Iterate All Permittees
240
+
241
+ ```python
242
+ for permittee in client.permittees.iterate(state="NY"):
243
+ print(f"{permittee.permit_number}: {permittee.company_name}")
244
+ ```
245
+
246
+ ### Barcode Lookup
247
+
248
+ ```python
249
+ result = client.barcode.lookup("012345678901")
250
+
251
+ print(f"Barcode: {result.barcode_value}")
252
+ print(f"Type: {result.barcode_type}")
253
+ print(f"Found {result.total_colas} COLAs")
254
+
255
+ for cola in result.colas:
256
+ print(f"- {cola.brand_name}")
257
+ ```
258
+
259
+ ### API Usage
260
+
261
+ ```python
262
+ usage = client.get_usage()
263
+
264
+ print(f"Tier: {usage.tier}")
265
+ print(f"Monthly limit: {usage.monthly_limit}")
266
+ print(f"Requests used: {usage.requests_used}")
267
+ print(f"Remaining: {usage.requests_remaining}")
268
+ print(f"Per-minute limit: {usage.per_minute_limit}")
269
+ ```
270
+
271
+ ### Rate Limit Info
272
+
273
+ ```python
274
+ # After any request, access rate limit headers
275
+ client.colas.list(q="test")
276
+ rate_limit = client.rate_limit_info
277
+
278
+ if rate_limit:
279
+ print(f"Remaining this minute: {rate_limit.remaining}")
280
+ print(f"Monthly remaining: {rate_limit.monthly_remaining}")
281
+ ```
282
+
283
+ ## Error Handling
284
+
285
+ ```python
286
+ from colacloud import (
287
+ ColaCloud,
288
+ ColaCloudError,
289
+ AuthenticationError,
290
+ RateLimitError,
291
+ NotFoundError,
292
+ ValidationError,
293
+ ServerError,
294
+ )
295
+
296
+ client = ColaCloud(api_key="your-api-key")
297
+
298
+ try:
299
+ cola = client.colas.get("12345678")
300
+ except AuthenticationError:
301
+ print("Invalid API key")
302
+ except NotFoundError:
303
+ print("COLA not found")
304
+ except RateLimitError as e:
305
+ print(f"Rate limit exceeded. Retry after {e.retry_after} seconds")
306
+ except ValidationError as e:
307
+ print(f"Invalid request: {e.message}")
308
+ except ServerError:
309
+ print("Server error, try again later")
310
+ except ColaCloudError as e:
311
+ print(f"API error: {e}")
312
+ ```
313
+
314
+ ## Configuration
315
+
316
+ ```python
317
+ from colacloud import ColaCloud
318
+
319
+ # Custom configuration
320
+ client = ColaCloud(
321
+ api_key="your-api-key",
322
+ base_url="https://custom.api.com/v1", # For testing
323
+ timeout=60.0, # Request timeout in seconds
324
+ )
325
+
326
+ # Or bring your own HTTP client
327
+ import httpx
328
+
329
+ custom_client = httpx.Client(
330
+ timeout=httpx.Timeout(60.0),
331
+ limits=httpx.Limits(max_connections=10),
332
+ )
333
+
334
+ client = ColaCloud(
335
+ api_key="your-api-key",
336
+ http_client=custom_client,
337
+ )
338
+ ```
339
+
340
+ ## Models
341
+
342
+ All responses are fully typed with Pydantic models:
343
+
344
+ - `ColaSummary` - Summary COLA info (list responses)
345
+ - `ColaDetail` - Full COLA info with images and barcodes
346
+ - `ColaImage` - Image metadata
347
+ - `ColaBarcode` - Barcode data
348
+ - `PermitteeSummary` - Summary permittee info
349
+ - `PermitteeDetail` - Full permittee info with recent COLAs
350
+ - `BarcodeLookupResult` - Barcode lookup results
351
+ - `UsageInfo` - API usage statistics
352
+ - `Pagination` - Pagination metadata
353
+ - `RateLimitInfo` - Rate limit information
354
+
355
+ ## Development
356
+
357
+ ```bash
358
+ # Clone the repository
359
+ git clone https://github.com/cola-cloud-us/colacloud-python.git
360
+ cd colacloud-python
361
+
362
+ # Install dependencies with uv
363
+ uv sync --dev
364
+
365
+ # Run tests
366
+ uv run pytest
367
+
368
+ # Run tests with coverage
369
+ uv run pytest --cov=src/colacloud
370
+
371
+ # Format code
372
+ uv run black .
373
+ uv run isort .
374
+
375
+ # Type checking
376
+ uv run mypy src/colacloud
377
+ ```
378
+
379
+ ## License
380
+
381
+ MIT License - see [LICENSE](LICENSE) for details.
382
+
383
+ ## Links
384
+
385
+ - [COLA Cloud Website](https://colacloud.us)
386
+ - [API Documentation](https://colacloud.us/docs/api)
387
+ - [GitHub Repository](https://github.com/cola-cloud-us/colacloud-python)