lvkit 0.8.2__tar.gz → 0.8.4__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 (518) hide show
  1. {lvkit-0.8.2 → lvkit-0.8.4}/PKG-INFO +1 -1
  2. {lvkit-0.8.2 → lvkit-0.8.4}/pyproject.toml +1 -1
  3. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/__init__.py +1 -1
  4. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/cache_paths.py +49 -10
  5. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/extractor.py +29 -15
  6. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/builders/operations.py +6 -2
  7. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/loading.py +173 -21
  8. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/models.py +9 -8
  9. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/parallel_parse.py +15 -6
  10. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/output_cache.py +38 -15
  11. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/metadata.py +26 -9
  12. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/node_types.py +30 -24
  13. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/vi.py +65 -22
  14. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/base.py +88 -7
  15. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/invoke_node.py +20 -19
  16. lvkit-0.8.4/src/lvkit/render/glyphs/nodes/property_node.py +78 -0
  17. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/nodes.py +111 -32
  18. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/scene.py +15 -6
  19. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/style.py +26 -2
  20. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/theme_web.py +1 -0
  21. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/structure.py +61 -9
  22. {lvkit-0.8.2 → lvkit-0.8.4}/tests/conftest.py +24 -0
  23. lvkit-0.8.4/tests/test_cache_path_bound.py +331 -0
  24. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_class_parent_linkinfo.py +22 -0
  25. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_class_wire_appearance.py +54 -0
  26. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_constant_decoding.py +45 -0
  27. lvkit-0.8.4/tests/test_decode_element_perf.py +107 -0
  28. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_extraction_cache.py +28 -9
  29. lvkit-0.8.4/tests/test_lvlib_nonvi_member.py +53 -0
  30. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_output_cache.py +10 -6
  31. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_parser.py +144 -0
  32. lvkit-0.8.4/tests/test_python_structure_plan.py +55 -0
  33. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_render.py +316 -12
  34. lvkit-0.8.2/src/lvkit/render/glyphs/nodes/property_node.py +0 -115
  35. {lvkit-0.8.2 → lvkit-0.8.4}/.gitignore +0 -0
  36. {lvkit-0.8.2 → lvkit-0.8.4}/.pre-commit-config.yaml +0 -0
  37. {lvkit-0.8.2 → lvkit-0.8.4}/LICENSE +0 -0
  38. {lvkit-0.8.2 → lvkit-0.8.4}/NOTICE +0 -0
  39. {lvkit-0.8.2 → lvkit-0.8.4}/README.md +0 -0
  40. {lvkit-0.8.2 → lvkit-0.8.4}/deploy/cloudrun/README.md +0 -0
  41. {lvkit-0.8.2 → lvkit-0.8.4}/docs/_internal/xml-schema/README.md +0 -0
  42. {lvkit-0.8.2 → lvkit-0.8.4}/editors/vscode/LICENSE +0 -0
  43. {lvkit-0.8.2 → lvkit-0.8.4}/editors/vscode/README.md +0 -0
  44. {lvkit-0.8.2 → lvkit-0.8.4}/mcpb/README.md +0 -0
  45. {lvkit-0.8.2 → lvkit-0.8.4}/plugin/README.md +0 -0
  46. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/audit_primitive_consistency.py +0 -0
  47. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/audit_terminal_order.py +0 -0
  48. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/audit_unresolved.py +0 -0
  49. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/build_example_pages.sh +0 -0
  50. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/build_hero.py +0 -0
  51. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/build_ni_function_catalog.py +0 -0
  52. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/connector_geometry_audit.py +0 -0
  53. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/dump_primitive_context.py +0 -0
  54. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/extract_corpus.py +0 -0
  55. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/gen_semantics_probe.py +0 -0
  56. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/generate_docs.py +0 -0
  57. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/generate_driver_data.py +0 -0
  58. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/generate_python.py +0 -0
  59. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/import_nodes_primitives.py +0 -0
  60. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/list_unknown_primitives.py +0 -0
  61. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/populate_vilib.py +0 -0
  62. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/pull_samples.sh +0 -0
  63. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/recategorize_vilib.py +0 -0
  64. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/render_gallery.py +0 -0
  65. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/reproduce_openg_corpus.py +0 -0
  66. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/study_unwired_direction.py +0 -0
  67. {lvkit-0.8.2 → lvkit-0.8.4}/scripts/wire_decode_probe.py +0 -0
  68. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/__main__.py +0 -0
  69. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/_data.py +0 -0
  70. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/_pylabview_patches.py +0 -0
  71. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/cli.py +0 -0
  72. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/README.md +0 -0
  73. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/__init__.py +0 -0
  74. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/ast_optimizer.py +0 -0
  75. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/ast_utils.py +0 -0
  76. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/builder.py +0 -0
  77. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/__init__.py +0 -0
  78. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/_shared.py +0 -0
  79. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/config.py +0 -0
  80. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/core.py +0 -0
  81. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/init_builder.py +0 -0
  82. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/methods.py +0 -0
  83. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/naming.py +0 -0
  84. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/properties.py +0 -0
  85. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/terminals.py +0 -0
  86. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/condition_builder.py +0 -0
  87. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/context.py +0 -0
  88. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/dataflow.py +0 -0
  89. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/elementwise.py +0 -0
  90. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/error_handler.py +0 -0
  91. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/expressions.py +0 -0
  92. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/fragment.py +0 -0
  93. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/function.py +0 -0
  94. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/imports.py +0 -0
  95. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/__init__.py +0 -0
  96. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/base.py +0 -0
  97. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/case.py +0 -0
  98. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/compound.py +0 -0
  99. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/constant.py +0 -0
  100. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/event.py +0 -0
  101. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/first_call.py +0 -0
  102. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/formula.py +0 -0
  103. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/in_place.py +0 -0
  104. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/invoke_node.py +0 -0
  105. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/loop.py +0 -0
  106. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/nmux.py +0 -0
  107. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/primitive.py +0 -0
  108. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/printf.py +0 -0
  109. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/property_node.py +0 -0
  110. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/queue_ops.py +0 -0
  111. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/sequence.py +0 -0
  112. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/nodes/subvi.py +0 -0
  113. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/stubs.py +0 -0
  114. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/codegen/unresolved.py +0 -0
  115. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/connector_geometry.py +0 -0
  116. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/connector_pane_geometry.py +0 -0
  117. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/builtin_types.json +0 -0
  118. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/connector_pane_patterns.json +0 -0
  119. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/_index.json +0 -0
  120. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/daqmx.json +0 -0
  121. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/nidcpower.json +0 -0
  122. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/nidigital.json +0 -0
  123. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/nidmm.json +0 -0
  124. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/nifgen.json +0 -0
  125. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/niscope.json +0 -0
  126. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/niswitch.json +0 -0
  127. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/serial.json +0 -0
  128. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/drivers/visa.json +0 -0
  129. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/labview_error_codes.json +0 -0
  130. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/measure_data.json +0 -0
  131. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/openg/_index.json +0 -0
  132. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/openg/array.json +0 -0
  133. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/openg/file.json +0 -0
  134. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/openg/string.json +0 -0
  135. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/openg/time.json +0 -0
  136. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/openg/variant.json +0 -0
  137. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/primitives.json +0 -0
  138. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/_index.json +0 -0
  139. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/_pending_terminals.json +0 -0
  140. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/_types.json +0 -0
  141. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/addons.json +0 -0
  142. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/application-control.json +0 -0
  143. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/array.json +0 -0
  144. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/boolean.json +0 -0
  145. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/cluster-class-variant.json +0 -0
  146. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/collection.json +0 -0
  147. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/comparison.json +0 -0
  148. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/connectivity.json +0 -0
  149. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/control-simulation.json +0 -0
  150. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/data-communication.json +0 -0
  151. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/dialog-user-interface.json +0 -0
  152. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/express.json +0 -0
  153. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/file-io.json +0 -0
  154. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/graphics-sound.json +0 -0
  155. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/instrument-io.json +0 -0
  156. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/mathematics.json +0 -0
  157. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/measurement-io.json +0 -0
  158. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/numeric.json +0 -0
  159. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/report-generation.json +0 -0
  160. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/signal-processing.json +0 -0
  161. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/string.json +0 -0
  162. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/structures.json +0 -0
  163. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/synchronization.json +0 -0
  164. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/timing.json +0 -0
  165. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/data/vilib/waveform.json +0 -0
  166. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/__init__.py +0 -0
  167. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/generate.py +0 -0
  168. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/html_generator/__init__.py +0 -0
  169. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/html_generator/assets.py +0 -0
  170. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/html_generator/class_page.py +0 -0
  171. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/html_generator/core.py +0 -0
  172. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/html_generator/index_page.py +0 -0
  173. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/html_generator/naming.py +0 -0
  174. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/html_generator/vi_page.py +0 -0
  175. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/template.css +0 -0
  176. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/docs/utils.py +0 -0
  177. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/flattened_typedesc.py +0 -0
  178. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/formula/__init__.py +0 -0
  179. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/formula/cparser.py +0 -0
  180. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/formula/emit.py +0 -0
  181. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/formula/lexer.py +0 -0
  182. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/formula/nodes.py +0 -0
  183. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/__init__.py +0 -0
  184. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/analysis.py +0 -0
  185. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/builders/__init__.py +0 -0
  186. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/builders/context.py +0 -0
  187. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/builders/refs.py +0 -0
  188. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/builders/structures.py +0 -0
  189. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/construction.py +0 -0
  190. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/core.py +0 -0
  191. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/describe.py +0 -0
  192. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/diff.py +0 -0
  193. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/interface_order.py +0 -0
  194. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/lvnet_grammar.py +0 -0
  195. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/lvnet_parse.py +0 -0
  196. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/lvnet_reconstruct.py +0 -0
  197. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/netlist.py +0 -0
  198. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/netlist_build.py +0 -0
  199. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/netlist_diff_helpers.py +0 -0
  200. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/netlist_json.py +0 -0
  201. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/netlist_models.py +0 -0
  202. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/op_walk.py +0 -0
  203. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/operations.py +0 -0
  204. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/queries.py +0 -0
  205. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/graph/render_lvnet.py +0 -0
  206. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/index/__init__.py +0 -0
  207. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/index/build.py +0 -0
  208. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/index/model.py +0 -0
  209. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/index/project.py +0 -0
  210. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/index/query.py +0 -0
  211. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/index/sql.py +0 -0
  212. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/index/store.py +0 -0
  213. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/labview_error.py +0 -0
  214. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/labview_error_codes.py +0 -0
  215. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/labview_queue.py +0 -0
  216. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/load_mode.py +0 -0
  217. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/lv_detect.py +0 -0
  218. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/__init__.py +0 -0
  219. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/schemas.py +0 -0
  220. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/__init__.py +0 -0
  221. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/__main__.py +0 -0
  222. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/_compat.py +0 -0
  223. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/app.py +0 -0
  224. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/index_tools.py +0 -0
  225. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/resolvers.py +0 -0
  226. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/roots.py +0 -0
  227. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/mcp/server/vi_tools.py +0 -0
  228. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/measure_data.py +0 -0
  229. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/models.py +0 -0
  230. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/num_format.py +0 -0
  231. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/__init__.py +0 -0
  232. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/conp_types.py +0 -0
  233. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/constants.py +0 -0
  234. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/defaults.py +0 -0
  235. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/flags.py +0 -0
  236. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/fp_heap_type.py +0 -0
  237. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/front_panel.py +0 -0
  238. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/image_resources.py +0 -0
  239. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/layout.py +0 -0
  240. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/models.py +0 -0
  241. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/naming.py +0 -0
  242. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/__init__.py +0 -0
  243. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/base.py +0 -0
  244. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/case.py +0 -0
  245. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/constant.py +0 -0
  246. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/decompose.py +0 -0
  247. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/disable.py +0 -0
  248. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/event.py +0 -0
  249. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/free_label.py +0 -0
  250. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/loop.py +0 -0
  251. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/nodes/sequence.py +0 -0
  252. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/type_mapping.py +0 -0
  253. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/type_resolution.py +0 -0
  254. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/utils.py +0 -0
  255. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/parser/wire_table.py +0 -0
  256. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/pipeline.py +0 -0
  257. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/primitive_resolver/__init__.py +0 -0
  258. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/primitive_resolver/exceptions.py +0 -0
  259. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/primitive_resolver/models.py +0 -0
  260. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/primitive_resolver/resolver.py +0 -0
  261. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/project_store.py +0 -0
  262. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/py.typed +0 -0
  263. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/ARCHITECTURE.md +0 -0
  264. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/__init__.py +0 -0
  265. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/backend.py +0 -0
  266. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/composite.py +0 -0
  267. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/connector_pane.py +0 -0
  268. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/connector_pane_panel.py +0 -0
  269. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/diff_viewer.py +0 -0
  270. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/draw.py +0 -0
  271. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyph.py +0 -0
  272. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/__init__.py +0 -0
  273. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/__init__.py +0 -0
  274. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/arrow.py +0 -0
  275. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/base.py +0 -0
  276. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/factory.py +0 -0
  277. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/fallback.py +0 -0
  278. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/frame.py +0 -0
  279. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/line.py +0 -0
  280. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/picture.py +0 -0
  281. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/__init__.py +0 -0
  282. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/arith.py +0 -0
  283. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_build.py +0 -0
  284. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_constant.py +0 -0
  285. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_reverse.py +0 -0
  286. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_search.py +0 -0
  287. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_size.py +0 -0
  288. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_sort.py +0 -0
  289. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_split.py +0 -0
  290. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/boolean_constant.py +0 -0
  291. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/boolean_gate.py +0 -0
  292. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/bundle.py +0 -0
  293. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/bundle_by_name.py +0 -0
  294. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/centered_svg.py +0 -0
  295. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/class_glyph.py +0 -0
  296. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/cluster_constant.py +0 -0
  297. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/compound_arith.py +0 -0
  298. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/constant.py +0 -0
  299. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/control_ref_const.py +0 -0
  300. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/convert.py +0 -0
  301. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/error_cluster.py +0 -0
  302. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/event_data.py +0 -0
  303. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/event_reg_node.py +0 -0
  304. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/formula_node.py +0 -0
  305. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/icon_image.py +0 -0
  306. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/in_place_element.py +0 -0
  307. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/inline_svg.py +0 -0
  308. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/label.py +0 -0
  309. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/local_variable.py +0 -0
  310. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/path_glyph.py +0 -0
  311. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/refnum_glyph.py +0 -0
  312. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/unbundle.py +0 -0
  313. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/variant.py +0 -0
  314. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/wrapped_box.py +0 -0
  315. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/__init__.py +0 -0
  316. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/base.py +0 -0
  317. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/case.py +0 -0
  318. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/disable.py +0 -0
  319. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/event.py +0 -0
  320. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/factory.py +0 -0
  321. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/flat_sequence.py +0 -0
  322. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/for_loop.py +0 -0
  323. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/generic.py +0 -0
  324. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/in_place.py +0 -0
  325. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/selectable.py +0 -0
  326. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/stacked_sequence.py +0 -0
  327. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/while_loop.py +0 -0
  328. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/__init__.py +0 -0
  329. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/autoindex.py +0 -0
  330. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/base.py +0 -0
  331. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/concatenate.py +0 -0
  332. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/conditional.py +0 -0
  333. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/event_dyn.py +0 -0
  334. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/event_timeout.py +0 -0
  335. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/factory.py +0 -0
  336. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/generic.py +0 -0
  337. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/loop_count.py +0 -0
  338. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/selector.py +0 -0
  339. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/shift_register.py +0 -0
  340. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/tunnel.py +0 -0
  341. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/help_tip.py +0 -0
  342. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/icons.py +0 -0
  343. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/lane_pass.py +0 -0
  344. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/properties_panel.py +0 -0
  345. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/render_viewer.py +0 -0
  346. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/templates/diff_viewer.html +0 -0
  347. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/templates/render_viewer.html +0 -0
  348. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/theme_control.py +0 -0
  349. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/render/wire_router.py +0 -0
  350. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/runtime/__init__.py +0 -0
  351. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/runtime/lv.py +0 -0
  352. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/__init__.py +0 -0
  353. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit/SKILL.md +0 -0
  354. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-convert/SKILL.md +0 -0
  355. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-describe/SKILL.md +0 -0
  356. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-document/SKILL.md +0 -0
  357. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-query/SKILL.md +0 -0
  358. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-resolve/SKILL.md +0 -0
  359. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-review/SKILL.md +0 -0
  360. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/terminal_collector.py +0 -0
  361. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/text_encoding.py +0 -0
  362. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/tools/__init__.py +0 -0
  363. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/tools/connector_geometry_profile.py +0 -0
  364. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/type_defaults.py +0 -0
  365. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/unresolved.py +0 -0
  366. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vi_diff.py +0 -0
  367. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/__init__.py +0 -0
  368. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/exceptions.py +0 -0
  369. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/loader.py +0 -0
  370. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/lookup.py +0 -0
  371. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/models.py +0 -0
  372. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/naming.py +0 -0
  373. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/resolver.py +0 -0
  374. {lvkit-0.8.2 → lvkit-0.8.4}/src/lvkit/vilib_resolver/variants.py +0 -0
  375. {lvkit-0.8.2 → lvkit-0.8.4}/tests/__init__.py +0 -0
  376. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/PROVENANCE.md +0 -0
  377. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib1/Class/Class.lvclass +0 -0
  378. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib1/Class/Do.vi +0 -0
  379. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib1/Lib1.lvlib +0 -0
  380. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Class.lvclass +0 -0
  381. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Do.vi +0 -0
  382. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Test.vi +0 -0
  383. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Lib2.lvlib +0 -0
  384. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Test LVKit.aliases +0 -0
  385. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Test LVKit.lvlps +0 -0
  386. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Test LVKit.lvproj +0 -0
  387. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/30/PROVENANCE.md +0 -0
  388. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/30/visible-frame-case-sequence.vi +0 -0
  389. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/30/visible-frame-conditional-disable.vi +0 -0
  390. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/31/PROVENANCE.md +0 -0
  391. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/31/disable-structure-frame-names.vi +0 -0
  392. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/32/PROVENANCE.md +0 -0
  393. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/32/comments-and-decorations.vi +0 -0
  394. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/33/PROVENANCE.md +0 -0
  395. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/33/coercion-dot-consistency.vi +0 -0
  396. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/34/PROVENANCE.md +0 -0
  397. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/34/hidden-iteration-terminal.vi +0 -0
  398. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/35/PROVENANCE.md +0 -0
  399. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/35/objects-hidden-by-structures.vi +0 -0
  400. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/36/PROVENANCE.md +0 -0
  401. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/36/bundle-unbundle-names.vi +0 -0
  402. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/37/PROVENANCE.md +0 -0
  403. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/37/structure-tunnel-wire-bends.vi +0 -0
  404. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/38/PROVENANCE.md +0 -0
  405. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/38/auto-concatenating-tunnel.vi +0 -0
  406. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/39/PROVENANCE.md +0 -0
  407. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/39/zorder-not-respected.vi +0 -0
  408. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/82/Pictures And Decorations.vi +0 -0
  409. {lvkit-0.8.2 → lvkit-0.8.4}/tests/corpus/issues/README.md +0 -0
  410. {lvkit-0.8.2 → lvkit-0.8.4}/tests/helpers.py +0 -0
  411. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_array_ops_codegen.py +0 -0
  412. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_ast_builder.py +0 -0
  413. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_ast_optimizer.py +0 -0
  414. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_case_codegen.py +0 -0
  415. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_case_parser.py +0 -0
  416. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_class_field_walkup.py +0 -0
  417. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_class_properties.py +0 -0
  418. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_cli.py +0 -0
  419. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_cli_cache.py +0 -0
  420. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_cli_describe_lvnet.py +0 -0
  421. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_cli_graph_ops.py +0 -0
  422. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_cli_query.py +0 -0
  423. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_cluster_wire_color.py +0 -0
  424. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_codegen_context.py +0 -0
  425. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_compound_codegen.py +0 -0
  426. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_condition_builder.py +0 -0
  427. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_connector_geometry.py +0 -0
  428. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_connector_pane_label_recovery.py +0 -0
  429. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_connector_pane_patterns.py +0 -0
  430. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_connector_pane_render.py +0 -0
  431. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_conp_types.py +0 -0
  432. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_dependency_path_refs.py +0 -0
  433. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_determinism.py +0 -0
  434. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_diff.py +0 -0
  435. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_diff_properties.py +0 -0
  436. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_diff_viewer.py +0 -0
  437. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_disable_graph.py +0 -0
  438. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_disable_parser.py +0 -0
  439. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_docs_class_hierarchy.py +0 -0
  440. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_docs_render.py +0 -0
  441. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_driver_codegen.py +0 -0
  442. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_dynamic_dispatch.py +0 -0
  443. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_e2e_codegen.py +0 -0
  444. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_elementwise.py +0 -0
  445. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_error_codegen.py +0 -0
  446. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_error_handling.py +0 -0
  447. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_error_terminal_label_fallback.py +0 -0
  448. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_event_codegen.py +0 -0
  449. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_event_parser.py +0 -0
  450. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_extractor_concurrency.py +0 -0
  451. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_extractor_long_path.py +0 -0
  452. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_first_call_codegen.py +0 -0
  453. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_formula_codegen.py +0 -0
  454. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_formula_runtime.py +0 -0
  455. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_formula_semantics.py +0 -0
  456. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_formula_transpile.py +0 -0
  457. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_fp_heap_type.py +0 -0
  458. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_frame_attribution.py +0 -0
  459. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_frame_zplane.py +0 -0
  460. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_glyphs.py +0 -0
  461. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_graceful_degradation.py +0 -0
  462. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_help_tip.py +0 -0
  463. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_import_startup.py +0 -0
  464. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_in_place_codegen.py +0 -0
  465. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_index.py +0 -0
  466. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_index_sql.py +0 -0
  467. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_index_warm_no_downgrade.py +0 -0
  468. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_interface_order.py +0 -0
  469. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_issue_corpus.py +0 -0
  470. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_label_extraction.py +0 -0
  471. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_labview_queue.py +0 -0
  472. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_livi_vipi.py +0 -0
  473. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_load_mode.py +0 -0
  474. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_load_upgrade.py +0 -0
  475. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_loop_codegen.py +0 -0
  476. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_lv_detect.py +0 -0
  477. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_lvnet_identity.py +0 -0
  478. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_lvnet_reconstruct.py +0 -0
  479. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_lvnet_roundtrip.py +0 -0
  480. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_lvpy.py +0 -0
  481. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_mcp_cache.py +0 -0
  482. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_mcp_evals.py +0 -0
  483. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_mcp_read_vi_lvnet.py +0 -0
  484. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_mcp_roots.py +0 -0
  485. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_naming.py +0 -0
  486. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_netlist_json.py +0 -0
  487. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_new_codegen.py +0 -0
  488. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_node_properties.py +0 -0
  489. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_parallel_codegen.py +0 -0
  490. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_parallel_parse.py +0 -0
  491. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_parser_regression.py +0 -0
  492. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_primitive_name_uniqueness.py +0 -0
  493. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_primitive_positional_order.py +0 -0
  494. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_primitive_resolutions.py +0 -0
  495. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_progressive_index.py +0 -0
  496. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_progressive_warm.py +0 -0
  497. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_project_store.py +0 -0
  498. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_queue_codegen.py +0 -0
  499. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_render_emission_order.py +0 -0
  500. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_render_lvnet.py +0 -0
  501. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_render_title_identity.py +0 -0
  502. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_render_viewer.py +0 -0
  503. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_sequence.py +0 -0
  504. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_soft_codegen.py +0 -0
  505. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_structure_lvproj.py +0 -0
  506. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_subvi_nav.py +0 -0
  507. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_text_encoding.py +0 -0
  508. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_type_driven_fixes.py +0 -0
  509. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_type_fields.py +0 -0
  510. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_type_loading.py +0 -0
  511. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_type_mapping.py +0 -0
  512. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_unknown_nodes.py +0 -0
  513. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_unresolved.py +0 -0
  514. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_vi_graph.py +0 -0
  515. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_vi_properties.py +0 -0
  516. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_viewer_properties.py +0 -0
  517. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_vilib_docurls.py +0 -0
  518. {lvkit-0.8.2 → lvkit-0.8.4}/tests/test_web_progressive_staging.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: lvkit
3
- Version: 0.8.2
3
+ Version: 0.8.4
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.2"
7
+ version = "0.8.4"
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.2"
7
+ __version__ = "0.8.4"
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
@@ -111,6 +111,35 @@ def _slug(path: Path) -> str:
111
111
  return f"{tail}-{h}"
112
112
 
113
113
 
114
+ # The fixed short stem every MANAGED-cache artifact (extract/render/diff) uses
115
+ # instead of the real VI's filename stem — the second Windows MAX_PATH axis
116
+ # alongside the bounded ``vi-<hash>`` slot below. Owned by this module (the
117
+ # single source of the cache-layout policy); ``extractor.py`` and
118
+ # ``output_cache.py`` import it rather than repeating the literal.
119
+ MANAGED_ARTIFACT_STEM = "vi"
120
+
121
+
122
+ def _vi_slot(rel: Path) -> str:
123
+ """A per-VI cache dir name that is ALWAYS bounded, whatever the source tree's
124
+ depth: ``vi-`` + 16 hex of a sha256 of the owner-relative path.
125
+
126
+ Owned namespaces used to hang a VI's cache under ``<rel.parent>`` — the full
127
+ source-directory hierarchy reproduced beneath the cache root. A deep repo (or
128
+ a long VI filename) then pushed the final cache path past Windows' MAX_PATH
129
+ even with a short ``LVKIT_CACHE_DIR``, because BOTH the depth and the source
130
+ stem were unbounded inputs (the failure this replaces). Collapsing the whole
131
+ owner-relative path to one fixed-width hash segment removes the depth axis;
132
+ fixed short artifact names inside the slot remove the stem axis. The path is
133
+ keyed on the FULL ``rel`` (parent + filename), so every source VI maps to its
134
+ own slot and sibling VIs never collide. The real source path is NOT lost — it
135
+ is recorded as the ``source`` field of each slot's ``.meta.json`` sidecar
136
+ (see ``extractor._write_cache_meta`` / ``output_cache._write``). The
137
+ separators are normalized to ``/`` so the same VI hashes identically
138
+ regardless of how its path was spelled on this platform."""
139
+ key = rel.as_posix()
140
+ return "vi-" + hashlib.sha256(key.encode("utf-8")).hexdigest()[:16]
141
+
142
+
114
143
  def kind_fingerprint(kind: str) -> str:
115
144
  """The 8-hex build-compatibility tag stamped into a cache path for ``kind``.
116
145
 
@@ -215,14 +244,20 @@ def classify(vi_path: Path, kind: str) -> tuple[Path, str, str]:
215
244
  """Map ``vi_path`` to ``(cache_dir, source_label, namespace)`` for one
216
245
  artifact ``kind`` (``"extract"`` | ``"render"`` | ``"diff"``).
217
246
 
218
- ``cache_dir`` is ``<cache>/<ns>/<slug>/<kind>/<fp>/<rel-parent>`` — project-
247
+ ``cache_dir`` is ``<cache>/<ns>/<slug>/<kind>/<fp>/vi-<hash>`` — project-
219
248
  first: the VI's identity (namespace + slug) is named ONCE and the ``kind``
220
- hangs off it, so one project's whole cache is a single subtree and sibling VIs
221
- of the same kind + build share a dir. ``<fp>`` is the per-kind build tag
222
- (:func:`kind_fingerprint`) so two incompatible lvkit builds get separate slots
223
- instead of clobbering each other. ``namespace`` is ``"projects"``,
249
+ hangs off it, so one project's whole cache is a single subtree. ``<fp>`` is
250
+ the per-kind build tag (:func:`kind_fingerprint`) so two incompatible lvkit
251
+ builds get separate slots instead of clobbering each other. ``vi-<hash>``
252
+ (:func:`_vi_slot`) is a bounded per-VI slot standing in for the owner-relative
253
+ directory hierarchy, so an arbitrarily deep source tree can never push the
254
+ cache path past Windows' MAX_PATH; the artifact names inside it are fixed and
255
+ short (``vi_BDHb.xml`` / ``vi.<ext>``) for the same reason. ``source_label``
256
+ stays the REAL owner-relative path (``str(rel)``) so the true source is
257
+ recorded in each slot's ``.meta.json``. ``namespace`` is ``"projects"``,
224
258
  ``"shared"``, or ``"adhoc"`` — callers path-address the first two and
225
- content-address ``adhoc`` (its paths never repeat).
259
+ content-address ``adhoc`` (its paths never repeat; its dir is already a single
260
+ bounded ``_slug`` segment).
226
261
  """
227
262
  resolved = vi_path.resolve()
228
263
  cache = global_cache_root()
@@ -237,7 +272,7 @@ def classify(vi_path: Path, kind: str) -> tuple[Path, str, str]:
237
272
  rel = _rel_under(resolved, vilib)
238
273
  if rel is not None:
239
274
  _note_owner(vilib)
240
- d = cache / "shared" / "vilib" / _slug(vilib) / kind / fp / rel.parent
275
+ d = cache / "shared" / "vilib" / _slug(vilib) / kind / fp / _vi_slot(rel)
241
276
  return d, str(rel), "shared"
242
277
 
243
278
  userlib = _userlib_root
@@ -245,7 +280,8 @@ def classify(vi_path: Path, kind: str) -> tuple[Path, str, str]:
245
280
  rel = _rel_under(resolved, userlib)
246
281
  if rel is not None:
247
282
  _note_owner(userlib)
248
- d = cache / "shared" / "userlib" / _slug(userlib) / kind / fp / rel.parent
283
+ slug = _slug(userlib)
284
+ d = cache / "shared" / "userlib" / slug / kind / fp / _vi_slot(rel)
249
285
  return d, str(rel), "shared"
250
286
 
251
287
  project = _project_root_for(resolved)
@@ -253,7 +289,7 @@ def classify(vi_path: Path, kind: str) -> tuple[Path, str, str]:
253
289
  proj_abs = project.resolve()
254
290
  rel = resolved.relative_to(proj_abs)
255
291
  _note_owner(proj_abs)
256
- d = cache / "projects" / _slug(proj_abs) / kind / fp / rel.parent
292
+ d = cache / "projects" / _slug(proj_abs) / kind / fp / _vi_slot(rel)
257
293
  return d, str(rel), "projects"
258
294
 
259
295
  # adhoc has NO owner (not a project, not a library) -> no identity slug to
@@ -474,7 +510,10 @@ def write_meta(vi_path: Path, meta_path: Path, **extra: object) -> None:
474
510
  # source/fingerprint change — that is handled by the <fp> path level). A mismatch
475
511
  # triggers a one-time drop of the derived namespaces in cleanup_legacy_cache.
476
512
  # "2": project-first with a per-kind <fp> level and <tail>-<hash8> slugs.
477
- _LAYOUT_VERSION = "2"
513
+ # "3": owned VIs sit in a bounded per-VI ``vi-<hash>`` slot with fixed short
514
+ # artifact names (was the reproduced ``<rel.parent>`` hierarchy + source
515
+ # stem), so a deep source tree can't overflow Windows MAX_PATH.
516
+ _LAYOUT_VERSION = "3"
478
517
 
479
518
 
480
519
  def cleanup_legacy_cache() -> None:
@@ -34,6 +34,7 @@ install_pylabview_patches()
34
34
  # pylabview). Re-exported here so long-standing callers of ``extractor.X`` (e.g.
35
35
  # ``graph.core`` -> ``extractor.set_extraction_roots``) keep working unchanged.
36
36
  from lvkit.cache_paths import ( # noqa: E402
37
+ MANAGED_ARTIFACT_STEM,
37
38
  _slug,
38
39
  classify,
39
40
  cleanup_legacy_cache,
@@ -179,7 +180,7 @@ def _make_read_po(**overrides: object) -> argparse.Namespace:
179
180
  return argparse.Namespace(**opts)
180
181
 
181
182
 
182
- def _extract_in_process(vi_path: Path, output_dir: Path, vi_stem: str) -> None:
183
+ def _extract_in_process(vi_path: Path, output_dir: Path, artifact_stem: str) -> None:
183
184
  """Extract a VI to XML in-process, matching ``readRSRC -i <vi> -x``.
184
185
 
185
186
  pylabview places each block's sidecar XML (``_BDHb.xml`` etc.) in
@@ -190,17 +191,21 @@ def _extract_in_process(vi_path: Path, output_dir: Path, vi_stem: str) -> None:
190
191
  request concurrency. This avoids the per-call interpreter boot + pylabview
191
192
  re-import that the subprocess path pays on every extraction.
192
193
 
194
+ ``artifact_stem`` names the produced files — the caller's real VI stem for a
195
+ caller-owned ``output_dir``, or the fixed ``MANAGED_ARTIFACT_STEM`` in the
196
+ managed cache; it is NOT necessarily ``vi_path.stem``.
197
+
193
198
  Mirrors the option set that ``readRSRC.main()`` builds for the ``-x``
194
199
  (extract) subcommand via argparse.
195
200
  """
196
- xml_path = output_dir / f"{vi_stem}.xml"
201
+ xml_path = output_dir / f"{artifact_stem}.xml"
197
202
  po = _make_read_po(
198
203
  rsrc=str(vi_path),
199
204
  xml=str(xml_path),
200
205
  textcp="mac_roman",
201
206
  raw_connectors=False,
202
207
  keep_names=False,
203
- filebase=vi_stem,
208
+ filebase=artifact_stem,
204
209
  list=False,
205
210
  dump=False,
206
211
  extract=True,
@@ -214,8 +219,8 @@ def _extract_in_process(vi_path: Path, output_dir: Path, vi_stem: str) -> None:
214
219
  with open(xml_path, "wb") as xml_fh:
215
220
  tree.write(xml_fh, encoding="utf-8", xml_declaration=True)
216
221
  for path in output_dir.iterdir():
217
- belongs_to_vi = path.name == f"{vi_stem}.xml" or path.name.startswith(
218
- f"{vi_stem}_"
222
+ belongs_to_vi = path.name == f"{artifact_stem}.xml" or path.name.startswith(
223
+ f"{artifact_stem}_"
219
224
  )
220
225
  if path.suffix == ".xml" and belongs_to_vi:
221
226
  normalize_extracted_xml(path)
@@ -249,15 +254,24 @@ def extract_vi_xml(
249
254
  """
250
255
  vi_path = Path(vi_path).resolve()
251
256
 
252
- if output_dir is None:
257
+ # A caller-supplied output_dir is caller-owned, so keep the real source stem
258
+ # in the artifact names there. The MANAGED cache (output_dir is None) uses a
259
+ # FIXED short stem instead: a long source filename would otherwise overflow
260
+ # the cache path once a ``_BDHb.xml`` suffix is appended — the second Windows
261
+ # MAX_PATH axis, paired with the bounded per-VI slot dir (cache_paths._vi_slot).
262
+ # The real source name/path is preserved for callers: the graph loader keys
263
+ # every node on the source path (never on this stem), and the ``source`` field
264
+ # of the ``.meta.json`` records the real owner-relative path.
265
+ managed = output_dir is None
266
+ if managed:
253
267
  output_dir = _cache_target(vi_path)
254
268
  output_dir.mkdir(parents=True, exist_ok=True)
255
269
 
256
- vi_stem = vi_path.stem
257
- bd_xml = output_dir / f"{vi_stem}_BDHb.xml"
258
- fp_xml = output_dir / f"{vi_stem}_FPHb.xml"
259
- main_xml = output_dir / f"{vi_stem}.xml"
260
- meta_path = output_dir / f"{vi_stem}.meta.json"
270
+ artifact_stem = MANAGED_ARTIFACT_STEM if managed else vi_path.stem
271
+ bd_xml = output_dir / f"{artifact_stem}_BDHb.xml"
272
+ fp_xml = output_dir / f"{artifact_stem}_FPHb.xml"
273
+ main_xml = output_dir / f"{artifact_stem}.xml"
274
+ meta_path = output_dir / f"{artifact_stem}.meta.json"
261
275
 
262
276
  # Cache hit: XML present and the recorded content-hash (or mtime/size
263
277
  # fast-path) still matches the VI. The extraction-code compatibility check is
@@ -316,15 +330,15 @@ def extract_vi_xml(
316
330
  tmp_dir = Path(tempfile.mkdtemp(prefix=".x-", dir=_staging_root()))
317
331
  try:
318
332
  try:
319
- _extract_in_process(vi_path, tmp_dir, vi_stem)
333
+ _extract_in_process(vi_path, tmp_dir, artifact_stem)
320
334
  except Exception as exc:
321
335
  raise RuntimeError(
322
336
  f"pylabview extraction failed for {vi_path.name}: {exc}"
323
- f"{_windows_long_path_hint(tmp_dir / f'{vi_stem}_BDHb.xml')}"
337
+ f"{_windows_long_path_hint(tmp_dir / f'{artifact_stem}_BDHb.xml')}"
324
338
  ) from exc
325
339
 
326
- if not (tmp_dir / f"{vi_stem}_BDHb.xml").exists():
327
- raise RuntimeError(f"Block diagram XML not found: {vi_stem}_BDHb.xml")
340
+ if not (tmp_dir / f"{artifact_stem}_BDHb.xml").exists():
341
+ raise RuntimeError(f"Block diagram XML not found: {artifact_stem}_BDHb.xml")
328
342
 
329
343
  # Publish every produced artifact atomically (same filesystem as the
330
344
  # temp dir), then meta.json last so its appearance marks the cache valid.
@@ -99,6 +99,12 @@ class PrimitiveBuildHandler(NodeBuildHandler):
99
99
  if isinstance(node, (PropertyNode, InvokeNode, EventRegNode)):
100
100
  prim_kwargs["object_name"] = node.object_name
101
101
  prim_kwargs["object_method_id"] = node.object_method_id
102
+ # Property/Invoke nodes share the SAME implicit-binding fields
103
+ # (task #51/#55) -- EventRegNode has neither, so it's excluded
104
+ # here rather than duplicating this pair per elif branch below.
105
+ if isinstance(node, (PropertyNode, InvokeNode)):
106
+ prim_kwargs["bound_control_uid"] = node.bound_control_uid
107
+ prim_kwargs["bound_control_type"] = node.bound_control_type
102
108
  if isinstance(node, PropertyNode):
103
109
  prim_kwargs["properties"] = [
104
110
  PropertyDef(name=p.get("name", "")) if isinstance(p, dict) else p
@@ -107,8 +113,6 @@ class PrimitiveBuildHandler(NodeBuildHandler):
107
113
  prim_kwargs["property_value_terminal_ids"] = [
108
114
  ctx.qid(uid) for uid in node.dco_terminal_uids
109
115
  ]
110
- prim_kwargs["bound_control_uid"] = node.bound_control_uid
111
- prim_kwargs["bound_control_type"] = node.bound_control_type
112
116
  elif isinstance(node, InvokeNode):
113
117
  prim_kwargs["method_name"] = node.method_name
114
118
  prim_kwargs["method_code"] = node.method_code
@@ -496,8 +496,10 @@ class LoadingMixin:
496
496
 
497
497
  for member in lib.members:
498
498
  if member.member_type == "VI":
499
- member_name = Path(member.url).name
500
- if member_name.lower().endswith(".ctl"):
499
+ member_url = Path(member.url)
500
+ member_name = member_url.name
501
+ member_suffix = member_url.suffix.lower()
502
+ if member_suffix == ".ctl":
501
503
  # .ctl members are type definitions, not loadable VIs
502
504
  typedef_qname = lib_qname + ":" + member_name
503
505
  ctl_path = lvlib_path.parent / member.url
@@ -528,7 +530,7 @@ class LoadingMixin:
528
530
  caller=lib_key,
529
531
  rel="owns",
530
532
  )
531
- else:
533
+ elif member_suffix == ".vi":
532
534
  member_qname = lib_qname + ":" + member_name
533
535
  vi_path = lvlib_path.parent / member.url
534
536
  if not vi_path.exists():
@@ -558,6 +560,21 @@ class LoadingMixin:
558
560
  caller=lib_key,
559
561
  rel="owns",
560
562
  )
563
+ else:
564
+ # A member the library XML declares Type="VI" but whose URL
565
+ # is neither .vi nor .ctl -- a source-metadata anomaly, not
566
+ # a code entity. No node, no stub (a stub means "a VI we
567
+ # expect to resolve later", which is wrong here): warn and
568
+ # move on rather than sending a non-VI file to load_vi
569
+ # (which raises ValueError and would abort the whole load).
570
+ logger.warning(
571
+ 'library %s declares member %r as Type="VI" but its '
572
+ "URL %r is not a loadable .vi or .ctl file — skipping "
573
+ "it.",
574
+ lvlib_path.name,
575
+ member.name,
576
+ member.url,
577
+ )
561
578
  elif member.member_type == "LVClass":
562
579
  class_name = Path(member.url).name
563
580
  class_path = lvlib_path.parent / member.url
@@ -647,13 +664,14 @@ class LoadingMixin:
647
664
  search_paths: list[Path] | None = None,
648
665
  owner_chain: list[str] | None = None,
649
666
  ) -> str:
650
- """Load a .lvclass file. Returns the dep_graph qname it was
651
- registered under (``cls_qname``, built from the ON-DISK file's own
652
- stem casing) — the CALLER may have referenced this class under a
653
- different casing (a type reference's recorded casing can differ
654
- from the file's actual casing), so callers that add dep_graph edges
655
- or aliases must use this return value, never re-derive/assume the
656
- qname themselves (see ``_load_dependency``'s ``.lvclass`` branch).
667
+ """Load a .lvclass file. Returns the dep-graph KEY (the resolved
668
+ ``.lvclass`` path) it was registered under — mirrors ``load_lvlib``/
669
+ ``load_typedef``: callers add ownership/reference edges to THIS key,
670
+ never to the qname (``cls_qname``, built from the ON-DISK file's own
671
+ stem casing — the CALLER may have referenced this class under a
672
+ different casing, e.g. a type reference's recorded casing can differ
673
+ from the file's actual casing, so the qname alone isn't a safe edge
674
+ target; see ``_load_dependency``'s ``.lvclass`` branch).
657
675
 
658
676
  ``MINIMAL`` is an INTERFACE load: add the class's private-data fields
659
677
  (and its parent chain's, via walk-up — nMux field indices run into the
@@ -686,7 +704,9 @@ class LoadingMixin:
686
704
  # walks follow it by IDENTITY (a name can hit duplicates; a path
687
705
  # can't). None when the parent isn't on disk.
688
706
  parent = cls.parent_class
689
- parent_file, parent_intended = self._resolve_parent(cls, lvclass_path)
707
+ parent_file, parent_intended = self._resolve_parent(
708
+ cls, lvclass_path, search_paths
709
+ )
690
710
  # The parent's KEY is its recorded path whether or not the file is staged
691
711
  # yet — so progressive (web) staging can NAME + fetch a not-yet-present
692
712
  # parent (an ``.exists()`` gate would drop the whole inherited surface).
@@ -832,6 +852,18 @@ class LoadingMixin:
832
852
  try:
833
853
  pd_fields = private_data_from_lvclass_xml(lvclass_path)
834
854
  except Exception:
855
+ # Intentional hard best-effort boundary, not a narrowable
856
+ # set: private_data_from_lvclass_xml decodes a possibly
857
+ # malformed/legacy embedded RSRC container through
858
+ # pylabview's OWN VI-resource parser (parse_flattened_
859
+ # private_data -> lv_rsrc.VI(...).parseData()), whose
860
+ # exception surface on untrusted/old-format binary data
861
+ # isn't a documented closed set (struct/index/value/key
862
+ # errors and more have all been observed from that parser
863
+ # elsewhere) -- this docstring's own contract is "a
864
+ # malformed/older embedded control must never break class
865
+ # loading", so any failure here degrades to "no fields
866
+ # recovered", never propagates.
835
867
  logger.debug(
836
868
  "flattened private-data recovery failed for %s",
837
869
  lvclass_path,
@@ -841,23 +873,119 @@ class LoadingMixin:
841
873
  fields = [private_data_field_to_cluster_field(f) for f in pd_fields]
842
874
  return fields
843
875
 
876
+ def _resolve_vilib_class_ref(
877
+ self,
878
+ parent_name: str,
879
+ path_tokens: list[str],
880
+ lvclass_path: Path,
881
+ search_paths: list[Path],
882
+ ) -> tuple[Path | None, Path | None]:
883
+ """Resolve a ``<vilib>``-rooted class reference's TOKENS (already
884
+ split — ``path_tokens[0] == "<vilib>"``) -> ``(parent_file,
885
+ parent_intended)``, via ``ParsedDependencyRef.resolve_against`` — the
886
+ EXACT SAME machinery a SubVI/type ``<vilib>`` dependency already
887
+ resolves through (``_resolve_dependency_path``), never a new
888
+ resolver. Shared by BOTH ``<vilib>``-rooted sources ``_resolve_parent``
889
+ can see (a plain-XML ``Parent`` Item's URL, and the binary
890
+ ``ParentClassLinkInfo``'s own recorded path — issue #84's #F1
891
+ correction: the URL case was previously naively joined, leaving a
892
+ literal ``<vilib>`` path component that never exists).
893
+
894
+ A configured ``vilib_root`` gives an exact, scan-free hit; otherwise
895
+ ``<vilib>`` maps onto ``search_paths`` (this loader's already-
896
+ configured SubVI roots) the same way, with ``_find_file``'s existing
897
+ bounded per-search-path lookup (used for every other unresolved
898
+ dependency) actually LOCATING the file when it's nested deeper than
899
+ a direct join reaches (e.g. actor-framework vendors ``Actor.lvclass``
900
+ under an extra ``Core/`` level the recorded path itself doesn't
901
+ record — LabVIEW's own vi.lib layout has no such prefix).
902
+ ``parent_intended`` is still produced via pure path math even when
903
+ no local file is found (one of ``vilib_root``/``search_paths[0]``),
904
+ so progressive/web staging can NAME + fetch it — never
905
+ ``.exists()``-gated away, same contract as the method-path code in
906
+ ``load_lvclass`` above."""
907
+ parent_file: Path | None = None
908
+ parent_intended: Path | None = None
909
+ dep_ref = ParsedDependencyRef(
910
+ name=parent_name + ".lvclass", path_tokens=path_tokens
911
+ )
912
+ candidate = dep_ref.resolve_against(
913
+ lvclass_path,
914
+ vilib_root=self._vilib_root,
915
+ userlib_root=self._userlib_root,
916
+ instrlib_root=self._instrlib_root,
917
+ )
918
+ if candidate is not None:
919
+ parent_intended = candidate
920
+ if candidate.exists():
921
+ parent_file = candidate
922
+ # Both the search_paths glob AND the search_paths[0]-as-vilib_root
923
+ # intended-path fallback are skipped once EITHER parent_file OR
924
+ # parent_intended is already known -- no point globbing when the
925
+ # exact vilib_root candidate already resolved, and no point
926
+ # recomputing parent_intended once parent_file has resolved (it's
927
+ # only ever consulted as parent_file's own fallback, never both).
928
+ if parent_file is None and parent_intended is None and search_paths:
929
+ parent_file = self._find_file(
930
+ parent_name + ".lvclass", search_paths, lvclass_path.parent
931
+ )
932
+ if parent_file is None and parent_intended is None and search_paths:
933
+ # No configured vilib_root — map <vilib> onto the first search
934
+ # root instead, so an absent parent still gets a deterministic
935
+ # (pure path math, no scan) intended path for web staging to
936
+ # name.
937
+ parent_intended = dep_ref.resolve_against(
938
+ lvclass_path, vilib_root=search_paths[0]
939
+ )
940
+ return parent_file, parent_intended
941
+
844
942
  def _resolve_parent(
845
- self, cls: LVClass, lvclass_path: Path
943
+ self, cls: LVClass, lvclass_path: Path, search_paths: list[Path]
846
944
  ) -> tuple[Path | None, Path | None]:
847
945
  """The parent class's file (when present) and its INTENDED path
848
946
  (present or not) -> ``(parent_file, parent_intended)``.
849
947
 
850
948
  PREFERS the parent's own recorded URL (a DIRECT relative path — the
851
949
  parent commonly lives in a sibling subtree an up-tree walk can't
852
- reach, e.g. ``../../Layer/Layer.lvclass``); falls back to a walk-up
853
- by name only when no URL was recorded. Both None when the class has
854
- no parent (or its parent is the root ``LabVIEW Object``).
950
+ reach, e.g. ``../../Layer/Layer.lvclass``) — UNLESS that URL is
951
+ itself ``<vilib>``-rooted (``cls.is_vilib_parent``, e.g.
952
+ ``"/<vilib>/ActorFramework/Actor/Actor.lvclass"``, verified against
953
+ Event Receiver Actor.lvclass's real ``Parent`` Item — a LEADING
954
+ SLASH, the marker, then forward-slash path components, NOT a normal
955
+ relative path), in which case it's tokenized and resolved via
956
+ ``_resolve_vilib_class_ref`` like any other vi.lib reference (issue
957
+ #84's #F1 correction — the naive join used to leave a literal
958
+ ``<vilib>`` path component that never exists).
959
+
960
+ When there's no URL but the parent's binary link record is
961
+ ``<vilib>``-rooted (``cls.parent_link_path``, issue #84 — e.g.
962
+ ``["<vilib>", "ActorFramework", "Actor", "Actor.lvclass"]``),
963
+ resolves it the SAME way via ``_resolve_vilib_class_ref``.
964
+
965
+ A NON-vilib link record (the "in-repo" PTH0 shape — no recorded
966
+ URL, parent lives elsewhere in the same tree) is deliberately left
967
+ to the existing bare-name walk-up below — ``resolve_against``'s
968
+ generic (non-``<vilib>``) branch reads leading EMPTY tokens as
969
+ ``..`` hops, a shape not verified against a real in-repo PTH0
970
+ record, so this stays scoped to what issue #84 actually asked for
971
+ rather than risking the already-working walk-up.
972
+
973
+ Falls back to a bare-name walk-up (``_walk_up_find`` —
974
+ filesystem-only, no search_paths, so it can't reach a cross-subtree
975
+ or vi.lib parent) when NEITHER a URL nor a resolved vilib link path
976
+ was found. Both None when the class has no parent (or its parent is
977
+ the root ``LabVIEW Object``).
855
978
  """
856
979
  parent = cls.parent_class
857
980
  parent_file: Path | None = None
858
981
  parent_intended: Path | None = None
859
982
  if parent and parent != "LabVIEW Object":
860
- if cls.parent_url:
983
+ if cls.parent_url and cls.is_vilib_parent:
984
+ tokens = [t for t in cls.parent_url.split("/") if t]
985
+ parent_file, parent_intended = self._resolve_vilib_class_ref(
986
+ parent, tokens, lvclass_path, search_paths
987
+ )
988
+ elif cls.parent_url:
861
989
  # LabVIEW ``.lvclass`` URLs are relative to the class FILE
862
990
  # treated as a directory (members read ``../X.vi``), so
863
991
  # resolve against ``lvclass_path`` itself — that absorbs the
@@ -865,6 +993,10 @@ class LoadingMixin:
865
993
  parent_intended = (lvclass_path / cls.parent_url).resolve()
866
994
  if parent_intended.exists():
867
995
  parent_file = parent_intended
996
+ elif cls.is_vilib_parent and cls.parent_link_path:
997
+ parent_file, parent_intended = self._resolve_vilib_class_ref(
998
+ parent, cls.parent_link_path, lvclass_path, search_paths
999
+ )
868
1000
  if parent_file is None and parent_intended is None:
869
1001
  parent_file = self._walk_up_find(
870
1002
  lvclass_path.parent, parent + ".lvclass"
@@ -1105,6 +1237,7 @@ class LoadingMixin:
1105
1237
  main_xml: Path | None,
1106
1238
  search_paths: list[Path],
1107
1239
  visited: set[str],
1240
+ *,
1108
1241
  source_dir: Path | None = None,
1109
1242
  source_override: Path | None = None,
1110
1243
  mode: LoadMode = LoadMode.FULL,
@@ -1136,6 +1269,9 @@ class LoadingMixin:
1136
1269
  bd_xml=bd_xml,
1137
1270
  fp_xml=fp_xml if fp_xml and fp_xml.exists() else None,
1138
1271
  main_xml=main_xml if main_xml and main_xml.exists() else None,
1272
+ # Pin the parser's identity (name, source_path, warnings) to the
1273
+ # real source path, not the fixed ``vi_BDHb.xml`` cache name.
1274
+ source_override=source_override,
1139
1275
  layout=self._want_layout,
1140
1276
  )
1141
1277
  )
@@ -1145,7 +1281,19 @@ class LoadingMixin:
1145
1281
  fp = vi.front_panel
1146
1282
  conpane = vi.connector_pane
1147
1283
 
1148
- unqualified_name = bd_xml.name.replace("_BDHb.xml", ".vi")
1284
+ # The VI's real unqualified name comes from its SOURCE path when we have
1285
+ # one (``source_override``), NOT from the extracted BD XML filename: the
1286
+ # managed extraction cache names every artifact ``vi_BDHb.xml`` (a bounded
1287
+ # fixed name — see ``extractor.extract_vi_xml``), so deriving the name from
1288
+ # the XML would make every VI ``vi.vi``. The source path is authoritative
1289
+ # and is threaded here for the top-level VI (``load_vi``) and every SubVI
1290
+ # dependency (``_leaf_load_vi``). Only a raw ``*_BDHb.xml`` handed in
1291
+ # directly (no source path) falls back to the XML-derived name.
1292
+ unqualified_name = (
1293
+ source_override.name
1294
+ if source_override is not None
1295
+ else bd_xml.name.replace("_BDHb.xml", ".vi")
1296
+ )
1149
1297
  # own_qname is this VI's (possibly NON-unique) qualified name — kept only
1150
1298
  # for the self-dependency compare below and the qname reverse index. It
1151
1299
  # is NOT the identity: two on-disk copies (a source VI + its stripped
@@ -1639,19 +1787,19 @@ class LoadingMixin:
1639
1787
  owner_chain = parts[:-1] if len(parts) > 1 else None
1640
1788
  # MINIMAL: field-load the class (no method bodies) — enough for
1641
1789
  # by-name field names. FULL: load its whole method tree for codegen.
1642
- loaded_qname = self.load_lvclass(
1790
+ loaded_key = self.load_lvclass(
1643
1791
  resolved,
1644
1792
  mode,
1645
1793
  search_paths=search_paths,
1646
1794
  owner_chain=owner_chain,
1647
1795
  )
1648
1796
  if caller_qname:
1649
- self._dep_graph.add_edge(caller_qname, loaded_qname)
1797
+ self._dep_graph.add_edge(caller_qname, loaded_key)
1650
1798
  # See the walk-up branch above: alias rather than let a
1651
1799
  # differently-cased reference create a second, empty dep_graph
1652
1800
  # node that shadows the real (populated) one.
1653
- if qualified_name != loaded_qname:
1654
- self._qualified_aliases[qualified_name] = loaded_qname
1801
+ if qualified_name != loaded_key:
1802
+ self._qualified_aliases[qualified_name] = loaded_key
1655
1803
  elif leaf.endswith(".lvlib"):
1656
1804
  lib_key = self.load_lvlib(resolved, mode, search_paths=search_paths)
1657
1805
  if caller_qname:
@@ -1711,6 +1859,10 @@ class LoadingMixin:
1711
1859
  search_paths=search_paths,
1712
1860
  visited=set(),
1713
1861
  source_dir=resolved.parent,
1862
+ # ``resolved`` is this SubVI's real source ``.vi`` path — pin the
1863
+ # VI's identity (key + unqualified name) to it, never to the
1864
+ # fixed-name ``vi_BDHb.xml`` in the extraction cache.
1865
+ source_override=resolved,
1714
1866
  mode=child_mode,
1715
1867
  )
1716
1868
  if loaded_name:
@@ -158,17 +158,18 @@ class PrimitiveNode(GraphNode):
158
158
  # reference terminal, but this structural id list always can. See
159
159
  # ``op_walk.correlate_property_terminals``.
160
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).
161
+ # Property/Invoke node only: the BOUND front-panel control's own ddo uid
162
+ # (RAW, unqualified -- not this node's own qualified id) when this node
163
+ # is IMPLICIT (permanently tied to a specific control, e.g. GTR's
164
+ # "Abort" boolean property node or its "Test Hierarchy Tree" invoke
165
+ # node) -- "" for an EXPLICIT one (identity from a wired reference). See
166
+ # ``parser.node_types.PropertyNode``/``InvokeNode``'s class docstrings
167
+ # for the full heap discriminator (a direct ``<ddo>`` child + a
168
+ # ``<label>`` naming the control, both absent when explicit).
168
169
  bound_control_uid: str = ""
169
170
  # The bound control's reconstructed LVType (``parser.fp_heap_type.
170
171
  # reconstruct_control_lvtype``, resolved at PARSE time against the
171
- # front-panel heap -- see ``parser.vi._resolve_property_node_bound_types``).
172
+ # front-panel heap -- see ``parser.vi._resolve_bound_control_types``).
172
173
  # None for an explicit node, or an implicit one whose control class isn't
173
174
  # modeled by that reconstructor.
174
175
  bound_control_type: LVType | None = None
@@ -47,18 +47,27 @@ PARALLEL_THRESHOLD = 50
47
47
  # process-pool scheduling/pickling overhead across many small XML files.
48
48
  _BATCH_SIZE = 20
49
49
 
50
- _ParseItem = tuple[Path, Path | None, Path | None]
50
+ # (vi_path, bd_xml, fp_xml, main_xml): vi_path is the REAL source .vi, carried so
51
+ # the worker can pin the parser's identity to it — the managed cache names BD XML
52
+ # ``vi_BDHb.xml`` (a bounded fixed name), so parsing without the real path would
53
+ # label every VI ``vi.vi`` (see parse_vi's source_override).
54
+ _ParseItem = tuple[Path, Path, Path | None, Path | None]
51
55
 
52
56
 
53
57
  def _parse_batch(items: list[_ParseItem]) -> dict[str, ParsedVI]:
54
- """Worker entry point: parse a batch of (bd_xml, fp_xml, main_xml)
55
- triples. Runs in a worker process. A single unparseable VI is skipped,
58
+ """Worker entry point: parse a batch of (vi_path, bd_xml, fp_xml, main_xml)
59
+ tuples. Runs in a worker process. A single unparseable VI is skipped,
56
60
  not fatal to the rest of the batch -- the caller's serial path parses it
57
61
  (and reports its error, same as today) when it finds no cache entry."""
58
62
  out: dict[str, ParsedVI] = {}
59
- for bd_xml, fp_xml, main_xml in items:
63
+ for vi_path, bd_xml, fp_xml, main_xml in items:
60
64
  try:
61
- out[str(bd_xml)] = parse_vi(bd_xml=bd_xml, fp_xml=fp_xml, main_xml=main_xml)
65
+ out[str(bd_xml)] = parse_vi(
66
+ bd_xml=bd_xml,
67
+ fp_xml=fp_xml,
68
+ main_xml=main_xml,
69
+ source_override=vi_path,
70
+ )
62
71
  except Exception:
63
72
  logger.debug("parallel parse: skipping %s", bd_xml, exc_info=True)
64
73
  return out
@@ -93,7 +102,7 @@ def parallel_parse_directory(
93
102
  except Exception:
94
103
  # Extraction failure -- let the serial path hit (and report) it.
95
104
  continue
96
- resolved.append((bd_xml, fp_xml, main_xml))
105
+ resolved.append((vi_path, bd_xml, fp_xml, main_xml))
97
106
 
98
107
  if not resolved:
99
108
  return {}