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.

Files changed (164) hide show
  1. {kicad_sch_api-0.4.4/kicad_sch_api.egg-info → kicad_sch_api-0.4.5}/PKG-INFO +1 -1
  2. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/__init__.py +9 -0
  3. kicad_sch_api-0.4.5/kicad_sch_api/core/__init__.py +57 -0
  4. kicad_sch_api-0.4.5/kicad_sch_api/core/exceptions.py +175 -0
  5. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/__init__.py +2 -0
  6. kicad_sch_api-0.4.5/kicad_sch_api/core/managers/base.py +76 -0
  7. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/file_io.py +3 -1
  8. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/format_sync.py +3 -2
  9. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/graphics.py +3 -2
  10. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/metadata.py +4 -2
  11. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/sheet.py +3 -2
  12. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/text_elements.py +3 -2
  13. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/validation.py +3 -2
  14. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/managers/wire.py +3 -2
  15. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/schematic.py +27 -1
  16. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/types.py +1 -0
  17. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/symbol_parser.py +70 -40
  18. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/utils/validation.py +16 -22
  19. kicad_sch_api-0.4.5/kicad_sch_api/wrappers/__init__.py +14 -0
  20. kicad_sch_api-0.4.5/kicad_sch_api/wrappers/base.py +89 -0
  21. kicad_sch_api-0.4.5/kicad_sch_api/wrappers/wire.py +198 -0
  22. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5/kicad_sch_api.egg-info}/PKG-INFO +1 -1
  23. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/SOURCES.txt +6 -1
  24. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/pyproject.toml +1 -1
  25. kicad_sch_api-0.4.5/tests/test_hierarchical_instances.py +249 -0
  26. kicad_sch_api-0.4.4/.claude/commands/dev/update-memory-bank.md +0 -33
  27. kicad_sch_api-0.4.4/kicad_sch_api/core/__init__.py +0 -23
  28. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/dead-code-analysis.md +0 -0
  29. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/publish-pypi.md +0 -0
  30. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/review-implementation.md +0 -0
  31. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/run-tests.md +0 -0
  32. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/dev/update-and-commit.md +0 -0
  33. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/.claude/commands/test/run-reference-tests.md +0 -0
  34. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/CHANGELOG.md +0 -0
  35. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/LICENSE +0 -0
  36. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/MANIFEST.in +0 -0
  37. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/README.md +0 -0
  38. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/advanced_usage.py +0 -0
  39. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/basic_usage.py +0 -0
  40. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/kicad_cli_exports.py +0 -0
  41. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/mcp_basic_example.py +0 -0
  42. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/mcp_integration.py +0 -0
  43. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/parser_demo.py +0 -0
  44. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/pin_to_pin_wiring_demo.py +0 -0
  45. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/simple_circuit_with_pin_wiring.py +0 -0
  46. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/examples/simple_two_resistor_routing.py +0 -0
  47. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/__init__.py +0 -0
  48. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/base.py +0 -0
  49. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/bom.py +0 -0
  50. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/erc.py +0 -0
  51. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/export_docs.py +0 -0
  52. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/netlist.py +0 -0
  53. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli/types.py +0 -0
  54. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/cli.py +0 -0
  55. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/__init__.py +0 -0
  56. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/base.py +0 -0
  57. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/components.py +0 -0
  58. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/junctions.py +0 -0
  59. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/labels.py +0 -0
  60. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/collections/wires.py +0 -0
  61. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/collections/__init__.py +0 -0
  62. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/collections/base.py +0 -0
  63. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/component_bounds.py +0 -0
  64. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/components.py +0 -0
  65. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/config.py +0 -0
  66. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/factories/__init__.py +0 -0
  67. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/factories/element_factory.py +0 -0
  68. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/formatter.py +0 -0
  69. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/geometry.py +0 -0
  70. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/ic_manager.py +0 -0
  71. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/junctions.py +0 -0
  72. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/labels.py +0 -0
  73. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/nets.py +0 -0
  74. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/no_connects.py +0 -0
  75. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/parser.py +0 -0
  76. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/parsing_utils.py +0 -0
  77. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/pin_utils.py +0 -0
  78. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/texts.py +0 -0
  79. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/core/wires.py +0 -0
  80. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/discovery/__init__.py +0 -0
  81. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/discovery/search_index.py +0 -0
  82. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/geometry/__init__.py +0 -0
  83. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/geometry/font_metrics.py +0 -0
  84. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/geometry/symbol_bbox.py +0 -0
  85. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/__init__.py +0 -0
  86. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/parser.py +0 -0
  87. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/repository.py +0 -0
  88. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/interfaces/resolver.py +0 -0
  89. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/library/__init__.py +0 -0
  90. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/library/cache.py +0 -0
  91. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/__init__.py +0 -0
  92. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/base.py +0 -0
  93. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/__init__.py +0 -0
  94. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/graphics_parser.py +0 -0
  95. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/label_parser.py +0 -0
  96. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/library_parser.py +0 -0
  97. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/metadata_parser.py +0 -0
  98. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/sheet_parser.py +0 -0
  99. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/text_parser.py +0 -0
  100. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/elements/wire_parser.py +0 -0
  101. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/registry.py +0 -0
  102. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/parsers/utils.py +0 -0
  103. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/py.typed +0 -0
  104. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/__init__.py +0 -0
  105. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/cache.py +0 -0
  106. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/resolver.py +0 -0
  107. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/symbols/validators.py +0 -0
  108. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/utils/__init__.py +0 -0
  109. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/__init__.py +0 -0
  110. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/erc.py +0 -0
  111. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/erc_models.py +0 -0
  112. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/pin_matrix.py +0 -0
  113. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api/validation/validators.py +0 -0
  114. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/dependency_links.txt +0 -0
  115. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/entry_points.txt +0 -0
  116. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/requires.txt +0 -0
  117. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/kicad_sch_api.egg-info/top_level.txt +0 -0
  118. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/setup.cfg +0 -0
  119. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/reference_tests/reference_kicad_projects/README.md +0 -0
  120. {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
  121. {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
  122. {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
  123. {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
  124. {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
  125. {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
  126. {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
  127. {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
  128. {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
  129. {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
  130. {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
  131. {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
  132. {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
  133. {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
  134. {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
  135. {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
  136. {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
  137. {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
  138. {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
  139. {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
  140. {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
  141. {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
  142. {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
  143. {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
  144. {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
  145. {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
  146. {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
  147. {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
  148. {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
  149. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_bounding_box_rectangles.py +0 -0
  150. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_cli_integration.py +0 -0
  151. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_component_removal.py +0 -0
  152. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_element_removal.py +0 -0
  153. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_geometry.py +0 -0
  154. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_grid_snapping.py +0 -0
  155. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_image_support.py +0 -0
  156. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_issue_13_public_properties.py +0 -0
  157. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_kicad_validation.py +0 -0
  158. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_parse_reference_rectangles.py +0 -0
  159. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_pin_positioning.py +0 -0
  160. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_pin_to_pin_wiring.py +0 -0
  161. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_rectangle.py +0 -0
  162. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_rectangle_roundtrip.py +0 -0
  163. {kicad_sch_api-0.4.4 → kicad_sch_api-0.4.5}/tests/test_removal_against_references.py +0 -0
  164. {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.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
- self._data = schematic_data
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
- self._data = schematic_data
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
- self._data = schematic_data
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
- self._data = schematic_data
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
- self._data = schematic_data
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
- self._data = schematic_data
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
- self._data = schematic_data
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
- self._data["components"] = [comp._data.__dict__ for comp in self._components]
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