labelinn 1.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,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to the LabelInn Python SDK will be documented in this file.
4
+
5
+ This project adheres to [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [1.1.0] - 2026-03-18
8
+
9
+ ### Added
10
+
11
+ - `ConnectResource` — universal data ingestion (XML, CSV, JSON, TSV, NDJSON)
12
+ - `connect.ingest()` — push data in any format
13
+ - `connect.test_parse()` — dry-run parse without storing
14
+ - `connect.sources.create/list/get/update/delete()` — manage connector sources
15
+ - `connect.sources.records()` — list ingested records
16
+ - `connect.sources.schema()` — get auto-discovered schema
17
+ - `connect.sources.get_mappings/update_mappings()` — field→label mappings
18
+ - `connect.sources.print_labels()` — print from connector data
19
+ - CLI: `labelinn connect sources`, `connect ingest`, `connect parse`
20
+
21
+ ## [1.0.0] - 2026-03-30
22
+
23
+ ### Added
24
+
25
+ - Initial public release
26
+ - `PrintResource` — create, list, get, cancel, reprint print jobs
27
+ - `FleetResource` — list printers, get details, check status
28
+ - `DesignsResource` — full design CRUD, element management, variables, clone, render, print
29
+ - `WebhooksResource` — create, list, delete, test webhook subscriptions
30
+ - `LabelInnError` and `RateLimitError` exception classes
31
+ - Idempotency support via `idempotency_key` parameter
32
+ - Test mode detection (`sk_test_*` keys)
33
+ - Rate limit info on every response
34
+ - CLI tool: `labelinn test|printers|print|jobs|designs|webhooks`
35
+ - Full type annotations (`py.typed`)
36
+ - Single dependency: `requests`
labelinn-1.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LabelInn
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,4 @@
1
+ include LICENSE
2
+ include CHANGELOG.md
3
+ include labelinn/py.typed
4
+ recursive-include labelinn *.py *.pyi
@@ -0,0 +1,439 @@
1
+ Metadata-Version: 2.4
2
+ Name: labelinn
3
+ Version: 1.1.0
4
+ Summary: Official Python SDK for the LabelInn Cloud Print API. Send labels to Zebra, TSC, and Honeywell thermal printers from any system.
5
+ Author-email: LabelInn <support@labelinn.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://labelinn.com
8
+ Project-URL: Documentation, https://labelinn.com/developers
9
+ Project-URL: Repository, https://github.com/labelcraft31/labelinn-python
10
+ Project-URL: Issues, https://github.com/labelcraft31/labelinn-python/issues
11
+ Project-URL: Changelog, https://github.com/labelcraft31/labelinn-python/blob/main/CHANGELOG.md
12
+ Keywords: labelinn,label,printer,zebra,tsc,honeywell,zpl,barcode,thermal,cloud-print,shipping,warehouse,logistics,ecommerce
13
+ Classifier: Development Status :: 5 - Production/Stable
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.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Printing
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Topic :: System :: Hardware
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.8
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: requests>=2.25.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=7.0; extra == "dev"
34
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.0; extra == "dev"
36
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
37
+ Requires-Dist: responses>=0.23.0; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ # LabelInn Python SDK
41
+
42
+ [![PyPI version](https://img.shields.io/pypi/v/labelinn.svg)](https://pypi.org/project/labelinn/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
44
+ [![Python](https://img.shields.io/pypi/pyversions/labelinn.svg)](https://pypi.org/project/labelinn/)
45
+
46
+ Official Python SDK for the [LabelInn](https://labelinn.com) Cloud Print API. Send labels to thermal printers (Zebra, TSC, Honeywell), manage your fleet, and build print automation workflows.
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ pip install labelinn
52
+ ```
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ from labelinn import LabelInn
58
+
59
+ # Use a test key for development (no real prints)
60
+ client = LabelInn("sk_test_xxxxx")
61
+
62
+ # Print a ZPL label
63
+ job = client.print.create(
64
+ printer_id="prt_abc123",
65
+ payload_type="zpl",
66
+ payload_data="^XA^FO50,50^ADN,36,20^FDHello World^FS^XZ",
67
+ )
68
+ print(f"Job {job['id']} → {job['status']}")
69
+ ```
70
+
71
+ ## Authentication
72
+
73
+ Get your API key from **LabelInn → Settings → API Keys**.
74
+
75
+ | Key prefix | Mode | Description |
76
+ |---------------|---------|------------------------------------|
77
+ | `sk_test_xxx` | Sandbox | No real prints, separate quota |
78
+ | `sk_live_xxx` | Live | Sends jobs to physical printers |
79
+
80
+ ```python
81
+ # Test mode — safe for development
82
+ dev = LabelInn("sk_test_xxxxx")
83
+ print(dev.is_test_mode) # True
84
+
85
+ # Live mode — real prints
86
+ prod = LabelInn("sk_live_xxxxx")
87
+ ```
88
+
89
+ ## Print Jobs
90
+
91
+ ### Send a ZPL label
92
+
93
+ ```python
94
+ job = client.print.create(
95
+ printer_id="prt_abc123",
96
+ payload_type="zpl",
97
+ payload_data="^XA^FO50,50^ADN,36,20^FDShipping Label^FS^XZ",
98
+ copies=2,
99
+ job_name="Order #1234",
100
+ )
101
+ ```
102
+
103
+ ### Send an image label
104
+
105
+ ```python
106
+ job = client.print.create(
107
+ printer_id="prt_abc123",
108
+ payload_type="image",
109
+ image_url="https://example.com/labels/shipping.png",
110
+ )
111
+ ```
112
+
113
+ ### Print from a template
114
+
115
+ ```python
116
+ job = client.print.create(
117
+ printer_id="prt_abc123",
118
+ payload_type="template",
119
+ design_id="dsg_shipping_v2",
120
+ data={
121
+ "order_id": "ORD-9876",
122
+ "customer": "Ali Yilmaz",
123
+ "barcode": "TR123456789",
124
+ },
125
+ )
126
+ ```
127
+
128
+ ### Idempotency (prevent duplicate prints)
129
+
130
+ ```python
131
+ job = client.print.create(
132
+ printer_id="prt_abc123",
133
+ payload_type="zpl",
134
+ payload_data="^XA...^XZ",
135
+ idempotency_key="order-9876-label",
136
+ )
137
+ # Calling again with the same key returns the original job
138
+ ```
139
+
140
+ ### List & manage jobs
141
+
142
+ ```python
143
+ # List recent jobs
144
+ result = client.print.list(limit=10)
145
+
146
+ # Filter by status
147
+ result = client.print.list(status="failed")
148
+
149
+ # Get job details
150
+ job = client.print.get("job_abc123")
151
+
152
+ # Cancel a queued job
153
+ client.print.cancel("job_abc123")
154
+
155
+ # Reprint with different printer
156
+ client.print.reprint("job_abc123", printer_id="prt_backup")
157
+ ```
158
+
159
+ ## Fleet Management
160
+
161
+ ```python
162
+ # List all printers
163
+ result = client.fleet.list()
164
+
165
+ # Filter by status
166
+ result = client.fleet.list(status="online")
167
+
168
+ # Get printer details
169
+ printer = client.fleet.get("prt_abc123")
170
+
171
+ # Quick status check
172
+ status = client.fleet.status("prt_abc123")
173
+ ```
174
+
175
+ ## Designs (Templates)
176
+
177
+ ```python
178
+ # List designs
179
+ result = client.designs.list()
180
+
181
+ # Get design with elements
182
+ design = client.designs.get("dsg_abc123")
183
+
184
+ # Get template variables
185
+ variables = client.designs.list_variables("dsg_abc123")
186
+
187
+ # Clone a design
188
+ clone = client.designs.clone("dsg_abc123")
189
+
190
+ # Print directly
191
+ client.designs.print(
192
+ "dsg_abc123",
193
+ printer_id="prt_abc123",
194
+ data={"order_id": "ORD-5555", "tracking_number": "TR999"},
195
+ copies=1,
196
+ )
197
+ ```
198
+
199
+ ## Webhooks
200
+
201
+ ```python
202
+ # Subscribe to events
203
+ webhook = client.webhooks.create(
204
+ url="https://yourapp.com/webhooks/labelinn",
205
+ events=["print.job.completed", "print.job.failed", "printer.status.changed"],
206
+ description="Production monitoring",
207
+ )
208
+
209
+ # Save the signing secret!
210
+ print("Secret:", webhook["signing_secret"])
211
+
212
+ # List subscriptions
213
+ result = client.webhooks.list()
214
+
215
+ # Send a test ping
216
+ client.webhooks.test(webhook["id"])
217
+
218
+ # Unsubscribe
219
+ client.webhooks.delete(webhook["id"])
220
+ ```
221
+
222
+ ### Verifying webhook signatures
223
+
224
+ ```python
225
+ from labelinn.webhooks import verify_signature
226
+
227
+ # In your Flask handler:
228
+ @app.route("/webhooks/labelinn", methods=["POST"])
229
+ def handle_webhook():
230
+ is_valid = verify_signature(
231
+ payload=request.data.decode(),
232
+ signature=request.headers["X-LabelInn-Signature"],
233
+ secret=WEBHOOK_SECRET,
234
+ )
235
+ if not is_valid:
236
+ return "Invalid signature", 401
237
+
238
+ event = request.json
239
+ print(f"Event: {event['event']}")
240
+ return "ok", 200
241
+ ```
242
+
243
+ ## Data Connect
244
+
245
+ Data Connect lets you ingest data from any enterprise system (SAP, Oracle, CSV exports, custom APIs) and print labels from it. Supports XML/IDoc, CSV/TSV, and JSON/NDJSON formats with auto-detection.
246
+
247
+ ### Ingest Data
248
+
249
+ ```python
250
+ # From a JSON payload
251
+ result = client.connect.ingest(
252
+ source_id="src_abc123",
253
+ payload='[{"sku": "A001", "name": "Widget"}, {"sku": "A002", "name": "Gadget"}]',
254
+ format="json",
255
+ )
256
+ print(f"Ingested {result['records_count']} records")
257
+
258
+ # From XML/IDoc
259
+ result = client.connect.ingest(
260
+ source_id="src_sap",
261
+ payload=xml_string,
262
+ format="xml",
263
+ )
264
+ ```
265
+
266
+ ### Test Parse (Dry Run)
267
+
268
+ ```python
269
+ parsed = client.connect.test_parse(payload=csv_string, format="csv")
270
+ print(f"Detected {len(parsed['records'])} records")
271
+ for field in parsed["schema"]:
272
+ print(f" {field['path']} ({field['type']})")
273
+ ```
274
+
275
+ ### Manage Sources
276
+
277
+ ```python
278
+ # Create a source
279
+ source = client.connect.create_source(name="SAP Orders", format="xml")
280
+
281
+ # List all sources
282
+ sources = client.connect.list_sources()
283
+
284
+ # Get source details
285
+ detail = client.connect.get_source("src_abc123")
286
+
287
+ # Update a source
288
+ client.connect.update_source("src_abc123", name="SAP Orders v2")
289
+
290
+ # Delete a source
291
+ client.connect.delete_source("src_abc123")
292
+ ```
293
+
294
+ ### Schema & Records
295
+
296
+ ```python
297
+ # Get detected schema
298
+ schema = client.connect.get_schema("src_abc123")
299
+ for field in schema["fields"]:
300
+ print(f"{field['path']} ({field['type']}): {field['sample']}")
301
+
302
+ # List ingested records
303
+ records = client.connect.list_records("src_abc123", limit=50)
304
+ ```
305
+
306
+ ### Field Mappings
307
+
308
+ ```python
309
+ # Get current mappings
310
+ mappings = client.connect.get_mappings("src_abc123")
311
+
312
+ # Update mappings
313
+ client.connect.update_mappings("src_abc123", {"sku": "product_code", "name": "product_name"})
314
+ ```
315
+
316
+ ### Print from Connector
317
+
318
+ ```python
319
+ result = client.connect.print(
320
+ source_id="src_abc123",
321
+ design_id="dsg_shipping",
322
+ printer_id="prt_warehouse1",
323
+ copies=1,
324
+ )
325
+ print(f"Created {result['count']} print jobs")
326
+ ```
327
+
328
+ ## Rate Limits
329
+
330
+ Every response includes rate limit info:
331
+
332
+ ```python
333
+ result = client.print.list()
334
+ print(result["_rate_limit"])
335
+ # {"limit": 2000, "remaining": 1847, "reset": 3600}
336
+ ```
337
+
338
+ | Plan | Daily Limit |
339
+ |------------|-------------|
340
+ | Pro | 2,000 |
341
+ | Enterprise | 50,000 |
342
+ | Test keys | 500 minimum |
343
+
344
+ When rate-limited, the SDK raises `RateLimitError`:
345
+
346
+ ```python
347
+ from labelinn import RateLimitError
348
+
349
+ try:
350
+ client.print.create(...)
351
+ except RateLimitError as e:
352
+ print(f"Rate limited. Retry in {e.retry_after}s")
353
+ ```
354
+
355
+ ## Error Handling
356
+
357
+ ```python
358
+ from labelinn import LabelInnError
359
+
360
+ try:
361
+ client.print.create(...)
362
+ except LabelInnError as e:
363
+ print(f"[{e.status}] {e.code}: {e.message}")
364
+ # e.raw contains the full response body
365
+ ```
366
+
367
+ ## CLI Tool
368
+
369
+ The SDK includes a command-line tool:
370
+
371
+ ```bash
372
+ # Set your API key
373
+ export LABELINN_API_KEY=sk_test_xxxxx
374
+
375
+ # Verify connectivity
376
+ labelinn test
377
+
378
+ # List printers
379
+ labelinn printers
380
+
381
+ # Print a ZPL label
382
+ labelinn print prt_abc123 --zpl "^XA^FO50,50^ADN,36,20^FDHello^FS^XZ"
383
+
384
+ # Print from a template
385
+ labelinn print prt_abc123 --design dsg_shipping --data '{"name": "Ali"}'
386
+
387
+ # List jobs
388
+ labelinn jobs
389
+
390
+ # --- Data Connect ---
391
+ # List connected data sources
392
+ labelinn connect sources
393
+
394
+ # Ingest data from a file
395
+ labelinn connect ingest conn_abc123 --file data.csv
396
+
397
+ # Test-parse a local file
398
+ labelinn connect parse --file data.csv --format csv
399
+
400
+ # Get help
401
+ labelinn --help
402
+ ```
403
+
404
+ ## Configuration
405
+
406
+ ```python
407
+ client = LabelInn(
408
+ "sk_test_xxxxx",
409
+ base_url="https://labelinn.com/v1", # default
410
+ timeout=30, # 30s default
411
+ )
412
+ ```
413
+
414
+ ## Requirements
415
+
416
+ - Python 3.8+
417
+ - `requests` (only dependency)
418
+
419
+ ## Contributing
420
+
421
+ Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/ArisHub/labelinn-python).
422
+
423
+ 1. Fork the repository
424
+ 2. Create your feature branch (`git checkout -b feature/my-feature`)
425
+ 3. Install dev dependencies: `pip install -e ".[dev]"`
426
+ 4. Run tests: `pytest`
427
+ 5. Submit a Pull Request
428
+
429
+ ## Links
430
+
431
+ - [LabelInn Website](https://labelinn.com)
432
+ - [API Documentation](https://labelinn.com/developers)
433
+ - [Node.js SDK](https://github.com/ArisHub/labelinn-node)
434
+ - [Changelog](./CHANGELOG.md)
435
+ - [Report a Bug](https://github.com/ArisHub/labelinn-python/issues)
436
+
437
+ ## License
438
+
439
+ MIT — see [LICENSE](./LICENSE) for details.