lvkit 0.8.1__tar.gz → 0.8.2__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 (517) hide show
  1. {lvkit-0.8.1 → lvkit-0.8.2}/.pre-commit-config.yaml +4 -0
  2. {lvkit-0.8.1 → lvkit-0.8.2}/PKG-INFO +1 -1
  3. {lvkit-0.8.1 → lvkit-0.8.2}/pyproject.toml +1 -1
  4. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/__init__.py +1 -1
  5. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/builders/operations.py +8 -1
  6. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/construction.py +1 -0
  7. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/core.py +39 -1
  8. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/loading.py +17 -0
  9. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/models.py +25 -0
  10. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/op_walk.py +81 -13
  11. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/models.py +50 -2
  12. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/constants.py +2 -0
  13. lvkit-0.8.2/src/lvkit/parser/image_resources.py +103 -0
  14. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/layout.py +634 -25
  15. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/models.py +5 -0
  16. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/node_types.py +99 -1
  17. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/case.py +26 -7
  18. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/constant.py +34 -0
  19. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/vi.py +43 -2
  20. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/__init__.py +50 -1
  21. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/backend.py +12 -2
  22. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/composite.py +116 -5
  23. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/draw.py +386 -40
  24. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyph.py +13 -0
  25. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/decorations/__init__.py +2 -0
  26. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/decorations/arrow.py +17 -8
  27. lvkit-0.8.2/src/lvkit/render/glyphs/decorations/factory.py +65 -0
  28. lvkit-0.8.2/src/lvkit/render/glyphs/decorations/line.py +28 -0
  29. lvkit-0.8.2/src/lvkit/render/glyphs/decorations/picture.py +28 -0
  30. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/array_constant.py +214 -0
  31. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/base.py +24 -0
  32. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/bundle_by_name.py +129 -0
  33. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/class_glyph.py +115 -0
  34. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/cluster_constant.py +206 -0
  35. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/constant.py +12 -3
  36. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/event_reg_node.py +103 -0
  37. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/path_glyph.py +71 -0
  38. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/property_node.py +41 -9
  39. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/refnum_glyph.py +299 -0
  40. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/nodes.py +404 -31
  41. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/scene.py +64 -97
  42. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/style.py +205 -23
  43. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/theme_web.py +3 -1
  44. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/structure.py +129 -2
  45. lvkit-0.8.2/tests/corpus/issues/82/Pictures And Decorations.vi +0 -0
  46. lvkit-0.8.2/tests/test_class_wire_appearance.py +119 -0
  47. lvkit-0.8.2/tests/test_cluster_wire_color.py +49 -0
  48. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_issue_corpus.py +103 -1
  49. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_parser.py +688 -0
  50. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_render.py +1902 -137
  51. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_type_loading.py +39 -0
  52. lvkit-0.8.1/src/lvkit/render/glyphs/decorations/factory.py +0 -47
  53. lvkit-0.8.1/src/lvkit/render/glyphs/decorations/line.py +0 -21
  54. lvkit-0.8.1/src/lvkit/render/glyphs/nodes/bundle_by_name.py +0 -49
  55. lvkit-0.8.1/src/lvkit/render/glyphs/nodes/cluster_constant.py +0 -92
  56. {lvkit-0.8.1 → lvkit-0.8.2}/.gitignore +0 -0
  57. {lvkit-0.8.1 → lvkit-0.8.2}/LICENSE +0 -0
  58. {lvkit-0.8.1 → lvkit-0.8.2}/NOTICE +0 -0
  59. {lvkit-0.8.1 → lvkit-0.8.2}/README.md +0 -0
  60. {lvkit-0.8.1 → lvkit-0.8.2}/deploy/cloudrun/README.md +0 -0
  61. {lvkit-0.8.1 → lvkit-0.8.2}/docs/_internal/xml-schema/README.md +0 -0
  62. {lvkit-0.8.1 → lvkit-0.8.2}/editors/vscode/LICENSE +0 -0
  63. {lvkit-0.8.1 → lvkit-0.8.2}/editors/vscode/README.md +0 -0
  64. {lvkit-0.8.1 → lvkit-0.8.2}/mcpb/README.md +0 -0
  65. {lvkit-0.8.1 → lvkit-0.8.2}/plugin/README.md +0 -0
  66. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/audit_primitive_consistency.py +0 -0
  67. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/audit_terminal_order.py +0 -0
  68. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/audit_unresolved.py +0 -0
  69. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/build_example_pages.sh +0 -0
  70. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/build_hero.py +0 -0
  71. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/build_ni_function_catalog.py +0 -0
  72. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/connector_geometry_audit.py +0 -0
  73. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/dump_primitive_context.py +0 -0
  74. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/extract_corpus.py +0 -0
  75. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/gen_semantics_probe.py +0 -0
  76. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/generate_docs.py +0 -0
  77. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/generate_driver_data.py +0 -0
  78. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/generate_python.py +0 -0
  79. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/import_nodes_primitives.py +0 -0
  80. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/list_unknown_primitives.py +0 -0
  81. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/populate_vilib.py +0 -0
  82. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/pull_samples.sh +0 -0
  83. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/recategorize_vilib.py +0 -0
  84. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/render_gallery.py +0 -0
  85. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/reproduce_openg_corpus.py +0 -0
  86. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/study_unwired_direction.py +0 -0
  87. {lvkit-0.8.1 → lvkit-0.8.2}/scripts/wire_decode_probe.py +0 -0
  88. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/__main__.py +0 -0
  89. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/_data.py +0 -0
  90. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/_pylabview_patches.py +0 -0
  91. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/cache_paths.py +0 -0
  92. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/cli.py +0 -0
  93. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/README.md +0 -0
  94. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/__init__.py +0 -0
  95. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/ast_optimizer.py +0 -0
  96. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/ast_utils.py +0 -0
  97. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/builder.py +0 -0
  98. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/__init__.py +0 -0
  99. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/_shared.py +0 -0
  100. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/config.py +0 -0
  101. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/core.py +0 -0
  102. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/init_builder.py +0 -0
  103. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/methods.py +0 -0
  104. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/naming.py +0 -0
  105. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/properties.py +0 -0
  106. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/class_builder/terminals.py +0 -0
  107. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/condition_builder.py +0 -0
  108. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/context.py +0 -0
  109. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/dataflow.py +0 -0
  110. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/elementwise.py +0 -0
  111. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/error_handler.py +0 -0
  112. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/expressions.py +0 -0
  113. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/fragment.py +0 -0
  114. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/function.py +0 -0
  115. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/imports.py +0 -0
  116. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/__init__.py +0 -0
  117. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/base.py +0 -0
  118. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/case.py +0 -0
  119. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/compound.py +0 -0
  120. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/constant.py +0 -0
  121. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/event.py +0 -0
  122. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/first_call.py +0 -0
  123. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/formula.py +0 -0
  124. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/in_place.py +0 -0
  125. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/invoke_node.py +0 -0
  126. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/loop.py +0 -0
  127. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/nmux.py +0 -0
  128. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/primitive.py +0 -0
  129. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/printf.py +0 -0
  130. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/property_node.py +0 -0
  131. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/queue_ops.py +0 -0
  132. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/sequence.py +0 -0
  133. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/nodes/subvi.py +0 -0
  134. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/stubs.py +0 -0
  135. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/codegen/unresolved.py +0 -0
  136. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/connector_geometry.py +0 -0
  137. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/connector_pane_geometry.py +0 -0
  138. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/builtin_types.json +0 -0
  139. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/connector_pane_patterns.json +0 -0
  140. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/_index.json +0 -0
  141. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/daqmx.json +0 -0
  142. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/nidcpower.json +0 -0
  143. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/nidigital.json +0 -0
  144. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/nidmm.json +0 -0
  145. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/nifgen.json +0 -0
  146. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/niscope.json +0 -0
  147. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/niswitch.json +0 -0
  148. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/serial.json +0 -0
  149. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/drivers/visa.json +0 -0
  150. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/labview_error_codes.json +0 -0
  151. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/measure_data.json +0 -0
  152. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/openg/_index.json +0 -0
  153. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/openg/array.json +0 -0
  154. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/openg/file.json +0 -0
  155. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/openg/string.json +0 -0
  156. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/openg/time.json +0 -0
  157. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/openg/variant.json +0 -0
  158. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/primitives.json +0 -0
  159. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/_index.json +0 -0
  160. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/_pending_terminals.json +0 -0
  161. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/_types.json +0 -0
  162. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/addons.json +0 -0
  163. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/application-control.json +0 -0
  164. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/array.json +0 -0
  165. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/boolean.json +0 -0
  166. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/cluster-class-variant.json +0 -0
  167. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/collection.json +0 -0
  168. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/comparison.json +0 -0
  169. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/connectivity.json +0 -0
  170. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/control-simulation.json +0 -0
  171. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/data-communication.json +0 -0
  172. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/dialog-user-interface.json +0 -0
  173. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/express.json +0 -0
  174. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/file-io.json +0 -0
  175. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/graphics-sound.json +0 -0
  176. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/instrument-io.json +0 -0
  177. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/mathematics.json +0 -0
  178. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/measurement-io.json +0 -0
  179. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/numeric.json +0 -0
  180. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/report-generation.json +0 -0
  181. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/signal-processing.json +0 -0
  182. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/string.json +0 -0
  183. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/structures.json +0 -0
  184. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/synchronization.json +0 -0
  185. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/timing.json +0 -0
  186. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/data/vilib/waveform.json +0 -0
  187. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/__init__.py +0 -0
  188. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/generate.py +0 -0
  189. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/html_generator/__init__.py +0 -0
  190. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/html_generator/assets.py +0 -0
  191. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/html_generator/class_page.py +0 -0
  192. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/html_generator/core.py +0 -0
  193. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/html_generator/index_page.py +0 -0
  194. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/html_generator/naming.py +0 -0
  195. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/html_generator/vi_page.py +0 -0
  196. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/template.css +0 -0
  197. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/docs/utils.py +0 -0
  198. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/extractor.py +0 -0
  199. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/flattened_typedesc.py +0 -0
  200. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/formula/__init__.py +0 -0
  201. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/formula/cparser.py +0 -0
  202. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/formula/emit.py +0 -0
  203. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/formula/lexer.py +0 -0
  204. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/formula/nodes.py +0 -0
  205. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/__init__.py +0 -0
  206. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/analysis.py +0 -0
  207. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/builders/__init__.py +0 -0
  208. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/builders/context.py +0 -0
  209. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/builders/refs.py +0 -0
  210. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/builders/structures.py +0 -0
  211. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/describe.py +0 -0
  212. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/diff.py +0 -0
  213. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/interface_order.py +0 -0
  214. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/lvnet_grammar.py +0 -0
  215. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/lvnet_parse.py +0 -0
  216. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/lvnet_reconstruct.py +0 -0
  217. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/netlist.py +0 -0
  218. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/netlist_build.py +0 -0
  219. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/netlist_diff_helpers.py +0 -0
  220. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/netlist_json.py +0 -0
  221. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/netlist_models.py +0 -0
  222. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/operations.py +0 -0
  223. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/parallel_parse.py +0 -0
  224. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/queries.py +0 -0
  225. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/graph/render_lvnet.py +0 -0
  226. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/index/__init__.py +0 -0
  227. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/index/build.py +0 -0
  228. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/index/model.py +0 -0
  229. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/index/project.py +0 -0
  230. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/index/query.py +0 -0
  231. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/index/sql.py +0 -0
  232. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/index/store.py +0 -0
  233. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/labview_error.py +0 -0
  234. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/labview_error_codes.py +0 -0
  235. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/labview_queue.py +0 -0
  236. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/load_mode.py +0 -0
  237. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/lv_detect.py +0 -0
  238. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/__init__.py +0 -0
  239. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/schemas.py +0 -0
  240. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/__init__.py +0 -0
  241. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/__main__.py +0 -0
  242. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/_compat.py +0 -0
  243. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/app.py +0 -0
  244. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/index_tools.py +0 -0
  245. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/resolvers.py +0 -0
  246. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/roots.py +0 -0
  247. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/mcp/server/vi_tools.py +0 -0
  248. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/measure_data.py +0 -0
  249. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/num_format.py +0 -0
  250. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/output_cache.py +0 -0
  251. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/__init__.py +0 -0
  252. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/conp_types.py +0 -0
  253. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/defaults.py +0 -0
  254. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/flags.py +0 -0
  255. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/fp_heap_type.py +0 -0
  256. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/front_panel.py +0 -0
  257. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/metadata.py +0 -0
  258. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/naming.py +0 -0
  259. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/__init__.py +0 -0
  260. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/base.py +0 -0
  261. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/decompose.py +0 -0
  262. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/disable.py +0 -0
  263. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/event.py +0 -0
  264. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/free_label.py +0 -0
  265. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/loop.py +0 -0
  266. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/nodes/sequence.py +0 -0
  267. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/type_mapping.py +0 -0
  268. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/type_resolution.py +0 -0
  269. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/utils.py +0 -0
  270. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/parser/wire_table.py +0 -0
  271. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/pipeline.py +0 -0
  272. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/primitive_resolver/__init__.py +0 -0
  273. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/primitive_resolver/exceptions.py +0 -0
  274. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/primitive_resolver/models.py +0 -0
  275. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/primitive_resolver/resolver.py +0 -0
  276. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/project_store.py +0 -0
  277. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/py.typed +0 -0
  278. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/ARCHITECTURE.md +0 -0
  279. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/connector_pane.py +0 -0
  280. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/connector_pane_panel.py +0 -0
  281. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/diff_viewer.py +0 -0
  282. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/__init__.py +0 -0
  283. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/decorations/base.py +0 -0
  284. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/decorations/fallback.py +0 -0
  285. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/decorations/frame.py +0 -0
  286. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/__init__.py +0 -0
  287. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/arith.py +0 -0
  288. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/array_build.py +0 -0
  289. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/array_reverse.py +0 -0
  290. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/array_search.py +0 -0
  291. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/array_size.py +0 -0
  292. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/array_sort.py +0 -0
  293. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/array_split.py +0 -0
  294. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/boolean_constant.py +0 -0
  295. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/boolean_gate.py +0 -0
  296. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/bundle.py +0 -0
  297. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/centered_svg.py +0 -0
  298. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/compound_arith.py +0 -0
  299. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/control_ref_const.py +0 -0
  300. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/convert.py +0 -0
  301. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/error_cluster.py +0 -0
  302. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/event_data.py +0 -0
  303. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/formula_node.py +0 -0
  304. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/icon_image.py +0 -0
  305. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/in_place_element.py +0 -0
  306. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/inline_svg.py +0 -0
  307. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/invoke_node.py +0 -0
  308. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/label.py +0 -0
  309. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/local_variable.py +0 -0
  310. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/unbundle.py +0 -0
  311. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/variant.py +0 -0
  312. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/nodes/wrapped_box.py +0 -0
  313. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/__init__.py +0 -0
  314. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/base.py +0 -0
  315. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/case.py +0 -0
  316. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/disable.py +0 -0
  317. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/event.py +0 -0
  318. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/factory.py +0 -0
  319. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/flat_sequence.py +0 -0
  320. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/for_loop.py +0 -0
  321. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/generic.py +0 -0
  322. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/in_place.py +0 -0
  323. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/selectable.py +0 -0
  324. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/stacked_sequence.py +0 -0
  325. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/structures/while_loop.py +0 -0
  326. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/__init__.py +0 -0
  327. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/autoindex.py +0 -0
  328. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/base.py +0 -0
  329. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/concatenate.py +0 -0
  330. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/conditional.py +0 -0
  331. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/event_dyn.py +0 -0
  332. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/event_timeout.py +0 -0
  333. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/factory.py +0 -0
  334. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/generic.py +0 -0
  335. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/loop_count.py +0 -0
  336. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/selector.py +0 -0
  337. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/shift_register.py +0 -0
  338. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/glyphs/terminals/tunnel.py +0 -0
  339. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/help_tip.py +0 -0
  340. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/icons.py +0 -0
  341. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/lane_pass.py +0 -0
  342. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/properties_panel.py +0 -0
  343. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/render_viewer.py +0 -0
  344. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/templates/diff_viewer.html +0 -0
  345. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/templates/render_viewer.html +0 -0
  346. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/theme_control.py +0 -0
  347. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/render/wire_router.py +0 -0
  348. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/runtime/__init__.py +0 -0
  349. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/runtime/lv.py +0 -0
  350. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/__init__.py +0 -0
  351. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/lvkit/SKILL.md +0 -0
  352. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/lvkit-convert/SKILL.md +0 -0
  353. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/lvkit-describe/SKILL.md +0 -0
  354. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/lvkit-document/SKILL.md +0 -0
  355. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/lvkit-query/SKILL.md +0 -0
  356. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/lvkit-resolve/SKILL.md +0 -0
  357. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/skill_templates/lvkit-review/SKILL.md +0 -0
  358. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/terminal_collector.py +0 -0
  359. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/text_encoding.py +0 -0
  360. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/tools/__init__.py +0 -0
  361. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/tools/connector_geometry_profile.py +0 -0
  362. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/type_defaults.py +0 -0
  363. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/unresolved.py +0 -0
  364. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vi_diff.py +0 -0
  365. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/__init__.py +0 -0
  366. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/exceptions.py +0 -0
  367. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/loader.py +0 -0
  368. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/lookup.py +0 -0
  369. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/models.py +0 -0
  370. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/naming.py +0 -0
  371. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/resolver.py +0 -0
  372. {lvkit-0.8.1 → lvkit-0.8.2}/src/lvkit/vilib_resolver/variants.py +0 -0
  373. {lvkit-0.8.1 → lvkit-0.8.2}/tests/__init__.py +0 -0
  374. {lvkit-0.8.1 → lvkit-0.8.2}/tests/conftest.py +0 -0
  375. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/PROVENANCE.md +0 -0
  376. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Lib1/Class/Class.lvclass +0 -0
  377. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Lib1/Class/Do.vi +0 -0
  378. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Lib1/Lib1.lvlib +0 -0
  379. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Class.lvclass +0 -0
  380. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Do.vi +0 -0
  381. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Test.vi +0 -0
  382. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Lib2/Lib2.lvlib +0 -0
  383. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Test LVKit.aliases +0 -0
  384. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Test LVKit.lvlps +0 -0
  385. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/29/Test LVKit/Test LVKit.lvproj +0 -0
  386. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/30/PROVENANCE.md +0 -0
  387. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/30/visible-frame-case-sequence.vi +0 -0
  388. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/30/visible-frame-conditional-disable.vi +0 -0
  389. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/31/PROVENANCE.md +0 -0
  390. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/31/disable-structure-frame-names.vi +0 -0
  391. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/32/PROVENANCE.md +0 -0
  392. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/32/comments-and-decorations.vi +0 -0
  393. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/33/PROVENANCE.md +0 -0
  394. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/33/coercion-dot-consistency.vi +0 -0
  395. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/34/PROVENANCE.md +0 -0
  396. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/34/hidden-iteration-terminal.vi +0 -0
  397. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/35/PROVENANCE.md +0 -0
  398. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/35/objects-hidden-by-structures.vi +0 -0
  399. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/36/PROVENANCE.md +0 -0
  400. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/36/bundle-unbundle-names.vi +0 -0
  401. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/37/PROVENANCE.md +0 -0
  402. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/37/structure-tunnel-wire-bends.vi +0 -0
  403. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/38/PROVENANCE.md +0 -0
  404. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/38/auto-concatenating-tunnel.vi +0 -0
  405. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/39/PROVENANCE.md +0 -0
  406. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/39/zorder-not-respected.vi +0 -0
  407. {lvkit-0.8.1 → lvkit-0.8.2}/tests/corpus/issues/README.md +0 -0
  408. {lvkit-0.8.1 → lvkit-0.8.2}/tests/helpers.py +0 -0
  409. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_array_ops_codegen.py +0 -0
  410. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_ast_builder.py +0 -0
  411. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_ast_optimizer.py +0 -0
  412. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_case_codegen.py +0 -0
  413. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_case_parser.py +0 -0
  414. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_class_field_walkup.py +0 -0
  415. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_class_parent_linkinfo.py +0 -0
  416. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_class_properties.py +0 -0
  417. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_cli.py +0 -0
  418. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_cli_cache.py +0 -0
  419. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_cli_describe_lvnet.py +0 -0
  420. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_cli_graph_ops.py +0 -0
  421. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_cli_query.py +0 -0
  422. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_codegen_context.py +0 -0
  423. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_compound_codegen.py +0 -0
  424. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_condition_builder.py +0 -0
  425. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_connector_geometry.py +0 -0
  426. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_connector_pane_label_recovery.py +0 -0
  427. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_connector_pane_patterns.py +0 -0
  428. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_connector_pane_render.py +0 -0
  429. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_conp_types.py +0 -0
  430. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_constant_decoding.py +0 -0
  431. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_dependency_path_refs.py +0 -0
  432. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_determinism.py +0 -0
  433. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_diff.py +0 -0
  434. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_diff_properties.py +0 -0
  435. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_diff_viewer.py +0 -0
  436. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_disable_graph.py +0 -0
  437. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_disable_parser.py +0 -0
  438. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_docs_class_hierarchy.py +0 -0
  439. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_docs_render.py +0 -0
  440. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_driver_codegen.py +0 -0
  441. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_dynamic_dispatch.py +0 -0
  442. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_e2e_codegen.py +0 -0
  443. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_elementwise.py +0 -0
  444. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_error_codegen.py +0 -0
  445. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_error_handling.py +0 -0
  446. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_error_terminal_label_fallback.py +0 -0
  447. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_event_codegen.py +0 -0
  448. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_event_parser.py +0 -0
  449. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_extraction_cache.py +0 -0
  450. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_extractor_concurrency.py +0 -0
  451. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_extractor_long_path.py +0 -0
  452. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_first_call_codegen.py +0 -0
  453. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_formula_codegen.py +0 -0
  454. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_formula_runtime.py +0 -0
  455. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_formula_semantics.py +0 -0
  456. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_formula_transpile.py +0 -0
  457. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_fp_heap_type.py +0 -0
  458. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_frame_attribution.py +0 -0
  459. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_frame_zplane.py +0 -0
  460. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_glyphs.py +0 -0
  461. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_graceful_degradation.py +0 -0
  462. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_help_tip.py +0 -0
  463. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_import_startup.py +0 -0
  464. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_in_place_codegen.py +0 -0
  465. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_index.py +0 -0
  466. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_index_sql.py +0 -0
  467. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_index_warm_no_downgrade.py +0 -0
  468. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_interface_order.py +0 -0
  469. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_label_extraction.py +0 -0
  470. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_labview_queue.py +0 -0
  471. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_livi_vipi.py +0 -0
  472. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_load_mode.py +0 -0
  473. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_load_upgrade.py +0 -0
  474. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_loop_codegen.py +0 -0
  475. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_lv_detect.py +0 -0
  476. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_lvnet_identity.py +0 -0
  477. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_lvnet_reconstruct.py +0 -0
  478. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_lvnet_roundtrip.py +0 -0
  479. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_lvpy.py +0 -0
  480. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_mcp_cache.py +0 -0
  481. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_mcp_evals.py +0 -0
  482. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_mcp_read_vi_lvnet.py +0 -0
  483. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_mcp_roots.py +0 -0
  484. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_naming.py +0 -0
  485. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_netlist_json.py +0 -0
  486. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_new_codegen.py +0 -0
  487. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_node_properties.py +0 -0
  488. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_output_cache.py +0 -0
  489. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_parallel_codegen.py +0 -0
  490. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_parallel_parse.py +0 -0
  491. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_parser_regression.py +0 -0
  492. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_primitive_name_uniqueness.py +0 -0
  493. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_primitive_positional_order.py +0 -0
  494. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_primitive_resolutions.py +0 -0
  495. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_progressive_index.py +0 -0
  496. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_progressive_warm.py +0 -0
  497. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_project_store.py +0 -0
  498. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_queue_codegen.py +0 -0
  499. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_render_emission_order.py +0 -0
  500. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_render_lvnet.py +0 -0
  501. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_render_title_identity.py +0 -0
  502. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_render_viewer.py +0 -0
  503. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_sequence.py +0 -0
  504. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_soft_codegen.py +0 -0
  505. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_structure_lvproj.py +0 -0
  506. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_subvi_nav.py +0 -0
  507. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_text_encoding.py +0 -0
  508. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_type_driven_fixes.py +0 -0
  509. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_type_fields.py +0 -0
  510. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_type_mapping.py +0 -0
  511. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_unknown_nodes.py +0 -0
  512. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_unresolved.py +0 -0
  513. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_vi_graph.py +0 -0
  514. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_vi_properties.py +0 -0
  515. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_viewer_properties.py +0 -0
  516. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_vilib_docurls.py +0 -0
  517. {lvkit-0.8.1 → lvkit-0.8.2}/tests/test_web_progressive_staging.py +0 -0
@@ -26,6 +26,10 @@ repos:
26
26
  - id: check-toml
27
27
  - id: check-added-large-files
28
28
  args: ["--maxkb=500"]
29
+ # Issue #82's regression fixture embeds a real ~3.6MB photograph (the
30
+ # bug is an embedded PICTURE decoration), so it can't fit the 500KB cap.
31
+ # Whitelist just that one file — the cap still guards every other fixture.
32
+ exclude: ^tests/corpus/issues/82/Pictures And Decorations\.vi$
29
33
  - id: check-merge-conflict
30
34
  - id: mixed-line-ending
31
35
  args: ["--fix=lf"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: lvkit
3
- Version: 0.8.1
3
+ Version: 0.8.2
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "lvkit"
7
- version = "0.8.1"
7
+ version = "0.8.2"
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"
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- __version__ = "0.8.1"
7
+ __version__ = "0.8.2"
8
8
 
9
9
  # The public API is exposed LAZILY (PEP 562 module ``__getattr__``): the graph /
10
10
  # parser / structure stacks (networkx, pydantic, pylabview, PIL — ~230 ms) load
@@ -16,6 +16,7 @@ from typing import Any
16
16
  from lvkit.models import PropertyDef, Terminal
17
17
  from lvkit.parser.node_types import (
18
18
  CpdArithNode,
19
+ EventRegNode,
19
20
  InvokeNode,
20
21
  PropertyNode,
21
22
  SubVINode,
@@ -95,7 +96,7 @@ class PrimitiveBuildHandler(NodeBuildHandler):
95
96
  prim_kwargs["prim_index"] = node.prim_index
96
97
  if isinstance(node, CpdArithNode):
97
98
  prim_kwargs["operation"] = node.operation
98
- if isinstance(node, (PropertyNode, InvokeNode)):
99
+ if isinstance(node, (PropertyNode, InvokeNode, EventRegNode)):
99
100
  prim_kwargs["object_name"] = node.object_name
100
101
  prim_kwargs["object_method_id"] = node.object_method_id
101
102
  if isinstance(node, PropertyNode):
@@ -106,12 +107,18 @@ class PrimitiveBuildHandler(NodeBuildHandler):
106
107
  prim_kwargs["property_value_terminal_ids"] = [
107
108
  ctx.qid(uid) for uid in node.dco_terminal_uids
108
109
  ]
110
+ prim_kwargs["bound_control_uid"] = node.bound_control_uid
111
+ prim_kwargs["bound_control_type"] = node.bound_control_type
109
112
  elif isinstance(node, InvokeNode):
110
113
  prim_kwargs["method_name"] = node.method_name
111
114
  prim_kwargs["method_code"] = node.method_code
112
115
  prim_kwargs["invoke_row_terminal_ids"] = [
113
116
  ctx.qid(uid) for uid in node.row_terminal_uids
114
117
  ]
118
+ elif isinstance(node, EventRegNode):
119
+ prim_kwargs["event_row_terminal_ids"] = [
120
+ ctx.qid(uid) for uid in node.event_row_terminal_uids
121
+ ]
115
122
 
116
123
  return GraphPrimitiveNode(
117
124
  id=q_node_uid,
@@ -463,6 +463,7 @@ class ConstructionMixin:
463
463
  raw_value=const.value,
464
464
  label=const.label,
465
465
  display_format=const.display_format,
466
+ collapsed=const.collapsed,
466
467
  terminals=[const_terminal],
467
468
  )
468
469
  g.add_node(q_const_uid, node=const_node)
@@ -13,7 +13,7 @@ from typing import TYPE_CHECKING
13
13
  import networkx as nx
14
14
 
15
15
  from ..load_mode import LoadMode
16
- from ..models import ClusterField, LVType, LVTypeKind
16
+ from ..models import ClusterField, LVType, LVTypeKind, WireStyle
17
17
  from ..parser.models import ParsedType, ParsedVI
18
18
 
19
19
  if TYPE_CHECKING:
@@ -330,6 +330,13 @@ class InMemoryVIGraph(
330
330
  # Class/typedef fields: codegen queries dep_graph or vilib_resolver
331
331
  # by classname/typedef_name. No copies.
332
332
 
333
+ # A class instance carries its OWN wire style (color/width/line style),
334
+ # resolved from its .lvclass, so the one render lookup draws every class
335
+ # wire in the class's style with no graph — see LVType.wire_style /
336
+ # render.style.wire_style.
337
+ if parsed_type.classname:
338
+ lv_type.wire_style = self.get_class_wire_style(parsed_type.classname)
339
+
333
340
  return lv_type
334
341
 
335
342
  def _dep_key_for_ref(
@@ -431,6 +438,37 @@ class InMemoryVIGraph(
431
438
  return parent_fields + own_fields
432
439
  return own_fields
433
440
 
441
+ def get_class_wire_style(
442
+ self,
443
+ classname: str,
444
+ caller_vi_key: str | None = None,
445
+ ) -> WireStyle | None:
446
+ """A class's own wire style, or None when it (and every ancestor) uses the
447
+ default/generic look.
448
+
449
+ ``classname`` is resolved to its PATH-key node via :meth:`_dep_key_for_ref`
450
+ (pass the CALLER VI key so a duplicated class name resolves by the
451
+ caller's edge). A class with no custom pen inherits its parent's (LabVIEW's
452
+ "use parent's/default design"), so the parent chain is walked by
453
+ ``parent_key`` (:meth:`_parent_class_key`) until a custom style is found.
454
+ """
455
+ node_key = self._dep_key_for_ref(classname, caller_vi_key)
456
+ if node_key is None or not self._dep_graph.has_node(node_key):
457
+ return None
458
+ return self._class_wire_style_by_key(node_key)
459
+
460
+ def _class_wire_style_by_key(self, node_key: str) -> WireStyle | None:
461
+ """This class's own wire style, else the nearest ancestor's — the
462
+ inherited case. Follows the parent's PATH key by IDENTITY
463
+ (:meth:`_parent_class_key`), same as :meth:`_class_fields_by_key`."""
464
+ style: WireStyle | None = self._dep_graph.nodes[node_key].get("wire_style")
465
+ if style is not None:
466
+ return style
467
+ parent_key = self._parent_class_key(node_key)
468
+ if parent_key is not None:
469
+ return self._class_wire_style_by_key(parent_key)
470
+ return None
471
+
434
472
  def get_type_fields(
435
473
  self,
436
474
  lv_type: LVType,
@@ -274,6 +274,9 @@ class LoadingMixin:
274
274
  iuse_to_qpath: dict[str, str] | None = None,
275
275
  ) -> None: ...
276
276
  def resolve_dispatch_qnames(self) -> None: ...
277
+ def _dep_key_for_ref(
278
+ self, ref: str, caller_vi_key: str | None = None
279
+ ) -> str | None: ...
277
280
 
278
281
  def load_vi(
279
282
  self,
@@ -718,6 +721,7 @@ class LoadingMixin:
718
721
  version=cls.version,
719
722
  ancestors=cls.ancestors,
720
723
  method_paths=method_paths,
724
+ wire_style=cls.wire_style,
721
725
  )
722
726
  self._register_dep_node(cls_key, cls_path_r, cls_name, cls_qname)
723
727
  self._stubs.discard(cls_key)
@@ -1588,6 +1592,19 @@ class LoadingMixin:
1588
1592
  if caller_qname:
1589
1593
  self._dep_graph.add_edge(caller_qname, found_key)
1590
1594
  return
1595
+ # Before stubbing: a SIBLING reference may already have resolved this
1596
+ # same file by path (e.g. a type_map's BARE ``typedef_name`` —
1597
+ # ``Parameters.ctl`` — duplicating the VICC-linked, path-resolved
1598
+ # qualified ref ``…lvclass:Parameters.ctl``). Route this ref's edge
1599
+ # onto that resolved node via the caller-scoped resolver instead of
1600
+ # spawning a second, empty bare-name stub node beside it. Caller-
1601
+ # scoped + unique-match (``_dep_key_for_ref``) so it can never point
1602
+ # at a same-leaf file from a different library.
1603
+ existing = self._dep_key_for_ref(qualified_name, caller_qname)
1604
+ if existing is not None and existing not in self._stubs:
1605
+ if caller_qname:
1606
+ self._dep_graph.add_edge(caller_qname, existing)
1607
+ return
1591
1608
  node_type = (
1592
1609
  "class"
1593
1610
  if leaf.endswith(".lvclass")
@@ -140,6 +140,13 @@ class PrimitiveNode(GraphNode):
140
140
  # rows 1..N = params [input, output]). Ids match ``terminals[i].id``.
141
141
  # See render/nodes.py:_invoke_node_glyph for how rows are built from this.
142
142
  invoke_row_terminal_ids: list[str] = []
143
+ # Register-For-Events node only (task #56): qualified terminal ids from
144
+ # the parser's dcoList, one per registered event source, in heap order
145
+ # -- each is a GROWABLE row's own INPUT terminal (the event source
146
+ # refnum to register on). Same dcoList convention as
147
+ # ``property_value_terminal_ids``/``invoke_row_terminal_ids``. See
148
+ # render/nodes.py:_event_reg_node_glyph.
149
+ event_row_terminal_ids: list[str] = []
143
150
  # Property node only: qualified terminal ids from the parser's dcoList,
144
151
  # ``properties[i]`` correlates to the terminal whose id is
145
152
  # ``property_value_terminal_ids[i]`` -- LabVIEW's real dcoList/permDCOList
@@ -151,6 +158,20 @@ class PrimitiveNode(GraphNode):
151
158
  # reference terminal, but this structural id list always can. See
152
159
  # ``op_walk.correlate_property_terminals``.
153
160
  property_value_terminal_ids: list[str] = []
161
+ # Property node only: the BOUND front-panel control's own ddo uid (RAW,
162
+ # unqualified -- not this node's own qualified id) when this property
163
+ # node is IMPLICIT (permanently tied to a specific control, e.g. GTR's
164
+ # "Abort" boolean property node) -- "" for an EXPLICIT one (identity from
165
+ # a wired reference). See ``parser.node_types.PropertyNode``'s class
166
+ # docstring for the full heap discriminator (a direct ``<ddo>`` child +
167
+ # a ``<label>`` naming the control, both absent when explicit).
168
+ bound_control_uid: str = ""
169
+ # The bound control's reconstructed LVType (``parser.fp_heap_type.
170
+ # reconstruct_control_lvtype``, resolved at PARSE time against the
171
+ # front-panel heap -- see ``parser.vi._resolve_property_node_bound_types``).
172
+ # None for an explicit node, or an implicit one whose control class isn't
173
+ # modeled by that reconstructor.
174
+ bound_control_type: LVType | None = None
154
175
 
155
176
 
156
177
  class StructureNode(GraphNode):
@@ -312,6 +333,10 @@ class ConstantNode(GraphNode):
312
333
  # (``ParsedConstant.display_format``, e.g. ``%.0x`` for hex), threaded
313
334
  # through unchanged — render/nodes.py is where it's interpreted.
314
335
  display_format: str | None = None
336
+ # True when this cluster/array constant is drawn COLLAPSED ("View As Icon",
337
+ # ``ParsedConstant.collapsed``): render shows a compact icon, not its
338
+ # members/elements (LabVIEW never shrinks a value's natural height).
339
+ collapsed: bool = False
315
340
 
316
341
 
317
342
  class LabelNode(GraphNode):
@@ -30,7 +30,7 @@ from ..models import (
30
30
  _is_error_cluster,
31
31
  )
32
32
  from ..num_format import format_numeric_const
33
- from ..parser.constants import NMUX_BY_NAME_NODE_CLASSES
33
+ from ..parser.constants import NMUX_BY_NAME_NODE_CLASSES, NODE_CLASS_NMUX
34
34
  from ..structure import _fields_from_xml, private_data_field_to_cluster_field
35
35
  from ..vilib_resolver import get_resolver as _get_vilib_resolver
36
36
  from .models import Constant
@@ -125,26 +125,52 @@ def _own_class_private_data_fields(
125
125
  return [private_data_field_to_cluster_field(f) for f in fields]
126
126
 
127
127
 
128
+ def _nmux_index_leaf_only(node_type: str | None, agg: Terminal | None) -> bool:
129
+ """How a node's flat ``<i>`` field index counts a NESTED cluster's fields.
130
+
131
+ FULL depth-first flatten (an intermediate sub-cluster is itself an
132
+ addressable slot) applies to exactly ONE case: a Bundle/Unbundle By Name
133
+ (``nMux``) over a plain typedef/cluster aggregate. Class private data —
134
+ accessed by ``nMux`` OR the IPES cluster border ``decomposeClusterNode`` —
135
+ and event data index LEAF fields only. Verified: ``nMux`` on
136
+ ``Parameters.ctl`` uses ``<i>``=40 for the whole ``PWM Config`` sub-cluster
137
+ (slot 40 of the full flatten; leaf-only has no such slot); ``nMux`` on a
138
+ class's own private data resolves ``pin_map_id`` (leaf); and a
139
+ ``decomposeClusterNode`` on ``Daqmx Module runtime`` private data uses
140
+ 7/1/9/3 -> the leaf fields DI Index/AO Task/PWM Freq Index/DO Task. So the
141
+ private-data (``classname``-bearing) aggregate stays leaf even under
142
+ ``nMux``."""
143
+ if node_type != NODE_CLASS_NMUX:
144
+ return True
145
+ return not (
146
+ agg is not None
147
+ and agg.lv_type is not None
148
+ and agg.lv_type.classname is None
149
+ )
150
+
151
+
128
152
  def _resolve_nmux_field_name(
129
153
  field_index: int | None,
130
154
  *field_sources: list[ClusterField],
155
+ leaf_only: bool,
131
156
  ) -> str | None:
132
157
  """Resolve a field-index's LabVIEW field name, trying each of
133
158
  ``field_sources`` (in priority order) in turn — each row resolved
134
159
  independently, so one source can cover a row another source misses.
135
160
 
136
- Each source is flattened LEAF-first (``_flatten_leaf_fields``):
137
- LabVIEW's flat ``<i>`` index for a NESTED cluster (e.g. a class
138
- private-data cluster whose own fields are themselves sub-clusters) runs
139
- over leaves only — an intermediate sub-cluster is never itself an
140
- addressable flat slot.
161
+ ``leaf_only`` picks how each source is flattened for a NESTED cluster (see
162
+ :func:`_nmux_index_leaf_only`): ``True`` counts LEAF fields only
163
+ (``_flatten_leaf_fields`` — IPES decompose / event data), ``False`` counts
164
+ every node depth-first so a whole sub-cluster is its own addressable slot
165
+ (``_flatten_fields`` — Bundle/Unbundle By Name).
141
166
  """
142
167
  if field_index is None:
143
168
  return None
169
+ flatten = _flatten_leaf_fields if leaf_only else _flatten_fields
144
170
  for fields in field_sources:
145
171
  if not fields:
146
172
  continue
147
- flat = _flatten_leaf_fields(fields)
173
+ flat = flatten(fields)
148
174
  if 0 <= field_index < len(flat):
149
175
  name = flat[field_index][1].name
150
176
  if name:
@@ -152,6 +178,31 @@ def _resolve_nmux_field_name(
152
178
  return None
153
179
 
154
180
 
181
+ def _resolve_nmux_field_path(
182
+ field_index: int | None,
183
+ *field_sources: list[ClusterField],
184
+ leaf_only: bool,
185
+ ) -> str | None:
186
+ """The full dotted navigation PATH to a NESTED field for a resolved nmux
187
+ index (e.g. ``Strain Config.strain gage information.poisson ratio``), or
188
+ None for a top-level field or when nothing resolves. Same flatten/source
189
+ order as :func:`_resolve_nmux_field_name` (which returns only the leaf) — the
190
+ flatten already carries the path per slot; this just keeps it for the
191
+ tooltip. Only a genuinely nested path (more than one segment) is returned."""
192
+ if field_index is None:
193
+ return None
194
+ flatten = _flatten_leaf_fields if leaf_only else _flatten_fields
195
+ for fields in field_sources:
196
+ if not fields:
197
+ continue
198
+ flat = flatten(fields)
199
+ if 0 <= field_index < len(flat):
200
+ path, field = flat[field_index]
201
+ if field.name and len(path) > 1:
202
+ return ".".join(path)
203
+ return None
204
+
205
+
155
206
  def _nmux_field_sources(
156
207
  vi_name: str,
157
208
  agg: Terminal | None,
@@ -183,13 +234,15 @@ def _nmux_lane_name(
183
234
  agg: Terminal | None,
184
235
  vi_name: str,
185
236
  graph: InMemoryVIGraph,
237
+ node_type: str | None,
186
238
  ) -> str | None:
187
239
  """THE canonical field-name resolution for an nMux/decompose LIST
188
240
  terminal, via ``term.nmux_field_index`` into the aggregate's field list
189
- (``_nmux_field_sources``, then ``_resolve_nmux_field_name``). Returns
190
- None when neither source resolves a name — callers keep their own
191
- index/name fallback (a bracketed index or the terminal's own name is
192
- display-only, never worth pinning onto ``display_name``)."""
241
+ (``_nmux_field_sources``, then ``_resolve_nmux_field_name`` — flattened per
242
+ ``node_type``, see :func:`_nmux_index_leaf_only`). Returns None when neither
243
+ source resolves a name — callers keep their own index/name fallback (a
244
+ bracketed index or the terminal's own name is display-only, never worth
245
+ pinning onto ``display_name``)."""
193
246
  # A MeasureData aggregate (waveform / digital data) has no VCTP fields — its
194
247
  # component names come from the built-in flavor table, keyed directly by the
195
248
  # drawer's field index (no leaf-flatten).
@@ -200,7 +253,17 @@ def _nmux_lane_name(
200
253
  if name:
201
254
  return name
202
255
  own_fields, dep_fields = _nmux_field_sources(vi_name, agg, graph)
203
- return _resolve_nmux_field_name(term.nmux_field_index, own_fields, dep_fields)
256
+ leaf_only = _nmux_index_leaf_only(node_type, agg)
257
+ name = _resolve_nmux_field_name(
258
+ term.nmux_field_index, own_fields, dep_fields, leaf_only=leaf_only
259
+ )
260
+ if name is not None:
261
+ # Also keep the full dotted path (nested fields only) for the tooltip —
262
+ # the glyph shows the terse leaf ``name``.
263
+ term.field_path = _resolve_nmux_field_path(
264
+ term.nmux_field_index, own_fields, dep_fields, leaf_only=leaf_only
265
+ )
266
+ return name
204
267
 
205
268
 
206
269
  def stamp_nmux_lane_names(graph: InMemoryVIGraph) -> None:
@@ -242,7 +305,7 @@ def stamp_nmux_lane_names(graph: InMemoryVIGraph) -> None:
242
305
  for term in node.terminals:
243
306
  if term.nmux_role != "list" or term.display_name is not None:
244
307
  continue
245
- name = _nmux_lane_name(term, agg, vi_name, graph)
308
+ name = _nmux_lane_name(term, agg, vi_name, graph, node.node_type)
246
309
  if name:
247
310
  term.display_name = name
248
311
 
@@ -356,6 +419,11 @@ def _format_ranges(ranges: list[SelectorRange], fmt: Callable[[int], str]) -> st
356
419
  parts.append(f"{fmt(r.start)}..")
357
420
  elif r.is_single:
358
421
  parts.append(fmt(r.start))
422
+ elif r.end == r.start + 1:
423
+ # Exactly two values — nothing lies between them to elide, so list
424
+ # both ("a, b"). ".." means the contiguous middle is skipped, which
425
+ # only applies to a span of three or more values.
426
+ parts.append(f"{fmt(r.start)}, {fmt(r.end)}")
359
427
  else:
360
428
  parts.append(f"{fmt(r.start)}..{fmt(r.end)}")
361
429
  return ", ".join(parts)
@@ -17,8 +17,8 @@ subclasses are the single source of truth for node structure.
17
17
  from __future__ import annotations
18
18
 
19
19
  import re
20
- from dataclasses import dataclass
21
- from enum import Enum
20
+ from dataclasses import dataclass, field
21
+ from enum import Enum, IntEnum
22
22
  from typing import Literal
23
23
 
24
24
  from pydantic import BaseModel
@@ -71,6 +71,12 @@ class LVType:
71
71
  # opaque built-in structures with no VCTP children, so their component names
72
72
  # come from a built-in table keyed by this flavor (see measure_data.py).
73
73
  measure_flavor: str | None = None
74
+ # This type's OWN wire style, when it has one — read by the one wire lookup
75
+ # (``render.style.wire_style``) so wire color/style is data-driven, not a
76
+ # fixed per-family table. None for a type that uses the family default (every
77
+ # built-in today); a LabVIEW class fills it from its ``.lvclass``.
78
+ # ``compare=False`` — presentation, never type identity/coercion.
79
+ wire_style: WireStyle | None = field(default=None, compare=False)
74
80
 
75
81
  def to_python(self) -> str:
76
82
  """Render as Python type annotation string."""
@@ -214,6 +220,43 @@ class LVType:
214
220
  return "?"
215
221
 
216
222
 
223
+ class WireLineStyle(IntEnum):
224
+ """A wire pen's ``Style`` — Solid/Dash/Dot/DashDot/DashDotDot. ``SOLID`` is
225
+ the default and the only style built-in wires use; a LabVIEW class can pick
226
+ another in its ``.lvclass``. ``IntEnum`` so a member equals the raw 0–4 the
227
+ binary stores, drop-in."""
228
+
229
+ SOLID = 0
230
+ DASH = 1
231
+ DOT = 2
232
+ DASH_DOT = 3
233
+ DASH_DOT_DOT = 4
234
+
235
+
236
+ @dataclass(frozen=True)
237
+ class WireStyle:
238
+ """Everything a wire needs to draw itself — the ONE style object the ONE wire
239
+ lookup (``render.style.wire_style``) returns and every drawing site renders.
240
+ A type's OWN style (``LVType.wire_style``) overrides the default per-family
241
+ color/width there; most types have none (the lookup derives theirs from the
242
+ family), but a LabVIEW class carries one decoded from its ``.lvclass``.
243
+
244
+ ``color``/``width``/``line_style`` describe a flat wire. ``edge_color`` +
245
+ ``core_width`` add the class two-band look — an outer ``edge_color`` band at
246
+ ``width`` with a ``color`` center of ``core_width`` on top; both None for a
247
+ flat wire (``width`` is then the single stroke). New wire styles (e.g. a fill
248
+ pattern) are added HERE, once, and every site renders them."""
249
+
250
+ color: str
251
+ width: float
252
+ line_style: WireLineStyle = WireLineStyle.SOLID
253
+ edge_color: str | None = None
254
+ core_width: float | None = None
255
+ # The pen's 8-row fill-pattern bitmap (one byte per row). Non-empty => the
256
+ # class wire is patterned (drawn as a chain) rather than solid; () => solid.
257
+ fill_pattern: tuple[int, ...] = ()
258
+
259
+
217
260
  @dataclass
218
261
  class EnumValue:
219
262
  """A single value in an enum typedef."""
@@ -322,6 +365,11 @@ class Terminal(BaseModel):
322
365
  # this must never change generated code. Used by the renderer's connector-
323
366
  # pane hover / tooltip and by describe. See graph/construction.py.
324
367
  display_name: str | None = None
368
+ # Full dotted navigation path to a NESTED Bundle/Unbundle-By-Name field
369
+ # (e.g. "Strain Config.strain gage information.poisson ratio") — tooltip-only
370
+ # detail beside the terse leaf ``display_name`` the glyph shows. None for a
371
+ # top-level or leaf-only field. Set at the ``stamp_nmux_lane_names`` seam.
372
+ field_path: str | None = None
325
373
  lv_type: LVType | None = None
326
374
  var_name: str | None = None # set during codegen
327
375
  nmux_role: str | None = None # "agg" or "list"
@@ -33,6 +33,7 @@ NODE_CLASS_FEEDBACK_MASTER = "hiddenFBNode"
33
33
  NODE_CLASS_FEEDBACK_SLAVE = "slaveFBInputNode"
34
34
  NODE_CLASS_PROP_NODE = "propNode"
35
35
  NODE_CLASS_INVOKE_NODE = "invokeNode"
36
+ NODE_CLASS_EVENT_REG = "eventRegNode" # Register For Events (task #56)
36
37
  NODE_CLASS_CPD_ARITH = "cpdArith" # Compound arithmetic (e.g., Or of multiple booleans)
37
38
  NODE_CLASS_ARRAY_BUILD = "aBuild" # Array builder node
38
39
  NODE_CLASS_ARRAY_INIT = "aInit" # Initialize Array (element + sizes -> array)
@@ -103,6 +104,7 @@ OPERATION_NODE_CLASSES = (
103
104
  NODE_CLASS_EVENT_STRUCT,
104
105
  NODE_CLASS_PROP_NODE,
105
106
  NODE_CLASS_INVOKE_NODE,
107
+ NODE_CLASS_EVENT_REG,
106
108
  NODE_CLASS_CPD_ARITH,
107
109
  NODE_CLASS_ARRAY_BUILD,
108
110
  NODE_CLASS_ARRAY_INIT,
@@ -0,0 +1,103 @@
1
+ """Embedded-picture / decoration resource resolution — LabVIEW's PICC
2
+ (picture) and DSIM (dynamic-size image) resource sections.
3
+
4
+ A heap element's ``<ImageResID>`` (when positive) or ``<ImageInternalsResID>``
5
+ names one of these sections by index. The VI's top-level ``<stem>.xml`` (the
6
+ sibling of ``<stem>_BDHb.xml`` extracted by pylabview) records the index -> file
7
+ mapping::
8
+
9
+ <PICC><Section Index="2" File="..._PICC2.bin"/><Section Index="3" .../></PICC>
10
+ <DSIM><Section Index="4" File="..._DSIM.bin"/></DSIM>
11
+
12
+ This module resolves that map (``resource_sections``/``resources_for_heap``),
13
+ carves the embedded PNG out of a DSIM section's raw bytes (``carve_png``), and
14
+ decodes a PICC section's absolute endpoint list (``decode_picc_points``). See
15
+ ``docs/_internal/design/labview-binary-format.md`` for the verified byte layout
16
+ of both sections (issue #82).
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import struct
22
+ import xml.etree.ElementTree as ET
23
+ from pathlib import Path
24
+
25
+ Point = tuple[float, float]
26
+
27
+ _PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n"
28
+
29
+ # The two resource-section kinds a decoration's ImageResID/ImageInternalsResID
30
+ # can name — a picture (DSIM) or a picture-internals blob (PICC). Any other
31
+ # top-level block in the VI's resource XML is unrelated and ignored.
32
+ _SECTION_BLOCKS = ("PICC", "DSIM")
33
+
34
+
35
+ def resource_sections(main_xml: Path) -> dict[int, Path]:
36
+ """Section Index -> resource file, from a VI's top-level ``<stem>.xml``.
37
+
38
+ Missing file or malformed XML -> ``{}`` (no resources), never a crash --
39
+ most VIs have no picture/decoration content at all.
40
+ """
41
+ try:
42
+ root = ET.parse(main_xml).getroot()
43
+ except (OSError, ET.ParseError):
44
+ return {}
45
+ sections: dict[int, Path] = {}
46
+ for block_tag in _SECTION_BLOCKS:
47
+ block = root.find(block_tag)
48
+ if block is None:
49
+ continue
50
+ for sec in block.findall("Section"):
51
+ idx, file_name = sec.get("Index"), sec.get("File")
52
+ if idx is None or not file_name:
53
+ continue
54
+ try:
55
+ sections[int(idx)] = main_xml.parent / file_name
56
+ except ValueError:
57
+ continue
58
+ return sections
59
+
60
+
61
+ def resources_for_heap(bd_xml: Path) -> dict[int, Path]:
62
+ """The resource-section map for a ``_BDHb.xml`` heap path's sibling
63
+ ``<stem>.xml`` (same naming convention as ``layout._icon_for_heap``): ``{}``
64
+ when that file doesn't exist (the common case)."""
65
+ main_xml = bd_xml.parent / f"{bd_xml.stem.replace('_BDHb', '')}.xml"
66
+ return resource_sections(main_xml) if main_xml.exists() else {}
67
+
68
+
69
+ def carve_png(data: bytes) -> bytes | None:
70
+ """The first embedded PNG in a DSIM section's raw bytes, or ``None``.
71
+
72
+ A DSIM section stores the picture behind a small binary preamble (size/
73
+ scaling fields LabVIEW itself uses) — the PNG payload starts at its own
74
+ signature and ends at the first ``IEND`` chunk's CRC (+8 bytes past the
75
+ ``IEND`` tag). Verified on the issue #82 repro: the PNG at offset 46,
76
+ sliced through ``IEND``, reproduces the embedded picture exactly."""
77
+ start = data.find(_PNG_SIGNATURE)
78
+ if start < 0:
79
+ return None
80
+ iend = data.find(b"IEND", start)
81
+ if iend < 0:
82
+ return None
83
+ return data[start : iend + 8]
84
+
85
+
86
+ def decode_picc_points(data: bytes) -> list[Point]:
87
+ """Absolute ``(x, y)`` endpoints from a PICC section's raw bytes.
88
+
89
+ Layout (verified on the issue #82 repro's PICC2/PICC3): a 4-byte header
90
+ (purpose not yet decoded — see labview-binary-format.md) followed by
91
+ ``(len(data) - 4) / 4`` points, each two big-endian signed int16 in
92
+ ``(y, x)`` order. These are the SAME absolute LabVIEW-pixel frame as a heap
93
+ element's own ``<bounds>`` — callers apply the identical walk offset.
94
+ Malformed data (not a whole number of points after the header) -> ``[]``.
95
+ """
96
+ body = data[4:]
97
+ if len(body) < 4 or len(body) % 4 != 0:
98
+ return []
99
+ points: list[Point] = []
100
+ for i in range(0, len(body), 4):
101
+ y, x = struct.unpack_from(">hh", body, i)
102
+ points.append((float(x), float(y)))
103
+ return points