lvkit 0.3.0__tar.gz → 0.4.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 (262) hide show
  1. {lvkit-0.3.0 → lvkit-0.4.0}/.gitignore +26 -0
  2. lvkit-0.4.0/NOTICE +26 -0
  3. {lvkit-0.3.0 → lvkit-0.4.0}/PKG-INFO +20 -2
  4. {lvkit-0.3.0 → lvkit-0.4.0}/README.md +18 -1
  5. lvkit-0.4.0/deploy/cloudrun/README.md +84 -0
  6. lvkit-0.4.0/docs/xml-schema/README.md +102 -0
  7. {lvkit-0.3.0 → lvkit-0.4.0}/pyproject.toml +10 -1
  8. lvkit-0.4.0/scripts/audit_terminal_order.py +755 -0
  9. lvkit-0.4.0/scripts/generate_docs.py +74 -0
  10. lvkit-0.4.0/scripts/pull_samples.sh +72 -0
  11. lvkit-0.4.0/scripts/recategorize_vilib.py +283 -0
  12. lvkit-0.4.0/scripts/render_gallery.py +248 -0
  13. lvkit-0.4.0/scripts/reproduce_openg_corpus.py +145 -0
  14. lvkit-0.4.0/scripts/wire_decode_probe.py +233 -0
  15. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/__init__.py +1 -1
  16. lvkit-0.4.0/src/lvkit/_pylabview_patches.py +271 -0
  17. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/cli.py +173 -48
  18. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/ast_utils.py +79 -1
  19. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/builder.py +55 -47
  20. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/condition_builder.py +6 -1
  21. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/context.py +24 -0
  22. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/__init__.py +34 -11
  23. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/case.py +63 -9
  24. lvkit-0.4.0/src/lvkit/codegen/nodes/compound.py +723 -0
  25. lvkit-0.4.0/src/lvkit/codegen/nodes/first_call.py +63 -0
  26. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/loop.py +208 -31
  27. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/primitive.py +81 -8
  28. lvkit-0.4.0/src/lvkit/codegen/nodes/queue_ops.py +212 -0
  29. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/primitives.json +638 -278
  30. lvkit-0.4.0/src/lvkit/data/vilib/_index.json +32 -0
  31. lvkit-0.4.0/src/lvkit/data/vilib/addons.json +26 -0
  32. lvkit-0.4.0/src/lvkit/data/vilib/application-control.json +2128 -0
  33. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/vilib/array.json +1018 -804
  34. lvkit-0.4.0/src/lvkit/data/vilib/boolean.json +492 -0
  35. lvkit-0.3.0/src/lvkit/data/vilib/cluster.json → lvkit-0.4.0/src/lvkit/data/vilib/cluster-class-variant.json +586 -291
  36. lvkit-0.4.0/src/lvkit/data/vilib/collection.json +1045 -0
  37. lvkit-0.4.0/src/lvkit/data/vilib/comparison.json +1642 -0
  38. lvkit-0.4.0/src/lvkit/data/vilib/connectivity.json +5924 -0
  39. lvkit-0.4.0/src/lvkit/data/vilib/control-simulation.json +5255 -0
  40. lvkit-0.4.0/src/lvkit/data/vilib/data-communication.json +9547 -0
  41. lvkit-0.4.0/src/lvkit/data/vilib/dialog-user-interface.json +2899 -0
  42. lvkit-0.4.0/src/lvkit/data/vilib/express.json +5086 -0
  43. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/vilib/file-io.json +4225 -1670
  44. lvkit-0.4.0/src/lvkit/data/vilib/graphics-sound.json +8038 -0
  45. lvkit-0.4.0/src/lvkit/data/vilib/instrument-io.json +3768 -0
  46. lvkit-0.4.0/src/lvkit/data/vilib/mathematics.json +32367 -0
  47. lvkit-0.4.0/src/lvkit/data/vilib/measurement-io.json +1046 -0
  48. lvkit-0.4.0/src/lvkit/data/vilib/numeric.json +3211 -0
  49. lvkit-0.4.0/src/lvkit/data/vilib/report-generation.json +5661 -0
  50. lvkit-0.4.0/src/lvkit/data/vilib/signal-processing.json +30948 -0
  51. lvkit-0.4.0/src/lvkit/data/vilib/string.json +3345 -0
  52. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/vilib/structures.json +574 -319
  53. lvkit-0.4.0/src/lvkit/data/vilib/synchronization.json +2475 -0
  54. lvkit-0.4.0/src/lvkit/data/vilib/timing.json +857 -0
  55. lvkit-0.4.0/src/lvkit/data/vilib/waveform.json +8366 -0
  56. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/docs/generate.py +62 -4
  57. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/docs/html_generator.py +323 -253
  58. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/docs/template.css +67 -0
  59. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/extractor.py +61 -11
  60. lvkit-0.4.0/src/lvkit/graph/builders/__init__.py +26 -0
  61. lvkit-0.4.0/src/lvkit/graph/builders/context.py +55 -0
  62. lvkit-0.4.0/src/lvkit/graph/builders/operations.py +152 -0
  63. lvkit-0.4.0/src/lvkit/graph/builders/refs.py +183 -0
  64. lvkit-0.4.0/src/lvkit/graph/builders/structures.py +213 -0
  65. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/construction.py +175 -316
  66. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/core.py +11 -0
  67. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/loading.py +48 -16
  68. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/models.py +107 -1
  69. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/operations.py +3 -0
  70. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/queries.py +225 -8
  71. lvkit-0.4.0/src/lvkit/labview_queue.py +166 -0
  72. lvkit-0.4.0/src/lvkit/lv_detect.py +248 -0
  73. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/mcp/server.py +45 -5
  74. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/mcp/tools.py +33 -8
  75. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/models.py +43 -0
  76. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/constants.py +12 -0
  77. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/flags.py +10 -0
  78. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/front_panel.py +53 -26
  79. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/models.py +60 -0
  80. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/node_types.py +176 -20
  81. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/nodes/__init__.py +2 -1
  82. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/nodes/base.py +32 -15
  83. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/nodes/case.py +237 -17
  84. lvkit-0.4.0/src/lvkit/parser/nodes/constant.py +130 -0
  85. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/nodes/decompose.py +1 -3
  86. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/nodes/loop.py +43 -4
  87. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/nodes/sequence.py +1 -3
  88. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/type_mapping.py +8 -3
  89. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/utils.py +49 -0
  90. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/vi.py +110 -32
  91. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/primitive_resolver.py +58 -27
  92. lvkit-0.4.0/src/lvkit/render/__init__.py +342 -0
  93. lvkit-0.4.0/src/lvkit/render/backend.py +302 -0
  94. lvkit-0.4.0/src/lvkit/render/draw.py +1709 -0
  95. lvkit-0.4.0/src/lvkit/render/glyph.py +1288 -0
  96. lvkit-0.4.0/src/lvkit/render/icons.py +165 -0
  97. lvkit-0.4.0/src/lvkit/render/lane_pass.py +525 -0
  98. lvkit-0.4.0/src/lvkit/render/layout.py +621 -0
  99. lvkit-0.4.0/src/lvkit/render/nodes.py +901 -0
  100. lvkit-0.4.0/src/lvkit/render/scene.py +1538 -0
  101. lvkit-0.4.0/src/lvkit/render/style.py +325 -0
  102. lvkit-0.4.0/src/lvkit/render/theme_web.py +155 -0
  103. lvkit-0.4.0/src/lvkit/render/wire_router.py +401 -0
  104. lvkit-0.4.0/src/lvkit/render/wire_table.py +663 -0
  105. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/skill_templates/lvkit-describe/SKILL.md +2 -2
  106. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/skill_templates/lvkit-resolve-primitive/SKILL.md +61 -70
  107. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/structure.py +53 -14
  108. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/vilib_resolver.py +9 -1
  109. lvkit-0.4.0/tests/test_array_ops_codegen.py +537 -0
  110. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_ast_builder.py +1 -1
  111. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_case_codegen.py +101 -0
  112. lvkit-0.4.0/tests/test_case_parser.py +438 -0
  113. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_compound_codegen.py +322 -1
  114. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_dependency_path_refs.py +4 -4
  115. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_determinism.py +19 -5
  116. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_diff.py +43 -29
  117. lvkit-0.4.0/tests/test_docs_class_hierarchy.py +388 -0
  118. lvkit-0.4.0/tests/test_docs_render.py +126 -0
  119. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_driver_codegen.py +66 -55
  120. lvkit-0.4.0/tests/test_e2e_codegen.py +508 -0
  121. lvkit-0.4.0/tests/test_first_call_codegen.py +111 -0
  122. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_frame_attribution.py +1 -1
  123. lvkit-0.4.0/tests/test_glyphs.py +487 -0
  124. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_graceful_degradation.py +2 -30
  125. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_loop_codegen.py +465 -2
  126. lvkit-0.4.0/tests/test_lv_detect.py +298 -0
  127. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_parallel_codegen.py +13 -41
  128. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_parser.py +195 -2
  129. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_parser_regression.py +98 -0
  130. lvkit-0.4.0/tests/test_primitive_resolutions.py +194 -0
  131. lvkit-0.4.0/tests/test_queue_codegen.py +414 -0
  132. lvkit-0.4.0/tests/test_render.py +2832 -0
  133. lvkit-0.4.0/tests/test_unknown_nodes.py +85 -0
  134. lvkit-0.4.0/tests/test_vilib_docurls.py +158 -0
  135. lvkit-0.3.0/scripts/generate_docs.py +0 -526
  136. lvkit-0.3.0/src/lvkit/codegen/nodes/compound.py +0 -181
  137. lvkit-0.3.0/src/lvkit/data/primitives-from-pdf.json +0 -8452
  138. lvkit-0.3.0/src/lvkit/data/vilib/_index.json +0 -19
  139. lvkit-0.3.0/src/lvkit/data/vilib/application-control.json +0 -5408
  140. lvkit-0.3.0/src/lvkit/data/vilib/boolean.json +0 -704
  141. lvkit-0.3.0/src/lvkit/data/vilib/comparison.json +0 -2388
  142. lvkit-0.3.0/src/lvkit/data/vilib/error-handling.json +0 -2274
  143. lvkit-0.3.0/src/lvkit/data/vilib/numeric.json +0 -1538
  144. lvkit-0.3.0/src/lvkit/data/vilib/other.json +0 -87782
  145. lvkit-0.3.0/src/lvkit/data/vilib/string.json +0 -3582
  146. lvkit-0.3.0/src/lvkit/data/vilib/variant.json +0 -1343
  147. lvkit-0.3.0/src/lvkit/graph/flowchart.py +0 -281
  148. lvkit-0.3.0/src/lvkit/parser/nodes/constant.py +0 -55
  149. lvkit-0.3.0/tests/test_case_parser.py +0 -216
  150. lvkit-0.3.0/tests/test_e2e_codegen.py +0 -349
  151. lvkit-0.3.0/tests/test_primitive_resolutions.py +0 -86
  152. {lvkit-0.3.0 → lvkit-0.4.0}/.pre-commit-config.yaml +0 -0
  153. {lvkit-0.3.0 → lvkit-0.4.0}/LICENSE +0 -0
  154. {lvkit-0.3.0 → lvkit-0.4.0}/scripts/audit_unresolved.py +0 -0
  155. {lvkit-0.3.0 → lvkit-0.4.0}/scripts/dump_primitive_context.py +0 -0
  156. {lvkit-0.3.0 → lvkit-0.4.0}/scripts/gen_semantics_probe.py +0 -0
  157. {lvkit-0.3.0 → lvkit-0.4.0}/scripts/generate_driver_data.py +0 -0
  158. {lvkit-0.3.0 → lvkit-0.4.0}/scripts/generate_python.py +0 -0
  159. {lvkit-0.3.0 → lvkit-0.4.0}/scripts/populate_vilib.py +0 -0
  160. {lvkit-0.3.0 → lvkit-0.4.0}/scripts/sync_skills.sh +0 -0
  161. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/_data.py +0 -0
  162. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/README.md +0 -0
  163. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/__init__.py +0 -0
  164. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/ast_optimizer.py +0 -0
  165. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/class_builder.py +0 -0
  166. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/dataflow.py +0 -0
  167. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/elementwise.py +0 -0
  168. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/error_handler.py +0 -0
  169. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/expressions.py +0 -0
  170. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/fragment.py +0 -0
  171. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/function.py +0 -0
  172. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/imports.py +0 -0
  173. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/base.py +0 -0
  174. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/constant.py +0 -0
  175. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/formula.py +0 -0
  176. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/in_place.py +0 -0
  177. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/invoke_node.py +0 -0
  178. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/nmux.py +0 -0
  179. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/printf.py +0 -0
  180. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/property_node.py +0 -0
  181. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/sequence.py +0 -0
  182. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/nodes/subvi.py +0 -0
  183. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/stubs.py +0 -0
  184. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/codegen/unresolved.py +0 -0
  185. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/_index.json +0 -0
  186. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/daqmx.json +0 -0
  187. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/nidcpower.json +0 -0
  188. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/nidigital.json +0 -0
  189. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/nidmm.json +0 -0
  190. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/nifgen.json +0 -0
  191. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/niscope.json +0 -0
  192. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/niswitch.json +0 -0
  193. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/serial.json +0 -0
  194. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/drivers/visa.json +0 -0
  195. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/labview_error_codes.json +0 -0
  196. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/openg/_index.json +0 -0
  197. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/openg/array.json +0 -0
  198. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/openg/file.json +0 -0
  199. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/openg/string.json +0 -0
  200. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/openg/time.json +0 -0
  201. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/openg/variant.json +0 -0
  202. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/vilib/_pending_terminals.json +0 -0
  203. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/data/vilib/_types.json +0 -0
  204. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/docs/__init__.py +0 -0
  205. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/docs/utils.py +0 -0
  206. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/formula/__init__.py +0 -0
  207. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/formula/cparser.py +0 -0
  208. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/formula/emit.py +0 -0
  209. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/formula/lexer.py +0 -0
  210. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/formula/nodes.py +0 -0
  211. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/__init__.py +0 -0
  212. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/analysis.py +0 -0
  213. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/describe.py +0 -0
  214. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/graph/diff.py +0 -0
  215. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/labview_error.py +0 -0
  216. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/labview_error_codes.py +0 -0
  217. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/mcp/__init__.py +0 -0
  218. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/mcp/schemas.py +0 -0
  219. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/__init__.py +0 -0
  220. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/defaults.py +0 -0
  221. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/metadata.py +0 -0
  222. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/naming.py +0 -0
  223. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/parser/type_resolution.py +0 -0
  224. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/pipeline.py +0 -0
  225. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/project_store.py +0 -0
  226. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/py.typed +0 -0
  227. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/runtime/__init__.py +0 -0
  228. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/runtime/lv.py +0 -0
  229. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/skill_templates/__init__.py +0 -0
  230. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/skill_templates/lvkit-convert/SKILL.md +0 -0
  231. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/skill_templates/lvkit-idiomatic/SKILL.md +0 -0
  232. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/skill_templates/lvkit-resolve-vilib/SKILL.md +0 -0
  233. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/terminal_collector.py +0 -0
  234. {lvkit-0.3.0 → lvkit-0.4.0}/src/lvkit/type_defaults.py +0 -0
  235. {lvkit-0.3.0 → lvkit-0.4.0}/tests/__init__.py +0 -0
  236. {lvkit-0.3.0 → lvkit-0.4.0}/tests/conftest.py +0 -0
  237. {lvkit-0.3.0 → lvkit-0.4.0}/tests/helpers.py +0 -0
  238. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_ast_optimizer.py +0 -0
  239. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_codegen_context.py +0 -0
  240. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_condition_builder.py +0 -0
  241. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_constant_decoding.py +0 -0
  242. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_diff_wiring_denoise.py +0 -0
  243. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_dynamic_dispatch.py +0 -0
  244. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_elementwise.py +0 -0
  245. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_error_codegen.py +0 -0
  246. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_error_handling.py +0 -0
  247. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_formula_codegen.py +0 -0
  248. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_formula_runtime.py +0 -0
  249. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_formula_semantics.py +0 -0
  250. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_formula_transpile.py +0 -0
  251. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_in_place_codegen.py +0 -0
  252. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_lvpy.py +0 -0
  253. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_naming.py +0 -0
  254. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_new_codegen.py +0 -0
  255. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_project_store.py +0 -0
  256. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_sequence.py +0 -0
  257. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_soft_codegen.py +0 -0
  258. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_type_driven_fixes.py +0 -0
  259. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_type_fields.py +0 -0
  260. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_type_loading.py +0 -0
  261. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_type_mapping.py +0 -0
  262. {lvkit-0.3.0 → lvkit-0.4.0}/tests/test_vi_graph.py +0 -0
@@ -79,6 +79,7 @@ dmypy.json
79
79
 
80
80
  # Sample LabVIEW projects (external test data)
81
81
  samples/
82
+ samples.bak/
82
83
 
83
84
  # Model files
84
85
  models/
@@ -101,3 +102,28 @@ outputs/
101
102
  docs/*.pdf
102
103
  docs/labview_ref_manual.txt
103
104
  docs/labview_programming_reference_manual*
105
+
106
+ # NI-derived extracted primitive-icon PNGs (pulled from the reference PDF by
107
+ # scripts/extract_lv_icons.py) — local-only build intermediates. Only the
108
+ # vectorized .svg equivalents (scripts/vectorize_icons.py) are tracked/shipped.
109
+ src/lvkit/data/glyphs/*.png
110
+
111
+ # lv-renderer experiment scratch. Keep only the canonical gallery examples;
112
+ # ignore the throwaway per-iteration review renders and icon-extraction probes.
113
+ experiments/lv-renderer/gallery/*
114
+ !experiments/lv-renderer/gallery/Build.svg
115
+ !experiments/lv-renderer/gallery/Out.svg
116
+ !experiments/lv-renderer/gallery/XML_Loop_Stack_Recursion.svg
117
+ experiments/lv-renderer/icon_extract/
118
+ experiments/lv-renderer/icon_probe/
119
+ experiments/lv-renderer/icon_probe_reverse1d.png
120
+
121
+ # NI-derived vectorized icon SVGs (from the reference PDF) — local-only,
122
+ # regenerated by scripts/vectorize_icons.py; cleanroom package ships none.
123
+ src/lvkit/data/glyphs/*.svg
124
+
125
+ # Local-only experiment/scratch VIs (unprovable provenance — never redistribute)
126
+ experiments/
127
+
128
+ # Claude Code agent worktrees (transient)
129
+ .claude/worktrees/
lvkit-0.4.0/NOTICE ADDED
@@ -0,0 +1,26 @@
1
+ lvkit
2
+ Copyright 2025-2026 Ryan Friedman
3
+
4
+ This product is an independent, clean-room project. It is not affiliated with,
5
+ authorized by, endorsed by, or sponsored by National Instruments Corporation.
6
+
7
+ LabVIEW, NI, and National Instruments are trademarks of National Instruments
8
+ Corporation, used herein only to identify the file format and software with
9
+ which lvkit interoperates (nominative use).
10
+
11
+ lvkit was developed using only publicly available information: public NI
12
+ documentation, the open-source pylabview project, and observation of VI files.
13
+ It was built without installing or running LabVIEW or any NI software, and
14
+ without the use of any NI source code, internal or non-public specifications,
15
+ or confidential or proprietary materials.
16
+
17
+ lvkit's mappings of LabVIEW primitives and standard-library VIs (in
18
+ src/lvkit/data/) are lvkit's own definitions, derived purely by inference from
19
+ public documentation and from the VI XML produced by pylabview. They are
20
+ best-effort inferences, not authoritative reproductions of any NI
21
+ specification, and they contain no NI documentation text or artwork.
22
+
23
+ lvkit depends on, but does not include, pylabview
24
+ (https://github.com/mefistotelis/pylabview).
25
+
26
+ See PROVENANCE.md for detail.
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lvkit
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Understand and convert LabVIEW VIs to Python without a LabVIEW license
5
5
  Project-URL: Repository, https://github.com/pragmatest-dev/lvkit
6
6
  Project-URL: Issues, https://github.com/pragmatest-dev/lvkit/issues
7
7
  Author: Pragmatest
8
8
  License-Expression: Apache-2.0
9
9
  License-File: LICENSE
10
+ License-File: NOTICE
10
11
  Keywords: ast,code-generation,labview,mcp,ni,static-analysis,vi
11
12
  Classifier: Development Status :: 3 - Alpha
12
13
  Classifier: Intended Audience :: Developers
@@ -38,6 +39,8 @@ Read, document, diff, and convert LabVIEW VI files — no LabVIEW license requir
38
39
 
39
40
  lvkit parses `.vi`, `.ctl`, `.lvclass`, and `.lvlib` files directly into queryable dependency and dataflow graphs. Use it to document code, track changes in CI, feed VI structure to AI tools, or generate equivalent Python.
40
41
 
42
+ > **Independent, clean-room project — not affiliated with NI.** lvkit was built using **only publicly available information**: public NI documentation, the open-source [pylabview](https://github.com/mefistotelis/pylabview) project, and observation of VI files. It was developed **without installing or running LabVIEW or any NI software**, and with **no NI source code, internal or non-public specifications, or confidential or proprietary materials**. LabVIEW, NI, and National Instruments are trademarks of National Instruments Corporation, used here only to identify the format lvkit interoperates with; lvkit is not affiliated with, authorized by, endorsed by, or sponsored by NI. See [Cleanroom approach](#cleanroom-approach), [`NOTICE`](NOTICE), and [`PROVENANCE.md`](PROVENANCE.md).
43
+
41
44
  ## Contents
42
45
 
43
46
  - [Quick Start](#quick-start)
@@ -167,7 +170,22 @@ Five workflows ship: `lvkit-describe`, `lvkit-convert`, `lvkit-resolve-primitive
167
170
 
168
171
  ## Cleanroom approach
169
172
 
170
- lvkit has no access to LabVIEW source code or runtime. LabVIEW's built-in primitives and standard library VIs are **semantically replaced**: each operation is mapped to an equivalent Python implementation in JSON data files (`src/lvkit/data/primitives.json`, `src/lvkit/data/vilib/`). These mappings are built from published documentation and observed behavior.
173
+ lvkit has no access to LabVIEW source code or runtime. LabVIEW's built-in primitives and standard library VIs are **semantically replaced**: each operation is mapped to an equivalent Python implementation in open, inspectable JSON data files (`src/lvkit/data/primitives.json`, `src/lvkit/data/vilib/`).
174
+
175
+ These mappings are **lvkit's own definitions, derived purely by inference** from two public inputs and nothing else:
176
+
177
+ 1. **Public NI documentation** — pages published openly on ni.com, accessed with no login, partner portal, or NDA gate.
178
+ 2. **The VI XML produced by [pylabview](https://github.com/mefistotelis/pylabview)** — the open-source parser that extracts the VI binary to XML. That XML is lvkit's *only* window into the format; lvkit has no other view of it.
179
+
180
+ The definitions are open source and fully inspectable, and many carry a note recording how each was inferred (the public doc consulted, the observed terminal signature, a `verified`/`guess_reason` marker). They are **best-effort inferences, not authoritative** — they have been wrong and corrected over time. That imperfection is a direct consequence of working from *only* public documentation and the pylabview XML, with **no access to any internal or authoritative NI specification** — an insider would not need to infer.
181
+
182
+ ### Provenance
183
+
184
+ lvkit was developed **using only publicly available information** and clean-room methods. It was built **without installing or running LabVIEW or any NI software**, and with **no NI source code, internal or non-public specifications, or confidential or proprietary materials**. Facts about LabVIEW's behavior are used as facts; no NI documentation prose or artwork is copied or redistributed — primitive glyphs are drawn procedurally, and the shipped data contains no NI text or images. See [`PROVENANCE.md`](PROVENANCE.md).
185
+
186
+ ### Trademarks
187
+
188
+ LabVIEW, NI, and National Instruments are trademarks of National Instruments Corporation. lvkit is an independent project and is not affiliated with, authorized by, endorsed by, or sponsored by NI. Those names are used only to identify the file format and software lvkit interoperates with (nominative use).
171
189
 
172
190
  Coverage is incremental. When `lvkit generate` encounters an unmapped primitive or vi.lib VI, it raises an error with diagnostic context so the mapping can be added. `describe`, `docs`, `diff`, and `visualize` are unaffected — they work from the graph, not the semantic mappings.
173
191
 
@@ -4,6 +4,8 @@ Read, document, diff, and convert LabVIEW VI files — no LabVIEW license requir
4
4
 
5
5
  lvkit parses `.vi`, `.ctl`, `.lvclass`, and `.lvlib` files directly into queryable dependency and dataflow graphs. Use it to document code, track changes in CI, feed VI structure to AI tools, or generate equivalent Python.
6
6
 
7
+ > **Independent, clean-room project — not affiliated with NI.** lvkit was built using **only publicly available information**: public NI documentation, the open-source [pylabview](https://github.com/mefistotelis/pylabview) project, and observation of VI files. It was developed **without installing or running LabVIEW or any NI software**, and with **no NI source code, internal or non-public specifications, or confidential or proprietary materials**. LabVIEW, NI, and National Instruments are trademarks of National Instruments Corporation, used here only to identify the format lvkit interoperates with; lvkit is not affiliated with, authorized by, endorsed by, or sponsored by NI. See [Cleanroom approach](#cleanroom-approach), [`NOTICE`](NOTICE), and [`PROVENANCE.md`](PROVENANCE.md).
8
+
7
9
  ## Contents
8
10
 
9
11
  - [Quick Start](#quick-start)
@@ -133,7 +135,22 @@ Five workflows ship: `lvkit-describe`, `lvkit-convert`, `lvkit-resolve-primitive
133
135
 
134
136
  ## Cleanroom approach
135
137
 
136
- lvkit has no access to LabVIEW source code or runtime. LabVIEW's built-in primitives and standard library VIs are **semantically replaced**: each operation is mapped to an equivalent Python implementation in JSON data files (`src/lvkit/data/primitives.json`, `src/lvkit/data/vilib/`). These mappings are built from published documentation and observed behavior.
138
+ lvkit has no access to LabVIEW source code or runtime. LabVIEW's built-in primitives and standard library VIs are **semantically replaced**: each operation is mapped to an equivalent Python implementation in open, inspectable JSON data files (`src/lvkit/data/primitives.json`, `src/lvkit/data/vilib/`).
139
+
140
+ These mappings are **lvkit's own definitions, derived purely by inference** from two public inputs and nothing else:
141
+
142
+ 1. **Public NI documentation** — pages published openly on ni.com, accessed with no login, partner portal, or NDA gate.
143
+ 2. **The VI XML produced by [pylabview](https://github.com/mefistotelis/pylabview)** — the open-source parser that extracts the VI binary to XML. That XML is lvkit's *only* window into the format; lvkit has no other view of it.
144
+
145
+ The definitions are open source and fully inspectable, and many carry a note recording how each was inferred (the public doc consulted, the observed terminal signature, a `verified`/`guess_reason` marker). They are **best-effort inferences, not authoritative** — they have been wrong and corrected over time. That imperfection is a direct consequence of working from *only* public documentation and the pylabview XML, with **no access to any internal or authoritative NI specification** — an insider would not need to infer.
146
+
147
+ ### Provenance
148
+
149
+ lvkit was developed **using only publicly available information** and clean-room methods. It was built **without installing or running LabVIEW or any NI software**, and with **no NI source code, internal or non-public specifications, or confidential or proprietary materials**. Facts about LabVIEW's behavior are used as facts; no NI documentation prose or artwork is copied or redistributed — primitive glyphs are drawn procedurally, and the shipped data contains no NI text or images. See [`PROVENANCE.md`](PROVENANCE.md).
150
+
151
+ ### Trademarks
152
+
153
+ LabVIEW, NI, and National Instruments are trademarks of National Instruments Corporation. lvkit is an independent project and is not affiliated with, authorized by, endorsed by, or sponsored by NI. Those names are used only to identify the file format and software lvkit interoperates with (nominative use).
137
154
 
138
155
  Coverage is incremental. When `lvkit generate` encounters an unmapped primitive or vi.lib VI, it raises an error with diagnostic context so the mapping can be added. `describe`, `docs`, `diff`, and `visualize` are unaffected — they work from the graph, not the semantic mappings.
139
156
 
@@ -0,0 +1,84 @@
1
+ # lvkit on Cloud Run — VI → SVG service
2
+
3
+ A tiny HTTP service: `POST` a `.vi` file, get an SVG block-diagram render back.
4
+ A page can upload a VI and drop the returned SVG straight into the DOM.
5
+
6
+ ## Why this works cleanly
7
+
8
+ lvkit needs **no LabVIEW and no native binary**. Extraction shells out to
9
+ `python -m pylabview.readRSRC` (pure Python, an lvkit dependency), and
10
+ `render_vi_file()` returns an SVG string. The container just needs Python +
11
+ lvkit + a writable temp dir — Cloud Run provides `/tmp` (in-memory).
12
+
13
+ Uploads are rendered with `expand_subvis=False`, which is effectively an
14
+ **offline mode**: a standalone VI has no sibling subVI files, so the render
15
+ never reaches the filesystem for dependencies (unresolved subVIs draw as
16
+ fallback boxes). It only reads lvkit's own **bundled** primitive/vilib JSON,
17
+ which ships inside the image. Nothing to configure.
18
+
19
+ ## Files
20
+
21
+ | file | purpose |
22
+ |------|---------|
23
+ | `main.py` | Flask app: `GET /` demo page, `GET /health`, `POST /render` |
24
+ | `Dockerfile` | installs lvkit (this branch) + flask/gunicorn; **build context = repo root** |
25
+ | `cloudbuild.yaml` | build → push → deploy in one `gcloud builds submit` |
26
+ | `static/index.html` | drop-a-VI demo page served at `/` |
27
+ | `requirements.txt` | web deps for local dev |
28
+
29
+ ## Deploy
30
+
31
+ From the **repo root** (not this folder — the Docker build needs the lvkit
32
+ source in context):
33
+
34
+ ```bash
35
+ gcloud builds submit --config deploy/cloudrun/cloudbuild.yaml \
36
+ --substitutions=_IMAGE=gcr.io/$(gcloud config get-value project)/lvkit-render,_REGION=us-central1 .
37
+ ```
38
+
39
+ That builds `deploy/cloudrun/Dockerfile`, pushes the image, and deploys the
40
+ `lvkit-render` service (`--allow-unauthenticated`, 1Gi, 1 CPU, 120s, max 5
41
+ instances — tune in `cloudbuild.yaml`).
42
+
43
+ ### Local test
44
+
45
+ ```bash
46
+ pip install -e . # from repo root (installs lvkit + pylabview)
47
+ pip install -r deploy/cloudrun/requirements.txt
48
+ cd deploy/cloudrun && python main.py # http://localhost:8080
49
+ # or exactly like prod:
50
+ docker build -f deploy/cloudrun/Dockerfile -t lvkit-render . # from repo root
51
+ docker run -p 8080:8080 -e PORT=8080 lvkit-render
52
+ ```
53
+
54
+ ## Calling it from a page
55
+
56
+ ```js
57
+ const fd = new FormData();
58
+ fd.append('vi', fileInput.files[0]);
59
+ const svg = await (await fetch('https://YOUR-URL/render', { method:'POST', body: fd })).text();
60
+ document.getElementById('out').innerHTML = svg; // static picture
61
+ ```
62
+
63
+ ### Heads-up: interactive frames
64
+
65
+ The SVG embeds an inline `<script>` for the case/stacked-sequence **frame
66
+ selector**. Browsers do **not** run scripts inserted via `innerHTML`, so a VI
67
+ rendered that way is a static image. To keep the frame toggles working, load the
68
+ SVG so its script executes — e.g. an `<iframe>`:
69
+
70
+ ```js
71
+ const url = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'}));
72
+ iframe.src = url; // scripts inside the SVG run here
73
+ ```
74
+
75
+ ## Notes / hardening
76
+
77
+ - **Untrusted input**: you're parsing arbitrary uploaded binaries. Cloud Run's
78
+ per-request container is the isolation boundary; `main.py` caps size at 25 MB
79
+ (Cloud Run's own request limit is 32 MB).
80
+ - **Memory**: `/tmp` is RAM on Cloud Run and holds the upload + extracted XML;
81
+ 1Gi is a safe start. Raise `--memory`/lower concurrency for large VIs.
82
+ - **Auth**: `--allow-unauthenticated` is for a public demo. Drop it (and add an
83
+ API key / IAM) for anything real.
84
+ - **Cold start**: first request imports lvkit + pylabview (~1s); fine for a demo.
@@ -0,0 +1,102 @@
1
+ # LabVIEW VI XML Schema Reference
2
+
3
+ This directory documents lvkit's current understanding of the XML that
4
+ [pylabview](https://github.com/mefistotelis/pylabview) extracts from a LabVIEW
5
+ `.vi` binary. It is a "genome project" for these archaic, binary-derived fields:
6
+ for each field, *what it is* and *what we currently believe it controls*, with
7
+ the evidence and a confidence level.
8
+
9
+ > **Grounding rule.** Every claim here is traced to lvkit parser code, a
10
+ > pylabview enum/comment, a concrete extracted XML sample, or a confirmed
11
+ > session finding. Where we genuinely do not know a field's meaning, it is
12
+ > marked **confidence = unknown** rather than guessed. (This repo has a hard
13
+ > "never fabricate looked-up facts" rule.)
14
+
15
+ ## The three files
16
+
17
+ `extractor.extract_vi_xml(vi_path)` runs one pylabview subprocess per VI and
18
+ writes three sibling XML files next to the `.vi` (plus a pile of `*.bin`
19
+ side-blobs and `*.png` icons):
20
+
21
+ | File | Nickname | Contents | Doc |
22
+ |---|---|---|---|
23
+ | `<name>_BDHb.xml` | **BD** — block-diagram heap | nodes, wires, structures, terminals, constants | [block-diagram.md](block-diagram.md) |
24
+ | `<name>_FPHb.xml` | **FP** — front-panel heap | controls/indicators, connector pane, default data | [front-panel.md](front-panel.md) |
25
+ | `<name>.xml` | **Base / main** | VI settings (LVSR/LVIN), type list (VCTP), dataspace default data (DFDS), link/dependency tables | [dataspace.md](dataspace.md) |
26
+
27
+ Both `_BDHb.xml` and `_FPHb.xml` are **heaps**: recursively nested
28
+ `<SL__arrayElement class="...">` objects, each carrying a `uid`, that model the
29
+ on-screen object tree. The base `.xml` is different in shape — it is a set of
30
+ named binary *sections* (LVSR, VCTP, DFDS, LIvi, LIbd, ...) that pylabview
31
+ renders as structured XML plus `<!-- ... -->` comments.
32
+
33
+ Suffix constants live in `src/lvkit/parser/constants.py:165-167`
34
+ (`BD_XML_SUFFIX`, `FP_XML_SUFFIX`, `MAIN_XML_SUFFIX`), with
35
+ `derive_fp_xml_path` / `derive_main_xml_path` / `derive_vi_name` helpers
36
+ (`constants.py:191-204`).
37
+
38
+ ## How the parser reads them
39
+
40
+ Pipeline (`src/lvkit/parser/vi.py:101` `parse_vi`):
41
+
42
+ 1. `_parse_metadata(main_xml)` — LVSR/LVIN qualified name, the **type map**
43
+ (`parse_type_map_rich`), and SubVI/dependency link tables. (`vi.py:170`)
44
+ 2. `_parse_selector_tables(main_xml)` — case-structure per-frame selector
45
+ values from the DFDS dataspace. (`vi.py:223`)
46
+ 3. `_parse_block_diagram(bd_xml, fp_xml, type_map, selector_tables)` — nodes,
47
+ wires, constants, terminals, loops, cases, sequences, IPES. (`vi.py:235`)
48
+ 4. `_parse_front_panel(fp_xml, ...)` and `parse_connector_pane(fp_xml)`.
49
+
50
+ ## Two SEPARATE type namespaces (they do NOT cross-reference)
51
+
52
+ This is the single most important thing to internalize:
53
+
54
+ - **BD heap `typeDesc` `TypeID(N)`** — an index into the **VCTP** (the
55
+ consolidated type list in the base `.xml`). Terminals, constants, tunnels and
56
+ FP DCOs all carry `<typeDesc>TypeID(N)</typeDesc>`; `N` is a *heap* TypeID,
57
+ resolved through the chain
58
+ `Heap TypeID → Consolidated TypeID → FlatTypeID → VCTP TypeDesc`
59
+ (`parser/type_mapping.py:17` `parse_type_map_rich`,
60
+ `parser/type_resolution.py:53` `resolve_type_rich`).
61
+ - **Dataspace `DataFill TypeID="N"`** — an index into the **DFDS** (dataspace)
62
+ default-data list. Same integer space *shape*, totally different assignment.
63
+
64
+ **A `DataFill TypeID` and a BD `typeDesc TypeID` with the same number are NOT
65
+ the same type.** They are two independent enumerations. The case-selector
66
+ correlation (see [dataspace.md](dataspace.md)) exploits the fact that, *within
67
+ each namespace*, LabVIEW assigns indices in the same DCO-enumeration order — so
68
+ you sort each side by its own index and zip. You never equate the two integers
69
+ directly. (`parser/nodes/case.py:513` `_apply_selector_tables`; session
70
+ finding, confirmed on "Draw Image from File__ogtk.vi".)
71
+
72
+ ## Coordinate spaces
73
+
74
+ - All heap rects are LabVIEW `(top, left, bottom, right)` — note the order
75
+ (`render/layout.py:109` `_rect` reorders them to `x1,y1,x2,y2`).
76
+ - A node's `<bounds>` is absolute (relative to the diagram it lives in; the
77
+ renderer accumulates diagram origins while recursing —
78
+ `render/layout.py:383` `walk`).
79
+ - A terminal's `<termBounds>` is **relative to the node's icon origin**, and a
80
+ primitive's icon is *centered* within its clickable `<bounds>` — so the
81
+ renderer computes a centering offset before placing terminals
82
+ (`render/layout.py:252-280` `_map_terms`). Constant part bounds are relative
83
+ to the constant DDO's own top-left (`render/layout.py:118` `_const_value_box`).
84
+ - Selector/label geometry lives in the heap; **selector VALUES do not** — they
85
+ are in the DFDS dataspace (see below).
86
+
87
+ ## A note on pylabview `OF__*` enums
88
+
89
+ pylabview's `LVheap.py` defines `OBJ_FIELD_TAGS` with members like
90
+ `OF__objFlags = 172`, `OF__bounds = 14`, `OF__termBounds = 266`
91
+ (`LVheap.py:75-360`). **These integers are attribute-tag IDs** — they identify
92
+ *which serialized attribute* a value belongs to inside the binary heap, and
93
+ they become the XML element *name* (`<objFlags>`, `<bounds>`, ...). They are
94
+ **NOT** bit positions within the `objFlags` integer. Do not conflate the two.
95
+ The bit meanings of `objFlags` are documented per-element in the field docs and
96
+ are lvkit session findings — pylabview does not decode them.
97
+
98
+ ## Field docs
99
+
100
+ - [block-diagram.md](block-diagram.md) — `_BDHb.xml`
101
+ - [front-panel.md](front-panel.md) — `_FPHb.xml`
102
+ - [dataspace.md](dataspace.md) — base `.xml` (metadata + VCTP + DFDS + links)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "lvkit"
7
- version = "0.3.0"
7
+ version = "0.4.0"
8
8
  description = "Understand and convert LabVIEW VIs to Python without a LabVIEW license"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -70,6 +70,13 @@ dev = [
70
70
  # the wheel automatically. The resolvers and `lvkit setup` load
71
71
  # them via paths relative to the package or via importlib.resources.
72
72
  packages = ["src/lvkit"]
73
+ # lvkit is cleanroom: it ships NO NI-derived primitive artwork. Primitive
74
+ # glyphs are drawn procedurally by the render layer (OriginalGlyphResolver /
75
+ # GeneratedGlyphResolver); un-migrated primitives render as a labeled box. The
76
+ # NI-icon extraction path (a data/glyphs/ asset dir + PdfIconResolver) was
77
+ # removed for licensing. These exclude globs remain as a guard so no such
78
+ # asset can ever be packaged if the directory is reintroduced.
79
+ exclude = ["src/lvkit/data/glyphs/*.png", "src/lvkit/data/glyphs/*.svg"]
73
80
 
74
81
  [tool.hatch.build.targets.sdist]
75
82
  include = [
@@ -86,6 +93,8 @@ exclude = [
86
93
  "outputs",
87
94
  "docs/labview_ref_manual.txt",
88
95
  "docs/*.pdf",
96
+ "src/lvkit/data/glyphs/*.png",
97
+ "src/lvkit/data/glyphs/*.svg",
89
98
  ".lvkit",
90
99
  ".tmp",
91
100
  ]