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