kicad-sch-api 0.4.4__tar.gz → 0.4.5__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.
Potentially problematic release.
This version of kicad-sch-api might be problematic. Click here for more details.
- {kicad_sch_api-0.4.4/kicad_sch_api.egg-info → kicad_sch_api-0.4.5}/PKG-INFO +1 -1
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/__init__.py +9 -0
- kicad_sch_api-0.4.5/kicad_sch_api/core/__init__.py +57 -0
- kicad_sch_api-0.4.5/kicad_sch_api/core/exceptions.py +175 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/__init__.py +2 -0
- kicad_sch_api-0.4.5/kicad_sch_api/core/managers/base.py +76 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/file_io.py +3 -1
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/format_sync.py +3 -2
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/graphics.py +3 -2
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/metadata.py +4 -2
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/sheet.py +3 -2
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/text_elements.py +3 -2
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/validation.py +3 -2
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/wire.py +3 -2
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/schematic.py +27 -1
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/types.py +1 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/symbol_parser.py +70 -40
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/utils/validation.py +16 -22
- kicad_sch_api-0.4.5/kicad_sch_api/wrappers/__init__.py +14 -0
- kicad_sch_api-0.4.5/kicad_sch_api/wrappers/base.py +89 -0
- kicad_sch_api-0.4.5/kicad_sch_api/wrappers/wire.py +198 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5/kicad_sch_api.egg-info}/PKG-INFO +1 -1
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/SOURCES.txt +6 -1
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/pyproject.toml +1 -1
- kicad_sch_api-0.4.5/tests/test_hierarchical_instances.py +249 -0
- kicad_sch_api-0.4.4/.claude/commands/dev/update-memory-bank.md +0 -33
- kicad_sch_api-0.4.4/kicad_sch_api/core/__init__.py +0 -23
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/dead-code-analysis.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/publish-pypi.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/review-implementation.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/run-tests.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/update-and-commit.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/test/run-reference-tests.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/CHANGELOG.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/LICENSE +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/MANIFEST.in +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/README.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/advanced_usage.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/basic_usage.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/kicad_cli_exports.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/mcp_basic_example.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/mcp_integration.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/parser_demo.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/pin_to_pin_wiring_demo.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/simple_circuit_with_pin_wiring.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/simple_two_resistor_routing.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/base.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/bom.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/erc.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/export_docs.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/netlist.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/types.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/base.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/components.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/junctions.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/labels.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/wires.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/collections/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/collections/base.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/component_bounds.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/components.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/config.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/factories/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/factories/element_factory.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/formatter.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/geometry.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/ic_manager.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/junctions.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/labels.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/nets.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/no_connects.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/parsing_utils.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/pin_utils.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/texts.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/wires.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/discovery/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/discovery/search_index.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/geometry/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/geometry/font_metrics.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/geometry/symbol_bbox.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/repository.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/resolver.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/library/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/library/cache.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/base.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/graphics_parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/label_parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/library_parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/metadata_parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/sheet_parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/text_parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/wire_parser.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/registry.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/utils.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/py.typed +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/cache.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/resolver.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/validators.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/utils/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/__init__.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/erc.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/erc_models.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/pin_matrix.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/validators.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/dependency_links.txt +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/entry_points.txt +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/requires.txt +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/top_level.txt +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/setup.cfg +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/README.md +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/sch_title/sch_title.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/sch_title/sch_title.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/subcircuit1.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_pro +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_sch +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_bounding_box_rectangles.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_cli_integration.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_component_removal.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_element_removal.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_geometry.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_grid_snapping.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_image_support.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_issue_13_public_properties.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_kicad_validation.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_parse_reference_rectangles.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_pin_positioning.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_pin_to_pin_wiring.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_rectangle.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_rectangle_roundtrip.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_removal_against_references.py +0 -0
- {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_wire_operations.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kicad-sch-api
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Professional KiCAD schematic manipulation library with exact format preservation
|
|
5
5
|
Author-email: Circuit-Synth <shane@circuit-synth.com>
|
|
6
6
|
Maintainer-email: Circuit-Synth <shane@circuit-synth.com>
|
|
@@ -53,6 +53,12 @@ from .core.config import KiCADConfig, config
|
|
|
53
53
|
from .core.schematic import Schematic
|
|
54
54
|
from .library.cache import SymbolLibraryCache, get_symbol_cache
|
|
55
55
|
from .utils.validation import ValidationError, ValidationIssue
|
|
56
|
+
# Commonly-used exceptions (ValidationError re-exported from utils for backward compat)
|
|
57
|
+
from .core.exceptions import (
|
|
58
|
+
KiCadSchError,
|
|
59
|
+
ElementNotFoundError,
|
|
60
|
+
DuplicateElementError,
|
|
61
|
+
)
|
|
56
62
|
|
|
57
63
|
# Version info
|
|
58
64
|
VERSION_INFO = (0, 4, 0)
|
|
@@ -69,8 +75,11 @@ __all__ = [
|
|
|
69
75
|
"KiCADConfig",
|
|
70
76
|
"config",
|
|
71
77
|
# Exceptions
|
|
78
|
+
"KiCadSchError",
|
|
72
79
|
"ValidationError",
|
|
73
80
|
"ValidationIssue",
|
|
81
|
+
"ElementNotFoundError",
|
|
82
|
+
"DuplicateElementError",
|
|
74
83
|
# Version info
|
|
75
84
|
"__version__",
|
|
76
85
|
"VERSION_INFO",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Core kicad-sch-api functionality."""
|
|
2
|
+
|
|
3
|
+
from .components import Component, ComponentCollection
|
|
4
|
+
from .formatter import ExactFormatter
|
|
5
|
+
from .parser import SExpressionParser
|
|
6
|
+
from .schematic import Schematic, create_schematic, load_schematic
|
|
7
|
+
from .types import Junction, Label, Net, Point, SchematicSymbol, Wire
|
|
8
|
+
# Exception hierarchy
|
|
9
|
+
from .exceptions import (
|
|
10
|
+
KiCadSchError,
|
|
11
|
+
ValidationError,
|
|
12
|
+
ReferenceError,
|
|
13
|
+
LibraryError,
|
|
14
|
+
GeometryError,
|
|
15
|
+
NetError,
|
|
16
|
+
ParseError,
|
|
17
|
+
FormatError,
|
|
18
|
+
CollectionError,
|
|
19
|
+
ElementNotFoundError,
|
|
20
|
+
DuplicateElementError,
|
|
21
|
+
CollectionOperationError,
|
|
22
|
+
FileOperationError,
|
|
23
|
+
CLIError,
|
|
24
|
+
SchematicStateError,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"Schematic",
|
|
29
|
+
"Component",
|
|
30
|
+
"ComponentCollection",
|
|
31
|
+
"Point",
|
|
32
|
+
"SchematicSymbol",
|
|
33
|
+
"Wire",
|
|
34
|
+
"Junction",
|
|
35
|
+
"Label",
|
|
36
|
+
"Net",
|
|
37
|
+
"SExpressionParser",
|
|
38
|
+
"ExactFormatter",
|
|
39
|
+
"load_schematic",
|
|
40
|
+
"create_schematic",
|
|
41
|
+
# Exceptions
|
|
42
|
+
"KiCadSchError",
|
|
43
|
+
"ValidationError",
|
|
44
|
+
"ReferenceError",
|
|
45
|
+
"LibraryError",
|
|
46
|
+
"GeometryError",
|
|
47
|
+
"NetError",
|
|
48
|
+
"ParseError",
|
|
49
|
+
"FormatError",
|
|
50
|
+
"CollectionError",
|
|
51
|
+
"ElementNotFoundError",
|
|
52
|
+
"DuplicateElementError",
|
|
53
|
+
"CollectionOperationError",
|
|
54
|
+
"FileOperationError",
|
|
55
|
+
"CLIError",
|
|
56
|
+
"SchematicStateError",
|
|
57
|
+
]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Exception hierarchy for kicad-sch-api.
|
|
3
|
+
|
|
4
|
+
Provides a structured exception hierarchy for better error handling and debugging.
|
|
5
|
+
All exceptions inherit from the base KiCadSchError class.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, List, Optional, TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
# Import validation types for type hints
|
|
11
|
+
# ValidationLevel is imported at runtime in methods that need it
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..utils.validation import ValidationIssue
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class KiCadSchError(Exception):
|
|
17
|
+
"""Base exception for all kicad-sch-api errors."""
|
|
18
|
+
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ValidationError(KiCadSchError):
|
|
23
|
+
"""
|
|
24
|
+
Raised when validation fails.
|
|
25
|
+
|
|
26
|
+
Supports rich error context with field/value information and can collect
|
|
27
|
+
multiple validation issues.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
message: str,
|
|
33
|
+
issues: Optional[List["ValidationIssue"]] = None,
|
|
34
|
+
field: str = "",
|
|
35
|
+
value: Any = None,
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Initialize validation error with context.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
message: Error message describing the validation failure
|
|
42
|
+
issues: List of validation issues (for collecting multiple errors)
|
|
43
|
+
field: The field name that failed validation
|
|
44
|
+
value: The invalid value that was provided
|
|
45
|
+
"""
|
|
46
|
+
self.issues = issues or []
|
|
47
|
+
self.field = field
|
|
48
|
+
self.value = value
|
|
49
|
+
super().__init__(message)
|
|
50
|
+
|
|
51
|
+
def add_issue(self, issue: "ValidationIssue") -> None:
|
|
52
|
+
"""Add a validation issue to this error."""
|
|
53
|
+
self.issues.append(issue)
|
|
54
|
+
|
|
55
|
+
def get_errors(self) -> List["ValidationIssue"]:
|
|
56
|
+
"""Get only error-level issues."""
|
|
57
|
+
# Import here to avoid circular dependency
|
|
58
|
+
from ..utils.validation import ValidationLevel
|
|
59
|
+
|
|
60
|
+
return [
|
|
61
|
+
issue
|
|
62
|
+
for issue in self.issues
|
|
63
|
+
if hasattr(issue, 'level') and issue.level in (ValidationLevel.ERROR, ValidationLevel.CRITICAL)
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
def get_warnings(self) -> List["ValidationIssue"]:
|
|
67
|
+
"""Get only warning-level issues."""
|
|
68
|
+
# Import here to avoid circular dependency
|
|
69
|
+
from ..utils.validation import ValidationLevel
|
|
70
|
+
|
|
71
|
+
return [issue for issue in self.issues if hasattr(issue, 'level') and issue.level == ValidationLevel.WARNING]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class ReferenceError(ValidationError):
|
|
75
|
+
"""Raised when a component reference is invalid."""
|
|
76
|
+
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class LibraryError(ValidationError):
|
|
81
|
+
"""Raised when a library or symbol reference is invalid."""
|
|
82
|
+
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class GeometryError(ValidationError):
|
|
87
|
+
"""Raised when geometry validation fails (positions, shapes, dimensions)."""
|
|
88
|
+
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class NetError(ValidationError):
|
|
93
|
+
"""Raised when a net specification or operation is invalid."""
|
|
94
|
+
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class ParseError(KiCadSchError):
|
|
99
|
+
"""Raised when parsing a schematic file fails."""
|
|
100
|
+
|
|
101
|
+
pass
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class FormatError(KiCadSchError):
|
|
105
|
+
"""Raised when formatting a schematic file fails."""
|
|
106
|
+
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class CollectionError(KiCadSchError):
|
|
111
|
+
"""Raised when a collection operation fails."""
|
|
112
|
+
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ElementNotFoundError(CollectionError):
|
|
117
|
+
"""Raised when an element is not found in a collection."""
|
|
118
|
+
|
|
119
|
+
def __init__(self, message: str, element_type: str = "", identifier: str = ""):
|
|
120
|
+
"""
|
|
121
|
+
Initialize element not found error.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
message: Error message
|
|
125
|
+
element_type: Type of element (e.g., 'component', 'wire', 'junction')
|
|
126
|
+
identifier: The identifier used to search (e.g., 'R1', UUID)
|
|
127
|
+
"""
|
|
128
|
+
self.element_type = element_type
|
|
129
|
+
self.identifier = identifier
|
|
130
|
+
super().__init__(message)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class DuplicateElementError(CollectionError):
|
|
134
|
+
"""Raised when attempting to add a duplicate element."""
|
|
135
|
+
|
|
136
|
+
def __init__(self, message: str, element_type: str = "", identifier: str = ""):
|
|
137
|
+
"""
|
|
138
|
+
Initialize duplicate element error.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
message: Error message
|
|
142
|
+
element_type: Type of element (e.g., 'component', 'wire', 'junction')
|
|
143
|
+
identifier: The duplicate identifier (e.g., 'R1', UUID)
|
|
144
|
+
"""
|
|
145
|
+
self.element_type = element_type
|
|
146
|
+
self.identifier = identifier
|
|
147
|
+
super().__init__(message)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class CollectionOperationError(CollectionError):
|
|
151
|
+
"""Raised when a collection operation fails for reasons other than not found/duplicate."""
|
|
152
|
+
|
|
153
|
+
pass
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class FileOperationError(KiCadSchError):
|
|
157
|
+
"""Raised when a file I/O operation fails."""
|
|
158
|
+
|
|
159
|
+
pass
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class CLIError(KiCadSchError):
|
|
163
|
+
"""Raised when KiCad CLI execution fails."""
|
|
164
|
+
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class SchematicStateError(KiCadSchError):
|
|
169
|
+
"""
|
|
170
|
+
Raised when an operation requires specific schematic state.
|
|
171
|
+
|
|
172
|
+
Examples: schematic must be saved before export, etc.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
pass
|
|
@@ -5,6 +5,7 @@ This package contains specialized managers for different aspects of schematic
|
|
|
5
5
|
manipulation, enabling clean separation of concerns and better maintainability.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
from .base import BaseManager
|
|
8
9
|
from .file_io import FileIOManager
|
|
9
10
|
from .format_sync import FormatSyncManager
|
|
10
11
|
from .graphics import GraphicsManager
|
|
@@ -15,6 +16,7 @@ from .validation import ValidationManager
|
|
|
15
16
|
from .wire import WireManager
|
|
16
17
|
|
|
17
18
|
__all__ = [
|
|
19
|
+
"BaseManager",
|
|
18
20
|
"FileIOManager",
|
|
19
21
|
"FormatSyncManager",
|
|
20
22
|
"GraphicsManager",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Base manager class for schematic operations.
|
|
2
|
+
|
|
3
|
+
Provides a consistent interface for all manager classes and enforces
|
|
4
|
+
common patterns for validation and data access.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC
|
|
8
|
+
from typing import Any, Dict, List, Optional, TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from ...utils.validation import ValidationIssue
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..schematic import Schematic
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseManager(ABC):
|
|
17
|
+
"""Base class for all schematic managers.
|
|
18
|
+
|
|
19
|
+
Managers encapsulate complex operations and keep Schematic focused.
|
|
20
|
+
This base class provides a consistent interface and common utilities
|
|
21
|
+
for all managers.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
_data: Reference to schematic data (optional, varies by manager)
|
|
25
|
+
_schematic: Reference to parent Schematic instance (optional)
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, schematic_data: Optional[Dict[str, Any]] = None, **kwargs):
|
|
29
|
+
"""Initialize manager with schematic data reference.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
schematic_data: Reference to schematic data dictionary (optional)
|
|
33
|
+
**kwargs: Additional manager-specific parameters
|
|
34
|
+
"""
|
|
35
|
+
self._data = schematic_data
|
|
36
|
+
self._schematic: Optional["Schematic"] = None
|
|
37
|
+
|
|
38
|
+
def set_schematic(self, schematic: "Schematic") -> None:
|
|
39
|
+
"""Set reference to parent schematic.
|
|
40
|
+
|
|
41
|
+
This is called by Schematic after manager initialization to establish
|
|
42
|
+
bidirectional relationship.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
schematic: The parent Schematic instance
|
|
46
|
+
"""
|
|
47
|
+
self._schematic = schematic
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def schematic(self) -> Optional["Schematic"]:
|
|
51
|
+
"""Get the parent schematic instance.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
The parent Schematic, or None if not set
|
|
55
|
+
"""
|
|
56
|
+
return self._schematic
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def data(self) -> Optional[Dict[str, Any]]:
|
|
60
|
+
"""Get the schematic data dictionary.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
The schematic data, or None if not set
|
|
64
|
+
"""
|
|
65
|
+
return self._data
|
|
66
|
+
|
|
67
|
+
def validate(self) -> List[ValidationIssue]:
|
|
68
|
+
"""Validate managed elements.
|
|
69
|
+
|
|
70
|
+
This is an optional method that managers can override to provide
|
|
71
|
+
validation. Default implementation returns empty list (no issues).
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
List of validation issues found
|
|
75
|
+
"""
|
|
76
|
+
return []
|
|
@@ -14,11 +14,12 @@ from ...utils.validation import ValidationError
|
|
|
14
14
|
from ..config import config
|
|
15
15
|
from ..formatter import ExactFormatter
|
|
16
16
|
from ..parser import SExpressionParser
|
|
17
|
+
from .base import BaseManager
|
|
17
18
|
|
|
18
19
|
logger = logging.getLogger(__name__)
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class FileIOManager:
|
|
22
|
+
class FileIOManager(BaseManager):
|
|
22
23
|
"""
|
|
23
24
|
Manages file I/O operations for KiCAD schematics.
|
|
24
25
|
|
|
@@ -31,6 +32,7 @@ class FileIOManager:
|
|
|
31
32
|
|
|
32
33
|
def __init__(self):
|
|
33
34
|
"""Initialize the FileIOManager."""
|
|
35
|
+
super().__init__()
|
|
34
36
|
self._parser = SExpressionParser(preserve_format=True)
|
|
35
37
|
self._formatter = ExactFormatter()
|
|
36
38
|
|
|
@@ -11,11 +11,12 @@ from typing import Any, Dict, List, Optional, Set, Union
|
|
|
11
11
|
|
|
12
12
|
from ..components import Component
|
|
13
13
|
from ..types import Point, Wire
|
|
14
|
+
from .base import BaseManager
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class FormatSyncManager:
|
|
19
|
+
class FormatSyncManager(BaseManager):
|
|
19
20
|
"""
|
|
20
21
|
Manages synchronization between object models and S-expression data.
|
|
21
22
|
|
|
@@ -34,7 +35,7 @@ class FormatSyncManager:
|
|
|
34
35
|
Args:
|
|
35
36
|
schematic_data: Reference to schematic data
|
|
36
37
|
"""
|
|
37
|
-
|
|
38
|
+
super().__init__(schematic_data)
|
|
38
39
|
self._dirty_flags: Set[str] = set()
|
|
39
40
|
self._change_log: List[Dict[str, Any]] = []
|
|
40
41
|
self._sync_lock = False
|
|
@@ -11,11 +11,12 @@ import uuid
|
|
|
11
11
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
12
12
|
|
|
13
13
|
from ..types import Point
|
|
14
|
+
from .base import BaseManager
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class GraphicsManager:
|
|
19
|
+
class GraphicsManager(BaseManager):
|
|
19
20
|
"""
|
|
20
21
|
Manages graphic elements and drawing shapes in KiCAD schematics.
|
|
21
22
|
|
|
@@ -34,7 +35,7 @@ class GraphicsManager:
|
|
|
34
35
|
Args:
|
|
35
36
|
schematic_data: Reference to schematic data
|
|
36
37
|
"""
|
|
37
|
-
|
|
38
|
+
super().__init__(schematic_data)
|
|
38
39
|
|
|
39
40
|
def add_rectangle(
|
|
40
41
|
self,
|
|
@@ -8,10 +8,12 @@ paper size, title block, version information, and instance sections.
|
|
|
8
8
|
import logging
|
|
9
9
|
from typing import Any, Dict, List, Optional
|
|
10
10
|
|
|
11
|
+
from .base import BaseManager
|
|
12
|
+
|
|
11
13
|
logger = logging.getLogger(__name__)
|
|
12
14
|
|
|
13
15
|
|
|
14
|
-
class MetadataManager:
|
|
16
|
+
class MetadataManager(BaseManager):
|
|
15
17
|
"""
|
|
16
18
|
Manages schematic metadata and configuration settings.
|
|
17
19
|
|
|
@@ -30,7 +32,7 @@ class MetadataManager:
|
|
|
30
32
|
Args:
|
|
31
33
|
schematic_data: Reference to schematic data dictionary
|
|
32
34
|
"""
|
|
33
|
-
|
|
35
|
+
super().__init__(schematic_data)
|
|
34
36
|
|
|
35
37
|
def set_paper_size(self, paper: str) -> None:
|
|
36
38
|
"""
|
|
@@ -11,11 +11,12 @@ from pathlib import Path
|
|
|
11
11
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
12
12
|
|
|
13
13
|
from ..types import Point
|
|
14
|
+
from .base import BaseManager
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class SheetManager:
|
|
19
|
+
class SheetManager(BaseManager):
|
|
19
20
|
"""
|
|
20
21
|
Manages hierarchical sheets and multi-sheet project coordination.
|
|
21
22
|
|
|
@@ -34,7 +35,7 @@ class SheetManager:
|
|
|
34
35
|
Args:
|
|
35
36
|
schematic_data: Reference to schematic data
|
|
36
37
|
"""
|
|
37
|
-
|
|
38
|
+
super().__init__(schematic_data)
|
|
38
39
|
|
|
39
40
|
def add_sheet(
|
|
40
41
|
self,
|
|
@@ -11,11 +11,12 @@ import uuid
|
|
|
11
11
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
12
12
|
|
|
13
13
|
from ..types import Point
|
|
14
|
+
from .base import BaseManager
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class TextElementManager:
|
|
19
|
+
class TextElementManager(BaseManager):
|
|
19
20
|
"""
|
|
20
21
|
Manages text elements and labeling in KiCAD schematics.
|
|
21
22
|
|
|
@@ -34,7 +35,7 @@ class TextElementManager:
|
|
|
34
35
|
Args:
|
|
35
36
|
schematic_data: Reference to schematic data
|
|
36
37
|
"""
|
|
37
|
-
|
|
38
|
+
super().__init__(schematic_data)
|
|
38
39
|
|
|
39
40
|
def add_label(
|
|
40
41
|
self,
|
|
@@ -11,11 +11,12 @@ from typing import Any, Dict, List, Optional, Set, Tuple
|
|
|
11
11
|
|
|
12
12
|
from ...utils.validation import ValidationError, ValidationIssue
|
|
13
13
|
from ..types import Point
|
|
14
|
+
from .base import BaseManager
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class ValidationManager:
|
|
19
|
+
class ValidationManager(BaseManager):
|
|
19
20
|
"""
|
|
20
21
|
Comprehensive validation manager for schematic integrity.
|
|
21
22
|
|
|
@@ -39,7 +40,7 @@ class ValidationManager:
|
|
|
39
40
|
component_collection: Component collection for validation
|
|
40
41
|
wire_collection: Wire collection for connectivity analysis
|
|
41
42
|
"""
|
|
42
|
-
|
|
43
|
+
super().__init__(schematic_data)
|
|
43
44
|
self._components = component_collection
|
|
44
45
|
self._wires = wire_collection
|
|
45
46
|
self._validation_rules = self._initialize_validation_rules()
|
|
@@ -12,11 +12,12 @@ from typing import Any, Dict, List, Optional, Tuple, Union
|
|
|
12
12
|
from ...library.cache import get_symbol_cache
|
|
13
13
|
from ..types import Point, Wire, WireType
|
|
14
14
|
from ..wires import WireCollection
|
|
15
|
+
from .base import BaseManager
|
|
15
16
|
|
|
16
17
|
logger = logging.getLogger(__name__)
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
class WireManager:
|
|
20
|
+
class WireManager(BaseManager):
|
|
20
21
|
"""
|
|
21
22
|
Manages wire operations and pin connectivity in KiCAD schematics.
|
|
22
23
|
|
|
@@ -39,7 +40,7 @@ class WireManager:
|
|
|
39
40
|
wire_collection: Wire collection for management
|
|
40
41
|
component_collection: Component collection for pin lookups
|
|
41
42
|
"""
|
|
42
|
-
|
|
43
|
+
super().__init__(schematic_data)
|
|
43
44
|
self._wires = wire_collection
|
|
44
45
|
self._components = component_collection
|
|
45
46
|
self._symbol_cache = get_symbol_cache()
|
|
@@ -1216,7 +1216,33 @@ class Schematic:
|
|
|
1216
1216
|
# Internal sync methods (migrated from original implementation)
|
|
1217
1217
|
def _sync_components_to_data(self):
|
|
1218
1218
|
"""Sync component collection state back to data structure."""
|
|
1219
|
-
|
|
1219
|
+
logger.debug("🔍 _sync_components_to_data: Syncing components to _data")
|
|
1220
|
+
|
|
1221
|
+
components_data = []
|
|
1222
|
+
for comp in self._components:
|
|
1223
|
+
# Start with base component data
|
|
1224
|
+
comp_dict = {k: v for k, v in comp._data.__dict__.items() if not k.startswith('_')}
|
|
1225
|
+
|
|
1226
|
+
# CRITICAL FIX: Explicitly preserve instances if user set them
|
|
1227
|
+
if hasattr(comp._data, 'instances') and comp._data.instances:
|
|
1228
|
+
logger.debug(f" Component {comp._data.reference} has {len(comp._data.instances)} instance(s)")
|
|
1229
|
+
comp_dict['instances'] = [
|
|
1230
|
+
{
|
|
1231
|
+
'project': getattr(inst, 'project', self.name) if hasattr(inst, 'project') else self.name,
|
|
1232
|
+
'path': inst.path, # PRESERVE exact path user set!
|
|
1233
|
+
'reference': inst.reference,
|
|
1234
|
+
'unit': inst.unit,
|
|
1235
|
+
}
|
|
1236
|
+
for inst in comp._data.instances
|
|
1237
|
+
]
|
|
1238
|
+
logger.debug(f" Instance paths: {[inst.path for inst in comp._data.instances]}")
|
|
1239
|
+
else:
|
|
1240
|
+
logger.debug(f" Component {comp._data.reference} has NO instances (will be generated by parser)")
|
|
1241
|
+
|
|
1242
|
+
components_data.append(comp_dict)
|
|
1243
|
+
|
|
1244
|
+
self._data["components"] = components_data
|
|
1245
|
+
logger.debug(f" Synced {len(components_data)} components to _data")
|
|
1220
1246
|
|
|
1221
1247
|
# Populate lib_symbols with actual symbol definitions used by components
|
|
1222
1248
|
lib_symbols = {}
|
|
@@ -171,6 +171,7 @@ class SchematicSymbol:
|
|
|
171
171
|
in_bom: bool = True
|
|
172
172
|
on_board: bool = True
|
|
173
173
|
unit: int = 1
|
|
174
|
+
instances: List["SymbolInstance"] = field(default_factory=list) # FIX: Add instances field for hierarchical support
|
|
174
175
|
|
|
175
176
|
def __post_init__(self) -> None:
|
|
176
177
|
# Generate UUID if not provided
|