lvkit 0.8.3__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.
- {lvkit-0.8.3 → lvkit-0.8.4}/PKG-INFO +1 -1
- {lvkit-0.8.3 → lvkit-0.8.4}/pyproject.toml +1 -1
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/__init__.py +1 -1
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/cache_paths.py +49 -10
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/extractor.py +29 -15
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/loading.py +41 -4
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/parallel_parse.py +15 -6
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/output_cache.py +38 -15
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/metadata.py +2 -2
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/vi.py +33 -7
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/conftest.py +24 -0
- lvkit-0.8.4/tests/test_cache_path_bound.py +331 -0
- lvkit-0.8.4/tests/test_decode_element_perf.py +107 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_extraction_cache.py +28 -9
- lvkit-0.8.4/tests/test_lvlib_nonvi_member.py +53 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_output_cache.py +10 -6
- {lvkit-0.8.3 → lvkit-0.8.4}/.gitignore +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/.pre-commit-config.yaml +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/LICENSE +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/NOTICE +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/deploy/cloudrun/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/docs/_internal/xml-schema/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/editors/vscode/LICENSE +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/editors/vscode/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/mcpb/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/plugin/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/audit_primitive_consistency.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/audit_terminal_order.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/audit_unresolved.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/build_example_pages.sh +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/build_hero.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/build_ni_function_catalog.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/connector_geometry_audit.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/dump_primitive_context.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/extract_corpus.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/gen_semantics_probe.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/generate_docs.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/generate_driver_data.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/generate_python.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/import_nodes_primitives.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/list_unknown_primitives.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/populate_vilib.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/pull_samples.sh +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/recategorize_vilib.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/render_gallery.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/reproduce_openg_corpus.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/study_unwired_direction.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/scripts/wire_decode_probe.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/__main__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/_data.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/_pylabview_patches.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/cli.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/ast_optimizer.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/ast_utils.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/builder.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/_shared.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/config.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/core.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/init_builder.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/methods.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/naming.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/properties.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/class_builder/terminals.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/condition_builder.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/context.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/dataflow.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/elementwise.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/error_handler.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/expressions.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/fragment.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/function.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/imports.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/base.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/case.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/compound.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/constant.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/event.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/first_call.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/formula.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/in_place.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/invoke_node.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/loop.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/nmux.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/primitive.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/printf.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/property_node.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/queue_ops.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/sequence.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/nodes/subvi.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/stubs.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/codegen/unresolved.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/connector_geometry.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/connector_pane_geometry.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/builtin_types.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/connector_pane_patterns.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/_index.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/daqmx.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/nidcpower.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/nidigital.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/nidmm.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/nifgen.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/niscope.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/niswitch.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/serial.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/drivers/visa.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/labview_error_codes.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/measure_data.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/openg/_index.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/openg/array.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/openg/file.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/openg/string.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/openg/time.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/openg/variant.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/primitives.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/_index.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/_pending_terminals.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/_types.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/addons.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/application-control.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/array.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/boolean.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/cluster-class-variant.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/collection.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/comparison.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/connectivity.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/control-simulation.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/data-communication.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/dialog-user-interface.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/express.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/file-io.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/graphics-sound.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/instrument-io.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/mathematics.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/measurement-io.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/numeric.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/report-generation.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/signal-processing.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/string.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/structures.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/synchronization.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/timing.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/data/vilib/waveform.json +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/generate.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/html_generator/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/html_generator/assets.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/html_generator/class_page.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/html_generator/core.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/html_generator/index_page.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/html_generator/naming.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/html_generator/vi_page.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/template.css +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/docs/utils.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/flattened_typedesc.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/formula/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/formula/cparser.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/formula/emit.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/formula/lexer.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/formula/nodes.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/analysis.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/builders/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/builders/context.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/builders/operations.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/builders/refs.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/builders/structures.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/construction.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/core.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/describe.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/diff.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/interface_order.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/lvnet_grammar.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/lvnet_parse.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/lvnet_reconstruct.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/models.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/netlist.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/netlist_build.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/netlist_diff_helpers.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/netlist_json.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/netlist_models.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/op_walk.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/operations.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/queries.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/graph/render_lvnet.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/index/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/index/build.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/index/model.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/index/project.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/index/query.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/index/sql.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/index/store.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/labview_error.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/labview_error_codes.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/labview_queue.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/load_mode.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/lv_detect.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/schemas.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/__main__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/_compat.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/app.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/index_tools.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/resolvers.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/roots.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/mcp/server/vi_tools.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/measure_data.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/models.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/num_format.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/conp_types.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/constants.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/defaults.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/flags.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/fp_heap_type.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/front_panel.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/image_resources.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/layout.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/models.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/naming.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/node_types.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/base.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/case.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/constant.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/decompose.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/disable.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/event.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/free_label.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/loop.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/nodes/sequence.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/type_mapping.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/type_resolution.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/utils.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/parser/wire_table.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/pipeline.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/primitive_resolver/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/primitive_resolver/exceptions.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/primitive_resolver/models.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/primitive_resolver/resolver.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/project_store.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/py.typed +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/ARCHITECTURE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/backend.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/composite.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/connector_pane.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/connector_pane_panel.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/diff_viewer.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/draw.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyph.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/arrow.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/base.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/factory.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/fallback.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/frame.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/line.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/decorations/picture.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/arith.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_build.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_constant.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_reverse.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_search.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_size.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_sort.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/array_split.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/base.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/boolean_constant.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/boolean_gate.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/bundle.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/bundle_by_name.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/centered_svg.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/class_glyph.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/cluster_constant.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/compound_arith.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/constant.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/control_ref_const.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/convert.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/error_cluster.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/event_data.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/event_reg_node.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/formula_node.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/icon_image.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/in_place_element.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/inline_svg.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/invoke_node.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/label.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/local_variable.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/path_glyph.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/property_node.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/refnum_glyph.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/unbundle.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/variant.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/nodes/wrapped_box.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/base.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/case.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/disable.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/event.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/factory.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/flat_sequence.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/for_loop.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/generic.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/in_place.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/selectable.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/stacked_sequence.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/structures/while_loop.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/autoindex.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/base.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/concatenate.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/conditional.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/event_dyn.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/event_timeout.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/factory.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/generic.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/loop_count.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/selector.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/shift_register.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/glyphs/terminals/tunnel.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/help_tip.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/icons.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/lane_pass.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/nodes.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/properties_panel.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/render_viewer.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/scene.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/style.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/templates/diff_viewer.html +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/templates/render_viewer.html +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/theme_control.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/theme_web.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/render/wire_router.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/runtime/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/runtime/lv.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit/SKILL.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-convert/SKILL.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-describe/SKILL.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-document/SKILL.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-query/SKILL.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-resolve/SKILL.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/skill_templates/lvkit-review/SKILL.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/structure.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/terminal_collector.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/text_encoding.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/tools/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/tools/connector_geometry_profile.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/type_defaults.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/unresolved.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vi_diff.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/exceptions.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/loader.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/lookup.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/models.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/naming.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/resolver.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/src/lvkit/vilib_resolver/variants.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/__init__.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib1/Class/Class.lvclass +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib1/Class/Do.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib1/Lib1.lvlib +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Class.lvclass +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Do.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Class/Test.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Lib2/Lib2.lvlib +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Test LVKit.aliases +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Test LVKit.lvlps +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/29/Test LVKit/Test LVKit.lvproj +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/30/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/30/visible-frame-case-sequence.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/30/visible-frame-conditional-disable.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/31/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/31/disable-structure-frame-names.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/32/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/32/comments-and-decorations.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/33/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/33/coercion-dot-consistency.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/34/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/34/hidden-iteration-terminal.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/35/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/35/objects-hidden-by-structures.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/36/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/36/bundle-unbundle-names.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/37/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/37/structure-tunnel-wire-bends.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/38/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/38/auto-concatenating-tunnel.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/39/PROVENANCE.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/39/zorder-not-respected.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/82/Pictures And Decorations.vi +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/corpus/issues/README.md +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/helpers.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_array_ops_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_ast_builder.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_ast_optimizer.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_case_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_case_parser.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_class_field_walkup.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_class_parent_linkinfo.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_class_properties.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_class_wire_appearance.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_cli.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_cli_cache.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_cli_describe_lvnet.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_cli_graph_ops.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_cli_query.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_cluster_wire_color.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_codegen_context.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_compound_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_condition_builder.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_connector_geometry.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_connector_pane_label_recovery.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_connector_pane_patterns.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_connector_pane_render.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_conp_types.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_constant_decoding.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_dependency_path_refs.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_determinism.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_diff.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_diff_properties.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_diff_viewer.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_disable_graph.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_disable_parser.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_docs_class_hierarchy.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_docs_render.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_driver_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_dynamic_dispatch.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_e2e_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_elementwise.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_error_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_error_handling.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_error_terminal_label_fallback.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_event_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_event_parser.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_extractor_concurrency.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_extractor_long_path.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_first_call_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_formula_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_formula_runtime.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_formula_semantics.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_formula_transpile.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_fp_heap_type.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_frame_attribution.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_frame_zplane.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_glyphs.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_graceful_degradation.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_help_tip.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_import_startup.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_in_place_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_index.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_index_sql.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_index_warm_no_downgrade.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_interface_order.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_issue_corpus.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_label_extraction.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_labview_queue.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_livi_vipi.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_load_mode.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_load_upgrade.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_loop_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_lv_detect.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_lvnet_identity.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_lvnet_reconstruct.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_lvnet_roundtrip.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_lvpy.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_mcp_cache.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_mcp_evals.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_mcp_read_vi_lvnet.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_mcp_roots.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_naming.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_netlist_json.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_new_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_node_properties.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_parallel_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_parallel_parse.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_parser.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_parser_regression.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_primitive_name_uniqueness.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_primitive_positional_order.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_primitive_resolutions.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_progressive_index.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_progressive_warm.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_project_store.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_python_structure_plan.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_queue_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_render.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_render_emission_order.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_render_lvnet.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_render_title_identity.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_render_viewer.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_sequence.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_soft_codegen.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_structure_lvproj.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_subvi_nav.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_text_encoding.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_type_driven_fixes.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_type_fields.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_type_loading.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_type_mapping.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_unknown_nodes.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_unresolved.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_vi_graph.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_vi_properties.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_viewer_properties.py +0 -0
- {lvkit-0.8.3 → lvkit-0.8.4}/tests/test_vilib_docurls.py +0 -0
- {lvkit-0.8.3 → 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.
|
|
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 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
-
__version__ = "0.8.
|
|
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
|
|
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
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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"{
|
|
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=
|
|
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"{
|
|
218
|
-
f"{
|
|
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
|
-
|
|
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
|
-
|
|
257
|
-
bd_xml = output_dir / f"{
|
|
258
|
-
fp_xml = output_dir / f"{
|
|
259
|
-
main_xml = output_dir / f"{
|
|
260
|
-
meta_path = output_dir / f"{
|
|
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,
|
|
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'{
|
|
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"{
|
|
327
|
-
raise RuntimeError(f"Block diagram XML not found: {
|
|
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.
|
|
@@ -496,8 +496,10 @@ class LoadingMixin:
|
|
|
496
496
|
|
|
497
497
|
for member in lib.members:
|
|
498
498
|
if member.member_type == "VI":
|
|
499
|
-
|
|
500
|
-
|
|
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
|
-
|
|
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
|
|
@@ -1220,6 +1237,7 @@ class LoadingMixin:
|
|
|
1220
1237
|
main_xml: Path | None,
|
|
1221
1238
|
search_paths: list[Path],
|
|
1222
1239
|
visited: set[str],
|
|
1240
|
+
*,
|
|
1223
1241
|
source_dir: Path | None = None,
|
|
1224
1242
|
source_override: Path | None = None,
|
|
1225
1243
|
mode: LoadMode = LoadMode.FULL,
|
|
@@ -1251,6 +1269,9 @@ class LoadingMixin:
|
|
|
1251
1269
|
bd_xml=bd_xml,
|
|
1252
1270
|
fp_xml=fp_xml if fp_xml and fp_xml.exists() else None,
|
|
1253
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,
|
|
1254
1275
|
layout=self._want_layout,
|
|
1255
1276
|
)
|
|
1256
1277
|
)
|
|
@@ -1260,7 +1281,19 @@ class LoadingMixin:
|
|
|
1260
1281
|
fp = vi.front_panel
|
|
1261
1282
|
conpane = vi.connector_pane
|
|
1262
1283
|
|
|
1263
|
-
|
|
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
|
+
)
|
|
1264
1297
|
# own_qname is this VI's (possibly NON-unique) qualified name — kept only
|
|
1265
1298
|
# for the self-dependency compare below and the qname reverse index. It
|
|
1266
1299
|
# is NOT the identity: two on-disk copies (a source VI + its stripped
|
|
@@ -1826,6 +1859,10 @@ class LoadingMixin:
|
|
|
1826
1859
|
search_paths=search_paths,
|
|
1827
1860
|
visited=set(),
|
|
1828
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,
|
|
1829
1866
|
mode=child_mode,
|
|
1830
1867
|
)
|
|
1831
1868
|
if loaded_name:
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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(
|
|
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 {}
|
|
@@ -92,13 +92,17 @@ def _ext_for(fmt: str) -> str:
|
|
|
92
92
|
# ── path resolution ─────────────────────────────────────────────────────────
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
def _render_paths(input_path: Path, fmt: str) -> tuple[Path, Path, bool]:
|
|
96
|
-
"""``(body_path, meta_path, is_adhoc)`` for a render of
|
|
95
|
+
def _render_paths(input_path: Path, fmt: str) -> tuple[Path, Path, str, bool]:
|
|
96
|
+
"""``(body_path, meta_path, source_label, is_adhoc)`` for a render of
|
|
97
|
+
``input_path``.
|
|
97
98
|
|
|
98
99
|
Path-addressed for project/shared VIs; flat content-addressed for adhoc.
|
|
100
|
+
``source_label`` is ``classify()``'s real owner-relative path (or, for
|
|
101
|
+
adhoc, the bare filename) — the caller writes it into the cache entry's
|
|
102
|
+
meta so the fixed ``vi.<ext>`` body name doesn't lose which VI it is.
|
|
99
103
|
"""
|
|
100
104
|
ext = _ext_for(fmt)
|
|
101
|
-
d,
|
|
105
|
+
d, source_label, ns = cache_paths.classify(input_path, "render")
|
|
102
106
|
if ns == "adhoc":
|
|
103
107
|
# Flat content-addressed pool, but still per-build: the <fp> keeps two
|
|
104
108
|
# lvkit builds from colliding on the same <sha>.<ext> (classify's dir is
|
|
@@ -111,8 +115,12 @@ def _render_paths(input_path: Path, fmt: str) -> tuple[Path, Path, bool]:
|
|
|
111
115
|
)
|
|
112
116
|
base = f"{cache_paths.sha256_file(input_path)}.{ext}"
|
|
113
117
|
else:
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
# classify's dir is now a bounded per-VI slot (vi-<hash>), so the source
|
|
119
|
+
# stem in the filename is both redundant AND a MAX_PATH hazard (a long VI
|
|
120
|
+
# name overflows the path) — use a fixed short base. The slot holds one
|
|
121
|
+
# source VI, so ``vi.<ext>`` is unique per format.
|
|
122
|
+
base = f"{cache_paths.MANAGED_ARTIFACT_STEM}.{ext}"
|
|
123
|
+
return d / base, d / f"{base}.meta.json", source_label, ns == "adhoc"
|
|
116
124
|
|
|
117
125
|
|
|
118
126
|
def _diff_ext(fmt: str) -> str:
|
|
@@ -121,17 +129,20 @@ def _diff_ext(fmt: str) -> str:
|
|
|
121
129
|
|
|
122
130
|
def _diff_paths(
|
|
123
131
|
before_path: Path, after_path: Path, fmt: str
|
|
124
|
-
) -> tuple[Path, Path, str, bool]:
|
|
125
|
-
"""``(body_path, meta_path, before_sha, is_adhoc)`` for a diff.
|
|
132
|
+
) -> tuple[Path, Path, str, str, bool]:
|
|
133
|
+
"""``(body_path, meta_path, before_sha, source_label, is_adhoc)`` for a diff.
|
|
126
134
|
|
|
127
135
|
Path-addressed by the AFTER (working-tree) VI — the side lvkit is handed as a
|
|
128
136
|
real path — with the before-content hash and the format in the filename
|
|
129
137
|
(lvkit is git-agnostic; the before side arrives only as bytes). Flat
|
|
130
|
-
content-addressed when even the after side is adhoc.
|
|
138
|
+
content-addressed when even the after side is adhoc. ``source_label`` is the
|
|
139
|
+
AFTER VI's real owner-relative path (or, for adhoc, its bare filename) — the
|
|
140
|
+
caller writes it into the cache entry's meta so the fixed ``vi.<sha>.<ext>``
|
|
141
|
+
body name doesn't lose which VI it is.
|
|
131
142
|
"""
|
|
132
143
|
ext = _diff_ext(fmt)
|
|
133
144
|
before_sha = cache_paths.sha256_file(before_path)
|
|
134
|
-
d,
|
|
145
|
+
d, source_label, ns = cache_paths.classify(after_path, "diff")
|
|
135
146
|
if ns == "adhoc":
|
|
136
147
|
after_sha = cache_paths.sha256_file(after_path)
|
|
137
148
|
d = (
|
|
@@ -142,8 +153,12 @@ def _diff_paths(
|
|
|
142
153
|
)
|
|
143
154
|
base = f"{before_sha[:16]}_{after_sha[:16]}.{ext}"
|
|
144
155
|
else:
|
|
145
|
-
|
|
146
|
-
|
|
156
|
+
# classify's dir is a bounded per-VI slot (vi-<hash>) holding one AFTER
|
|
157
|
+
# VI, so the after-stem in the filename is redundant AND a MAX_PATH
|
|
158
|
+
# hazard — a fixed short base plus the before-content hash still
|
|
159
|
+
# distinguishes every (before, format) pair.
|
|
160
|
+
base = f"{cache_paths.MANAGED_ARTIFACT_STEM}.{before_sha[:16]}.{ext}"
|
|
161
|
+
return d / base, d / f"{base}.meta.json", before_sha, source_label, ns == "adhoc"
|
|
147
162
|
|
|
148
163
|
|
|
149
164
|
# ── read / write ────────────────────────────────────────────────────────────
|
|
@@ -200,7 +215,7 @@ def diff_slot(before_path: Path, after_path: Path, fmt: str) -> Path:
|
|
|
200
215
|
|
|
201
216
|
def lookup_render(input_path: Path, fmt: str, options: str, version: str) -> str | None:
|
|
202
217
|
"""Return cached render output for ``input_path`` if fresh, else ``None``."""
|
|
203
|
-
body_path, meta_path, _ = _render_paths(input_path, fmt)
|
|
218
|
+
body_path, meta_path, _, _ = _render_paths(input_path, fmt)
|
|
204
219
|
return _read_if_fresh(
|
|
205
220
|
input_path,
|
|
206
221
|
body_path,
|
|
@@ -217,7 +232,7 @@ def store_render(
|
|
|
217
232
|
input_path: Path, fmt: str, options: str, version: str, body: str
|
|
218
233
|
) -> Path:
|
|
219
234
|
"""Cache ``body`` as the render of ``input_path``; return the slot path."""
|
|
220
|
-
body_path, meta_path, _ = _render_paths(input_path, fmt)
|
|
235
|
+
body_path, meta_path, source_label, _ = _render_paths(input_path, fmt)
|
|
221
236
|
_write(
|
|
222
237
|
body_path,
|
|
223
238
|
meta_path,
|
|
@@ -228,6 +243,9 @@ def store_render(
|
|
|
228
243
|
"options": options,
|
|
229
244
|
"kind": "render",
|
|
230
245
|
"text_encoding": labview_text_encoding(),
|
|
246
|
+
# The fixed ``vi.<ext>`` body name carries no source info by
|
|
247
|
+
# itself — record the real path (mirrors extraction's meta.json).
|
|
248
|
+
"source": source_label,
|
|
231
249
|
},
|
|
232
250
|
)
|
|
233
251
|
return body_path
|
|
@@ -237,7 +255,7 @@ def lookup_diff(
|
|
|
237
255
|
before_path: Path, after_path: Path, fmt: str, options: str, version: str
|
|
238
256
|
) -> str | None:
|
|
239
257
|
"""Return cached diff output for the ``(before, after)`` pair if fresh."""
|
|
240
|
-
body_path, meta_path, before_sha, _ = _diff_paths(before_path, after_path, fmt)
|
|
258
|
+
body_path, meta_path, before_sha, _, _ = _diff_paths(before_path, after_path, fmt)
|
|
241
259
|
return _read_if_fresh(
|
|
242
260
|
after_path,
|
|
243
261
|
body_path,
|
|
@@ -260,7 +278,9 @@ def store_diff(
|
|
|
260
278
|
body: str,
|
|
261
279
|
) -> Path:
|
|
262
280
|
"""Cache ``body`` as the diff of ``(before, after)``; return the slot path."""
|
|
263
|
-
body_path, meta_path, before_sha, _ = _diff_paths(
|
|
281
|
+
body_path, meta_path, before_sha, source_label, _ = _diff_paths(
|
|
282
|
+
before_path, after_path, fmt
|
|
283
|
+
)
|
|
264
284
|
_write(
|
|
265
285
|
body_path,
|
|
266
286
|
meta_path,
|
|
@@ -272,6 +292,9 @@ def store_diff(
|
|
|
272
292
|
"before_sha": before_sha,
|
|
273
293
|
"kind": "diff",
|
|
274
294
|
"text_encoding": labview_text_encoding(),
|
|
295
|
+
# The fixed ``vi.<sha>.<ext>`` body name carries no source info by
|
|
296
|
+
# itself — record the AFTER VI's real path (mirrors extraction).
|
|
297
|
+
"source": source_label,
|
|
275
298
|
},
|
|
276
299
|
)
|
|
277
300
|
return body_path
|
|
@@ -506,7 +506,7 @@ def parse_iuse_from_libd(libd_path: Path) -> dict[str, str]:
|
|
|
506
506
|
|
|
507
507
|
|
|
508
508
|
def _decode_pth0_components(
|
|
509
|
-
data: bytes, pth0_offset: int, end: int
|
|
509
|
+
data: bytes | memoryview, pth0_offset: int, end: int
|
|
510
510
|
) -> tuple[list[str], int]:
|
|
511
511
|
"""Decode one ``PTH0`` record's pascal-string path components ->
|
|
512
512
|
``(tokens, next_idx)``.
|
|
@@ -557,7 +557,7 @@ def _decode_pth0_components(
|
|
|
557
557
|
idx += 1
|
|
558
558
|
if idx + ln > end:
|
|
559
559
|
return [], pth0_offset
|
|
560
|
-
tokens.append(decode_labview_text(data[idx : idx + ln]))
|
|
560
|
+
tokens.append(decode_labview_text(bytes(data[idx : idx + ln])))
|
|
561
561
|
idx += ln
|
|
562
562
|
return tokens, idx
|
|
563
563
|
|
|
@@ -134,6 +134,7 @@ def parse_vi(
|
|
|
134
134
|
bd_xml: Path | str | None = None,
|
|
135
135
|
fp_xml: Path | str | None = None,
|
|
136
136
|
main_xml: Path | str | None = None,
|
|
137
|
+
source_override: Path | str | None = None,
|
|
137
138
|
layout: bool = False,
|
|
138
139
|
) -> ParsedVI:
|
|
139
140
|
"""Parse a VI file into all components.
|
|
@@ -146,6 +147,11 @@ def parse_vi(
|
|
|
146
147
|
bd_xml: Path to *_BDHb.xml (for direct XML parsing)
|
|
147
148
|
fp_xml: Path to *_FPHb.xml (optional)
|
|
148
149
|
main_xml: Path to main *.xml (optional)
|
|
150
|
+
source_override: the VI's real source path, when the caller already
|
|
151
|
+
knows it and ``bd_xml`` lives under a fixed cache name (e.g.
|
|
152
|
+
``vi_BDHb.xml``) that can't itself supply it. Pins the parsed VI's
|
|
153
|
+
name/``source_path``/warnings to this path instead of deriving them
|
|
154
|
+
from ``bd_xml``'s filename. Takes precedence over ``vi_path``.
|
|
149
155
|
layout: also decode block-diagram GEOMETRY (node/terminal/wire bounds)
|
|
150
156
|
from the same parsed heap and attach it as ``ParsedVI.layout``. Off
|
|
151
157
|
by default — codegen needs no positions. Rendering passes True so
|
|
@@ -180,9 +186,17 @@ def parse_vi(
|
|
|
180
186
|
)
|
|
181
187
|
fp_xml = None
|
|
182
188
|
|
|
183
|
-
# Derive source .vi path. Prefer
|
|
184
|
-
#
|
|
185
|
-
|
|
189
|
+
# Derive source .vi path. Prefer an explicit real source path — the caller
|
|
190
|
+
# passes ``source_override`` (the graph loader / parallel pre-parse) or
|
|
191
|
+
# ``vi_path`` — because the BD XML now lives in the managed cache under a
|
|
192
|
+
# bounded FIXED name (``vi_BDHb.xml``; see ``extractor.extract_vi_xml``).
|
|
193
|
+
# Deriving identity from that filename would mislabel every VI ``vi.vi`` (its
|
|
194
|
+
# name, ``metadata.source_path``, and every warning), so the source path is
|
|
195
|
+
# authoritative. ``source_override`` is NOT ``.exists()``-gated: the real .vi
|
|
196
|
+
# need not sit beside the cached XML.
|
|
197
|
+
if source_override is not None:
|
|
198
|
+
source_path_str = str(Path(source_override).resolve())
|
|
199
|
+
elif vi_path is not None:
|
|
186
200
|
source_path_str = str(Path(vi_path).resolve())
|
|
187
201
|
else:
|
|
188
202
|
source_path = bd_xml.with_name(bd_xml.name.replace("_BDHb.xml", ".vi"))
|
|
@@ -1450,7 +1464,7 @@ def _decode_default_data(
|
|
|
1450
1464
|
return None
|
|
1451
1465
|
|
|
1452
1466
|
|
|
1453
|
-
def _walk_path(data: bytes) -> tuple[str | None, int]:
|
|
1467
|
+
def _walk_path(data: bytes | memoryview) -> tuple[str | None, int]:
|
|
1454
1468
|
"""Walk a ``PTH0`` path DefaultData blob ONCE -> ``(value, bytes_consumed)``.
|
|
1455
1469
|
|
|
1456
1470
|
Delegates the pascal-string component decode to
|
|
@@ -1460,7 +1474,9 @@ def _walk_path(data: bytes) -> tuple[str | None, int]:
|
|
|
1460
1474
|
cluster stays aligned with the following field. Returns ``(None, 0)``
|
|
1461
1475
|
when ``data`` is not a ``PTH0`` blob.
|
|
1462
1476
|
"""
|
|
1463
|
-
|
|
1477
|
+
# An equality slice (not ``.startswith``, which memoryview lacks) works for
|
|
1478
|
+
# both ``bytes`` and ``memoryview`` callers.
|
|
1479
|
+
if data[:4] != b"PTH0":
|
|
1464
1480
|
return None, 0
|
|
1465
1481
|
parts, idx = _decode_pth0_components(data, 0, len(data))
|
|
1466
1482
|
return (f'Path("{"/".join(parts)}")' if parts else None), idx
|
|
@@ -1505,7 +1521,9 @@ def _decode_numeric_default(data: bytes) -> str | None:
|
|
|
1505
1521
|
return None
|
|
1506
1522
|
|
|
1507
1523
|
|
|
1508
|
-
def _decode_element(
|
|
1524
|
+
def _decode_element(
|
|
1525
|
+
data: bytes | memoryview, elem_type: LVType | None
|
|
1526
|
+
) -> tuple[str | None, int]:
|
|
1509
1527
|
"""Decode a single element and return (value, bytes_consumed).
|
|
1510
1528
|
|
|
1511
1529
|
Handles all LabVIEW types recursively: primitives, enums,
|
|
@@ -1521,6 +1539,14 @@ def _decode_element(data: bytes, elem_type: LVType | None) -> tuple[str | None,
|
|
|
1521
1539
|
if not elem_type or len(data) == 0:
|
|
1522
1540
|
return None, 0
|
|
1523
1541
|
|
|
1542
|
+
# A memoryview instead of bytes so the ARRAY/CLUSTER branches' recursive
|
|
1543
|
+
# ``data[idx:]`` slices below are non-copying subviews -- an array/cluster
|
|
1544
|
+
# element decode used to re-copy the whole remaining payload bytes object
|
|
1545
|
+
# on every recursive call, making a large array's decode O(N^2) (a
|
|
1546
|
+
# 65,160,056-byte NumInt32 array default effectively hung parse_vi()).
|
|
1547
|
+
if isinstance(data, bytes):
|
|
1548
|
+
data = memoryview(data)
|
|
1549
|
+
|
|
1524
1550
|
underlying = elem_type.underlying_type or ""
|
|
1525
1551
|
kind = elem_type.kind
|
|
1526
1552
|
|
|
@@ -1531,7 +1557,7 @@ def _decode_element(data: bytes, elem_type: LVType | None) -> tuple[str | None,
|
|
|
1531
1557
|
str_len = int.from_bytes(data[:4], "big")
|
|
1532
1558
|
if len(data) < 4 + str_len:
|
|
1533
1559
|
return None, 0
|
|
1534
|
-
string_val = decode_labview_text(data[4 : 4 + str_len])
|
|
1560
|
+
string_val = decode_labview_text(bytes(data[4 : 4 + str_len]))
|
|
1535
1561
|
escaped = string_val.replace("\\", "\\\\").replace("'", "\\'")
|
|
1536
1562
|
return f"'{escaped}'", 4 + str_len
|
|
1537
1563
|
|
|
@@ -29,6 +29,30 @@ def pytest_collection_modifyitems(config, items):
|
|
|
29
29
|
item.add_marker(skip)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
@pytest.fixture(autouse=True)
|
|
33
|
+
def _sanitize_git_env(monkeypatch):
|
|
34
|
+
"""Strip git's repo-locating env vars so a test's ``git -C <sample repo>``
|
|
35
|
+
subprocess resolves THAT repo, not whatever the ambient environment points at.
|
|
36
|
+
|
|
37
|
+
Under the pre-commit hook the suite runs with ``GIT_DIR`` / ``GIT_WORK_TREE`` /
|
|
38
|
+
``GIT_INDEX_FILE`` (and friends) exported, pointing at the lvkit repo. A child
|
|
39
|
+
``git -C <other repo> show`` then INHERITS them, they take precedence over
|
|
40
|
+
``-C``, git looks the ref up in the wrong repo, and the call fails with exit
|
|
41
|
+
128 (yielding an empty / unreadable VI). That flake appears ONLY under
|
|
42
|
+
pre-commit — never in a bare ``pytest`` run — so it is invisible until commit
|
|
43
|
+
time. Clearing these makes ``-C`` authoritative for every git-extracting test
|
|
44
|
+
(test_diff, test_class_field_walkup, …) in one place."""
|
|
45
|
+
for var in (
|
|
46
|
+
"GIT_DIR",
|
|
47
|
+
"GIT_WORK_TREE",
|
|
48
|
+
"GIT_INDEX_FILE",
|
|
49
|
+
"GIT_OBJECT_DIRECTORY",
|
|
50
|
+
"GIT_COMMON_DIR",
|
|
51
|
+
"GIT_PREFIX",
|
|
52
|
+
):
|
|
53
|
+
monkeypatch.delenv(var, raising=False)
|
|
54
|
+
|
|
55
|
+
|
|
32
56
|
@pytest.fixture(autouse=True)
|
|
33
57
|
def _hermetic_cache(tmp_path_factory, monkeypatch):
|
|
34
58
|
"""Point the extraction cache at a per-test tmp dir so no test ever writes
|