datamax-dpl 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.
Files changed (166) hide show
  1. datamax_dpl-0.1.0/.claude-plugin/marketplace.json +16 -0
  2. datamax_dpl-0.1.0/.claude-plugin/plugin.json +11 -0
  3. datamax_dpl-0.1.0/.gitignore +216 -0
  4. datamax_dpl-0.1.0/CHANGELOG.md +43 -0
  5. datamax_dpl-0.1.0/CONFIG.md +657 -0
  6. datamax_dpl-0.1.0/LICENSE +22 -0
  7. datamax_dpl-0.1.0/PKG-INFO +343 -0
  8. datamax_dpl-0.1.0/README.md +281 -0
  9. datamax_dpl-0.1.0/docs/adr/0001-memory-adapters-in-src.md +31 -0
  10. datamax_dpl-0.1.0/docs/capabilities.md +233 -0
  11. datamax_dpl-0.1.0/docs/dpl-reference.md +237 -0
  12. datamax_dpl-0.1.0/docs/label-spec.md +366 -0
  13. datamax_dpl-0.1.0/docs/systemdesign/module_reference.md +152 -0
  14. datamax_dpl-0.1.0/examples/product-label.json +50 -0
  15. datamax_dpl-0.1.0/examples/shipping-label.json +69 -0
  16. datamax_dpl-0.1.0/examples/shipping-records.json +16 -0
  17. datamax_dpl-0.1.0/pyproject.toml +308 -0
  18. datamax_dpl-0.1.0/skills/datamax-dpl/SKILL.md +117 -0
  19. datamax_dpl-0.1.0/src/datamax_dpl/__init__.py +96 -0
  20. datamax_dpl-0.1.0/src/datamax_dpl/__init__conf__.py +90 -0
  21. datamax_dpl-0.1.0/src/datamax_dpl/__main__.py +9 -0
  22. datamax_dpl-0.1.0/src/datamax_dpl/adapters/__init__.py +14 -0
  23. datamax_dpl-0.1.0/src/datamax_dpl/adapters/camera/__init__.py +117 -0
  24. datamax_dpl-0.1.0/src/datamax_dpl/adapters/camera/command.py +144 -0
  25. datamax_dpl-0.1.0/src/datamax_dpl/adapters/camera/file.py +138 -0
  26. datamax_dpl-0.1.0/src/datamax_dpl/adapters/camera/http.py +156 -0
  27. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/__init__.py +56 -0
  28. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/commands/__init__.py +52 -0
  29. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/commands/config.py +529 -0
  30. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/commands/info.py +38 -0
  31. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/commands/labels.py +272 -0
  32. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/commands/model_options.py +80 -0
  33. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/commands/printer.py +264 -0
  34. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/config_load.py +206 -0
  35. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/constants.py +28 -0
  36. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/context.py +184 -0
  37. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/envelope.py +97 -0
  38. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/exit_codes.py +59 -0
  39. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/label_io.py +144 -0
  40. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/main.py +123 -0
  41. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/payloads.py +92 -0
  42. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/py.typed +0 -0
  43. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/root.py +181 -0
  44. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/runner.py +90 -0
  45. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/safe_console.py +315 -0
  46. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/settings.py +142 -0
  47. datamax_dpl-0.1.0/src/datamax_dpl/adapters/cli/typed_click.py +77 -0
  48. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/__init__.py +25 -0
  49. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/defaultconfig.d/40-layered-config.toml +78 -0
  50. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/defaultconfig.d/50-printer.toml +86 -0
  51. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/defaultconfig.d/60-camera.toml +66 -0
  52. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/defaultconfig.d/90-logging.toml +448 -0
  53. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/defaultconfig.toml +56 -0
  54. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/deploy.py +135 -0
  55. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/display.py +60 -0
  56. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/loader.py +210 -0
  57. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/overrides.py +305 -0
  58. datamax_dpl-0.1.0/src/datamax_dpl/adapters/config/py.typed +0 -0
  59. datamax_dpl-0.1.0/src/datamax_dpl/adapters/logging/__init__.py +13 -0
  60. datamax_dpl-0.1.0/src/datamax_dpl/adapters/logging/py.typed +0 -0
  61. datamax_dpl-0.1.0/src/datamax_dpl/adapters/logging/setup.py +437 -0
  62. datamax_dpl-0.1.0/src/datamax_dpl/adapters/memory/__init__.py +54 -0
  63. datamax_dpl-0.1.0/src/datamax_dpl/adapters/memory/camera.py +109 -0
  64. datamax_dpl-0.1.0/src/datamax_dpl/adapters/memory/config.py +66 -0
  65. datamax_dpl-0.1.0/src/datamax_dpl/adapters/memory/logging.py +80 -0
  66. datamax_dpl-0.1.0/src/datamax_dpl/adapters/memory/printer.py +125 -0
  67. datamax_dpl-0.1.0/src/datamax_dpl/adapters/preview/__init__.py +112 -0
  68. datamax_dpl-0.1.0/src/datamax_dpl/adapters/py.typed +0 -0
  69. datamax_dpl-0.1.0/src/datamax_dpl/adapters/transport/__init__.py +114 -0
  70. datamax_dpl-0.1.0/src/datamax_dpl/adapters/transport/device.py +84 -0
  71. datamax_dpl-0.1.0/src/datamax_dpl/adapters/transport/file.py +101 -0
  72. datamax_dpl-0.1.0/src/datamax_dpl/adapters/transport/serial.py +241 -0
  73. datamax_dpl-0.1.0/src/datamax_dpl/adapters/transport/tcp.py +167 -0
  74. datamax_dpl-0.1.0/src/datamax_dpl/adapters/transport/uri.py +372 -0
  75. datamax_dpl-0.1.0/src/datamax_dpl/application/__init__.py +28 -0
  76. datamax_dpl-0.1.0/src/datamax_dpl/application/ports.py +155 -0
  77. datamax_dpl-0.1.0/src/datamax_dpl/application/py.typed +0 -0
  78. datamax_dpl-0.1.0/src/datamax_dpl/application/use_cases.py +217 -0
  79. datamax_dpl-0.1.0/src/datamax_dpl/application/verify.py +116 -0
  80. datamax_dpl-0.1.0/src/datamax_dpl/composition/__init__.py +146 -0
  81. datamax_dpl-0.1.0/src/datamax_dpl/composition/py.typed +0 -0
  82. datamax_dpl-0.1.0/src/datamax_dpl/domain/__init__.py +20 -0
  83. datamax_dpl-0.1.0/src/datamax_dpl/domain/barcodes.py +496 -0
  84. datamax_dpl-0.1.0/src/datamax_dpl/domain/batch.py +79 -0
  85. datamax_dpl-0.1.0/src/datamax_dpl/domain/camera.py +71 -0
  86. datamax_dpl-0.1.0/src/datamax_dpl/domain/charset.py +205 -0
  87. datamax_dpl-0.1.0/src/datamax_dpl/domain/decoder.py +370 -0
  88. datamax_dpl-0.1.0/src/datamax_dpl/domain/detect.py +107 -0
  89. datamax_dpl-0.1.0/src/datamax_dpl/domain/encode_barcode.py +145 -0
  90. datamax_dpl-0.1.0/src/datamax_dpl/domain/encode_common.py +86 -0
  91. datamax_dpl-0.1.0/src/datamax_dpl/domain/encode_graphics.py +140 -0
  92. datamax_dpl-0.1.0/src/datamax_dpl/domain/encode_text.py +137 -0
  93. datamax_dpl-0.1.0/src/datamax_dpl/domain/enums.py +219 -0
  94. datamax_dpl-0.1.0/src/datamax_dpl/domain/errors.py +66 -0
  95. datamax_dpl-0.1.0/src/datamax_dpl/domain/findings.py +89 -0
  96. datamax_dpl-0.1.0/src/datamax_dpl/domain/image_records.py +226 -0
  97. datamax_dpl-0.1.0/src/datamax_dpl/domain/job.py +261 -0
  98. datamax_dpl-0.1.0/src/datamax_dpl/domain/label.py +369 -0
  99. datamax_dpl-0.1.0/src/datamax_dpl/domain/placeholders.py +88 -0
  100. datamax_dpl-0.1.0/src/datamax_dpl/domain/png.py +123 -0
  101. datamax_dpl-0.1.0/src/datamax_dpl/domain/preview.py +248 -0
  102. datamax_dpl-0.1.0/src/datamax_dpl/domain/profiles.py +490 -0
  103. datamax_dpl-0.1.0/src/datamax_dpl/domain/py.typed +0 -0
  104. datamax_dpl-0.1.0/src/datamax_dpl/domain/raster.py +536 -0
  105. datamax_dpl-0.1.0/src/datamax_dpl/domain/raster_fallback.py +120 -0
  106. datamax_dpl-0.1.0/src/datamax_dpl/domain/records.py +196 -0
  107. datamax_dpl-0.1.0/src/datamax_dpl/domain/render.py +192 -0
  108. datamax_dpl-0.1.0/src/datamax_dpl/domain/render_context.py +131 -0
  109. datamax_dpl-0.1.0/src/datamax_dpl/domain/status.py +394 -0
  110. datamax_dpl-0.1.0/src/datamax_dpl/domain/symbology.py +125 -0
  111. datamax_dpl-0.1.0/src/datamax_dpl/domain/units.py +127 -0
  112. datamax_dpl-0.1.0/src/datamax_dpl/entry.py +26 -0
  113. datamax_dpl-0.1.0/src/datamax_dpl/py.typed +0 -0
  114. datamax_dpl-0.1.0/tests/conftest.py +587 -0
  115. datamax_dpl-0.1.0/tests/test_barcodes.py +374 -0
  116. datamax_dpl-0.1.0/tests/test_cache_effectiveness.py +155 -0
  117. datamax_dpl-0.1.0/tests/test_camera_command.py +155 -0
  118. datamax_dpl-0.1.0/tests/test_camera_file.py +202 -0
  119. datamax_dpl-0.1.0/tests/test_camera_http.py +226 -0
  120. datamax_dpl-0.1.0/tests/test_capabilities_doc.py +95 -0
  121. datamax_dpl-0.1.0/tests/test_charset.py +214 -0
  122. datamax_dpl-0.1.0/tests/test_cli_commands.py +328 -0
  123. datamax_dpl-0.1.0/tests/test_cli_config.py +886 -0
  124. datamax_dpl-0.1.0/tests/test_cli_config_errors.py +582 -0
  125. datamax_dpl-0.1.0/tests/test_cli_core.py +220 -0
  126. datamax_dpl-0.1.0/tests/test_cli_env_file.py +170 -0
  127. datamax_dpl-0.1.0/tests/test_cli_exit_codes.py +83 -0
  128. datamax_dpl-0.1.0/tests/test_cli_main_exit.py +122 -0
  129. datamax_dpl-0.1.0/tests/test_cli_overrides.py +167 -0
  130. datamax_dpl-0.1.0/tests/test_cli_validation.py +132 -0
  131. datamax_dpl-0.1.0/tests/test_config_overrides.py +390 -0
  132. datamax_dpl-0.1.0/tests/test_coverage_database.py +51 -0
  133. datamax_dpl-0.1.0/tests/test_declared_dependencies.py +89 -0
  134. datamax_dpl-0.1.0/tests/test_decoder.py +106 -0
  135. datamax_dpl-0.1.0/tests/test_deploy_mode_safety.py +191 -0
  136. datamax_dpl-0.1.0/tests/test_deploy_permissions.py +369 -0
  137. datamax_dpl-0.1.0/tests/test_display.py +186 -0
  138. datamax_dpl-0.1.0/tests/test_enums.py +78 -0
  139. datamax_dpl-0.1.0/tests/test_errors.py +14 -0
  140. datamax_dpl-0.1.0/tests/test_fallbacks.py +207 -0
  141. datamax_dpl-0.1.0/tests/test_image_records.py +157 -0
  142. datamax_dpl-0.1.0/tests/test_logging.py +31 -0
  143. datamax_dpl-0.1.0/tests/test_logging_dotenv_isolation.py +545 -0
  144. datamax_dpl-0.1.0/tests/test_memory_camera.py +89 -0
  145. datamax_dpl-0.1.0/tests/test_memory_logging.py +120 -0
  146. datamax_dpl-0.1.0/tests/test_memory_printer.py +80 -0
  147. datamax_dpl-0.1.0/tests/test_metadata.py +84 -0
  148. datamax_dpl-0.1.0/tests/test_metadata_sync.py +99 -0
  149. datamax_dpl-0.1.0/tests/test_module_entry.py +152 -0
  150. datamax_dpl-0.1.0/tests/test_packaging.py +142 -0
  151. datamax_dpl-0.1.0/tests/test_permission_defaults.py +672 -0
  152. datamax_dpl-0.1.0/tests/test_placeholders.py +56 -0
  153. datamax_dpl-0.1.0/tests/test_platform_markers.py +31 -0
  154. datamax_dpl-0.1.0/tests/test_png.py +164 -0
  155. datamax_dpl-0.1.0/tests/test_ports.py +129 -0
  156. datamax_dpl-0.1.0/tests/test_property_overrides.py +165 -0
  157. datamax_dpl-0.1.0/tests/test_raster.py +539 -0
  158. datamax_dpl-0.1.0/tests/test_render.py +176 -0
  159. datamax_dpl-0.1.0/tests/test_safe_console.py +302 -0
  160. datamax_dpl-0.1.0/tests/test_settings_dotenv_numbers.py +55 -0
  161. datamax_dpl-0.1.0/tests/test_skill_matches_cli.py +48 -0
  162. datamax_dpl-0.1.0/tests/test_status.py +347 -0
  163. datamax_dpl-0.1.0/tests/test_transport_files.py +204 -0
  164. datamax_dpl-0.1.0/tests/test_transport_serial.py +256 -0
  165. datamax_dpl-0.1.0/tests/test_transport_tcp.py +296 -0
  166. datamax_dpl-0.1.0/tests/test_transport_uri.py +238 -0
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "datamax-dpl",
3
+ "owner": {
4
+ "name": "bitranox"
5
+ },
6
+ "metadata": {
7
+ "description": "datamax-dpl as a single Claude Code plugin: a skill to build, check, preview and print Datamax DPL labels."
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "datamax-dpl",
12
+ "source": ".",
13
+ "description": "Use the datamax-dpl CLI and library: label JSON, model profiles and fallbacks, cutter jobs, data-driven batches, preview, print and camera verification."
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "datamax-dpl",
3
+ "description": "Design, check and print Datamax DPL labels from Claude Code: write a label as JSON, validate it against the printer model, preview it as a PNG, print it over tcp or serial, and photograph the result for comparison. Ships the datamax-dpl skill.",
4
+ "version": "0.1.0",
5
+ "author": {
6
+ "name": "bitranox"
7
+ },
8
+ "homepage": "https://github.com/bitranox/datamax-dpl",
9
+ "repository": "https://github.com/bitranox/datamax-dpl",
10
+ "license": "MIT"
11
+ }
@@ -0,0 +1,216 @@
1
+ # ====================================
2
+ # PYCHARM SPEZIFISCH: Git commands you might run once
3
+ # git add .gitignore && git commit -m "Ignore IDE settings"
4
+ # git push
5
+ # git rm -r --cached .idea
6
+ # git commit -m "Remove .idea and add to .gitignore"
7
+ # git push
8
+ # alternative : BE CAREFUL: overwrites remote history
9
+ # git push origin master --force
10
+
11
+ # ====================================
12
+ # APP
13
+ # ====================================
14
+ website/build/
15
+ website/.docusaurus/
16
+ website/node_modules/
17
+ node_modules/
18
+ web-local-preview/
19
+ translation_app*.log
20
+ translation_web*.log
21
+ tmp_github_web_pages/
22
+ tmp_linkcheck_web_pages/
23
+ .eslintcache
24
+ .vitest/
25
+ npm-debug.log*
26
+ yarn-error.log*
27
+ pnpm-debug.log*
28
+ .env.*
29
+ !.env.example
30
+ todo.md
31
+ tmp_*
32
+
33
+ # ====================================
34
+ # IDEs & Editors
35
+ # ====================================
36
+ # IntelliJ, PyCharm, etc.
37
+ .idea/
38
+ # VS Code workspace settings
39
+ .vscode/
40
+ *.code-workspace
41
+
42
+ # ====================================
43
+ # Python bytecode & caches
44
+ # ====================================
45
+ # __pycache__: compiled .pyc files at any depth
46
+ # *.py[cod]: catches .pyc, .pyo, .pyd
47
+ __pycache__/
48
+ src/datamax_dpl/__pycache__/
49
+ *.py[cod]
50
+ # other compiled artifacts
51
+ *$py.class
52
+
53
+ # pytest, coverage, MyPy, Hypothesis
54
+ .pytest_cache/
55
+ .mypy_cache/
56
+ .pyright/
57
+ .coverage*
58
+ htmlcov/
59
+ nosetests.xml
60
+ coverage.xml
61
+ *.cover
62
+ .hypothesis/
63
+ .tox/
64
+ .nox/
65
+
66
+ # general cache directories (any project-level caching)
67
+ .cache/
68
+ .run/
69
+ .import_linter_cache/
70
+
71
+ # ====================================
72
+ # Build & distribution artifacts
73
+ # ====================================
74
+ # source/package builds
75
+ build/
76
+ dist/
77
+ # metadata for pip installs
78
+ *.egg-info/
79
+ *.egg
80
+ *.whl
81
+ pip-wheel-metadata/
82
+ # PyInstaller metadata
83
+ *.manifest
84
+ # PyInstaller spec files
85
+ *.spec
86
+
87
+ # Eggs, parts, wheels, sdist, etc.
88
+ develop-eggs/
89
+ .eggs/
90
+ parts/
91
+ sdist/
92
+ wheels/
93
+ downloads/
94
+ var/
95
+
96
+ # pip logs & installer leftovers
97
+ pip-log.txt
98
+ pip-delete-this-directory.txt
99
+ .installed.cfg
100
+
101
+ # ====================================
102
+ # Virtual environments & secrets
103
+ # ====================================
104
+ # common venv folder names
105
+ env/
106
+ venv/
107
+ ENV/
108
+ .venv/
109
+ # backups, alternate names
110
+ env.bak/
111
+ venv.bak/
112
+ # dotenv files with credentials
113
+ .env
114
+
115
+ # ====================================
116
+ # Project-specific & framework files
117
+ # ====================================
118
+ # Django logs & local overrides
119
+ *.log
120
+ local_settings.py
121
+
122
+ # Flask instance folder
123
+ instance/
124
+ .webassets-cache
125
+
126
+ # Scrapy cache
127
+ .scrapy
128
+
129
+ # Sphinx docs
130
+ docs/_build/
131
+
132
+ # PyBuilder output
133
+ target/
134
+
135
+ # Jupyter notebooks checkpoints
136
+ .ipynb_checkpoints
137
+
138
+ # pyenv Python version file
139
+ .python-version
140
+
141
+ # Celery beat schedule
142
+ celerybeat-schedule
143
+
144
+ # SageMath parsed files
145
+ *.sage.py
146
+
147
+ # Spyder IDE
148
+ .spyderproject
149
+ .spyproject
150
+
151
+ # Rope IDE
152
+ .ropeproject
153
+
154
+ # MkDocs static site folder
155
+ /site
156
+
157
+ # ====================================
158
+ # OS-specific files
159
+ # ====================================
160
+ # macOS
161
+ .DS_Store
162
+ # Windows
163
+ Thumbs.db
164
+ ehthumbs.db
165
+
166
+ # Archives
167
+ *.zip
168
+
169
+ # Thunderbird build artifact (created temporarily by pack script)
170
+ sources/manifest.json
171
+
172
+ # ====================================
173
+ # Tool-specific extras
174
+ # ====================================
175
+ # Codecov uploader script (downloaded during local uploads)
176
+ codecov.sh
177
+ codecov.xml
178
+
179
+ # Nix build result symlink
180
+ result
181
+
182
+ # Optional lockfiles (for alternative managers)
183
+ poetry.lock
184
+ pdm.lock
185
+
186
+ # div
187
+ # .devcontainer/ # needed for github codespaces
188
+ .claude/
189
+ CLAUDE.md
190
+ prompts.md
191
+ .grimp_cache/
192
+
193
+ # Local, per-developer settings (Claude Code etc.) - never commit
194
+ *.local.json
195
+ # bitranox curated memory (local; CLAUDE.local.md @imports it)
196
+ CLAUDE.local.md
197
+
198
+ # Python virtual environments (managed by bmk)
199
+ .venv-win/
200
+ .venv-bmk/
201
+
202
+ # Python virtual environments (managed by bmk)
203
+ .venv*/
204
+
205
+ # Autonomous-execution decision log (never committed)
206
+ EXECUTION-USER-REVIEW.md
207
+
208
+ # Local session notes and memory (never committed)
209
+ .remember/
210
+ handover*.md
211
+ OPEN-WORK*.md
212
+ EXECUTION-USER-REVIEW*.md
213
+ USER-DECISIONS.jsonl
214
+
215
+ # Vendor manual: copyrighted, kept locally as the reference only, never redistributed
216
+ docs/*.pdf
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-10-23
10
+
11
+ First release. Built from the 1998 DPL programmer's manual and tested against
12
+ simulated printers and cameras only; no real printer or camera has been
13
+ attached yet.
14
+
15
+ ### Added
16
+
17
+ - Label format in JSON (millimetres or inches, DPL-native bottom-left origin):
18
+ text in the internal and scalable fonts, lines, boxes, circles, polygons,
19
+ images, and barcodes including Code 128, EAN, UPC, Code 39, PDF417, MaxiCode
20
+ and DataMatrix. `datamax-dpl schema` prints its JSON Schema.
21
+ - 20 profiles for the 18 printer models of the manual, with firmware- and
22
+ option-dependent features; `models` and `capabilities` list them, and
23
+ `docs/capabilities.md` is generated from them.
24
+ - Capability checks per model with a `degrade` policy (documented fallbacks,
25
+ such as a circle sent as a downloaded bitmap, reported as findings) and a
26
+ `strict` policy that refuses instead.
27
+ - Data batches: `{name}` placeholders filled from CSV or JSON records, one label
28
+ per record, with cutting every N labels.
29
+ - Commands `render`, `validate`, `explain` (DPL back to JSON), `preview` (PNG at
30
+ the printer's resolution; lettered text with the `preview` extra on Python
31
+ 3.11+), `print`, `status`, `detect`, `feed`, `cut`, `pause`, `cancel` and
32
+ `reset`.
33
+ - Transports: TCP (port 9100), serial, a device file (USB printer class), a
34
+ file and stdout. A TCP or serial write times out when the printer stops
35
+ taking data for longer than the timeout, on Windows and macOS too; a timed
36
+ out serial write drops what the port had not sent yet.
37
+ - Camera feedback: `capture` takes a photo, `verify` prints a label and puts the
38
+ photo next to the expected preview.
39
+ - `--json` / `--json-bare` envelopes and exit codes 0 / 1 / 2 on every label and
40
+ printer command, for scripts and LLM agents.
41
+ - Public library API for rendering, validating and printing from Python.
42
+ - A Claude Code skill (`skills/datamax-dpl/`), installable from this repository
43
+ as a plugin marketplace.