kicad-sch-api 0.4.1__tar.gz → 0.4.3__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 (157) hide show
  1. {kicad_sch_api-0.4.1/kicad_sch_api.egg-info → kicad_sch_api-0.4.3}/PKG-INFO +1 -1
  2. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/__init__.py +1 -1
  3. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/components.py +80 -2
  4. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/factories/element_factory.py +1 -1
  5. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/formatter.py +22 -5
  6. kicad_sch_api-0.4.3/kicad_sch_api/core/parsing_utils.py +63 -0
  7. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/symbol_parser.py +9 -2
  8. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3/kicad_sch_api.egg-info}/PKG-INFO +1 -1
  9. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api.egg-info/SOURCES.txt +1 -0
  10. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/pyproject.toml +1 -1
  11. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/.claude/commands/dev/dead-code-analysis.md +0 -0
  12. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/.claude/commands/dev/publish-pypi.md +0 -0
  13. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/.claude/commands/dev/review-implementation.md +0 -0
  14. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/.claude/commands/dev/run-tests.md +0 -0
  15. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/.claude/commands/dev/update-and-commit.md +0 -0
  16. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/.claude/commands/dev/update-memory-bank.md +0 -0
  17. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/.claude/commands/test/run-reference-tests.md +0 -0
  18. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/CHANGELOG.md +0 -0
  19. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/LICENSE +0 -0
  20. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/MANIFEST.in +0 -0
  21. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/README.md +0 -0
  22. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/advanced_usage.py +0 -0
  23. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/basic_usage.py +0 -0
  24. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/kicad_cli_exports.py +0 -0
  25. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/mcp_basic_example.py +0 -0
  26. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/mcp_integration.py +0 -0
  27. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/parser_demo.py +0 -0
  28. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/pin_to_pin_wiring_demo.py +0 -0
  29. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/simple_circuit_with_pin_wiring.py +0 -0
  30. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/examples/simple_two_resistor_routing.py +0 -0
  31. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli/__init__.py +0 -0
  32. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli/base.py +0 -0
  33. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli/bom.py +0 -0
  34. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli/erc.py +0 -0
  35. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli/export_docs.py +0 -0
  36. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli/netlist.py +0 -0
  37. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli/types.py +0 -0
  38. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/cli.py +0 -0
  39. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/collections/__init__.py +0 -0
  40. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/collections/base.py +0 -0
  41. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/collections/components.py +0 -0
  42. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/collections/junctions.py +0 -0
  43. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/collections/labels.py +0 -0
  44. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/collections/wires.py +0 -0
  45. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/__init__.py +0 -0
  46. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/collections/__init__.py +0 -0
  47. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/collections/base.py +0 -0
  48. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/component_bounds.py +0 -0
  49. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/config.py +0 -0
  50. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/factories/__init__.py +0 -0
  51. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/geometry.py +0 -0
  52. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/ic_manager.py +0 -0
  53. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/junctions.py +0 -0
  54. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/labels.py +0 -0
  55. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/__init__.py +0 -0
  56. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/file_io.py +0 -0
  57. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/format_sync.py +0 -0
  58. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/graphics.py +0 -0
  59. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/metadata.py +0 -0
  60. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/sheet.py +0 -0
  61. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/text_elements.py +0 -0
  62. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/validation.py +0 -0
  63. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/managers/wire.py +0 -0
  64. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/nets.py +0 -0
  65. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/no_connects.py +0 -0
  66. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/parser.py +0 -0
  67. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/pin_utils.py +0 -0
  68. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/schematic.py +0 -0
  69. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/texts.py +0 -0
  70. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/types.py +0 -0
  71. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/core/wires.py +0 -0
  72. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/discovery/__init__.py +0 -0
  73. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/discovery/search_index.py +0 -0
  74. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/geometry/__init__.py +0 -0
  75. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/geometry/font_metrics.py +0 -0
  76. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/geometry/symbol_bbox.py +0 -0
  77. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/interfaces/__init__.py +0 -0
  78. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/interfaces/parser.py +0 -0
  79. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/interfaces/repository.py +0 -0
  80. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/interfaces/resolver.py +0 -0
  81. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/library/__init__.py +0 -0
  82. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/library/cache.py +0 -0
  83. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/__init__.py +0 -0
  84. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/base.py +0 -0
  85. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/__init__.py +0 -0
  86. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/graphics_parser.py +0 -0
  87. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/label_parser.py +0 -0
  88. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/library_parser.py +0 -0
  89. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/metadata_parser.py +0 -0
  90. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/sheet_parser.py +0 -0
  91. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/text_parser.py +0 -0
  92. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/elements/wire_parser.py +0 -0
  93. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/registry.py +0 -0
  94. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/parsers/utils.py +0 -0
  95. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/py.typed +0 -0
  96. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/symbols/__init__.py +0 -0
  97. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/symbols/cache.py +0 -0
  98. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/symbols/resolver.py +0 -0
  99. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/symbols/validators.py +0 -0
  100. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/utils/__init__.py +0 -0
  101. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/utils/validation.py +0 -0
  102. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/validation/__init__.py +0 -0
  103. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/validation/erc.py +0 -0
  104. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/validation/erc_models.py +0 -0
  105. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/validation/pin_matrix.py +0 -0
  106. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api/validation/validators.py +0 -0
  107. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api.egg-info/dependency_links.txt +0 -0
  108. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api.egg-info/entry_points.txt +0 -0
  109. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api.egg-info/requires.txt +0 -0
  110. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/kicad_sch_api.egg-info/top_level.txt +0 -0
  111. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/setup.cfg +0 -0
  112. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/README.md +0 -0
  113. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_pro +0 -0
  114. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_sch +0 -0
  115. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_pro +0 -0
  116. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_sch +0 -0
  117. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_pro +0 -0
  118. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_sch +0 -0
  119. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_pro +0 -0
  120. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_sch +0 -0
  121. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/sch_title/sch_title.kicad_pro +0 -0
  122. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/sch_title/sch_title.kicad_sch +0 -0
  123. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_pro +0 -0
  124. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_sch +0 -0
  125. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_pro +0 -0
  126. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_sch +0 -0
  127. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/subcircuit1.kicad_sch +0 -0
  128. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_pro +0 -0
  129. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_sch +0 -0
  130. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_pro +0 -0
  131. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_sch +0 -0
  132. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_pro +0 -0
  133. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_sch +0 -0
  134. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_pro +0 -0
  135. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_sch +0 -0
  136. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_pro +0 -0
  137. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_sch +0 -0
  138. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_pro +0 -0
  139. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_sch +0 -0
  140. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_pro +0 -0
  141. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_sch +0 -0
  142. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_bounding_box_rectangles.py +0 -0
  143. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_cli_integration.py +0 -0
  144. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_component_removal.py +0 -0
  145. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_element_removal.py +0 -0
  146. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_geometry.py +0 -0
  147. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_grid_snapping.py +0 -0
  148. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_image_support.py +0 -0
  149. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_issue_13_public_properties.py +0 -0
  150. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_kicad_validation.py +0 -0
  151. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_parse_reference_rectangles.py +0 -0
  152. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_pin_positioning.py +0 -0
  153. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_pin_to_pin_wiring.py +0 -0
  154. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_rectangle.py +0 -0
  155. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_rectangle_roundtrip.py +0 -0
  156. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/tests/test_removal_against_references.py +0 -0
  157. {kicad_sch_api-0.4.1 → kicad_sch_api-0.4.3}/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.1
3
+ Version: 0.4.3
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>
@@ -42,7 +42,7 @@ Advanced Usage:
42
42
  print(f"Found {len(issues)} validation issues")
43
43
  """
44
44
 
45
- __version__ = "0.4.0"
45
+ __version__ = "0.4.3"
46
46
  __author__ = "Circuit-Synth"
47
47
  __email__ = "info@circuit-synth.com"
48
48
 
@@ -448,11 +448,25 @@ class ComponentCollection(BaseCollection[Component]):
448
448
  Remove component by reference.
449
449
 
450
450
  Args:
451
- reference: Component reference to remove
451
+ reference: Component reference to remove (e.g., "R1")
452
452
 
453
453
  Returns:
454
- True if component was removed
454
+ True if component was removed, False if not found
455
+
456
+ Raises:
457
+ TypeError: If reference is not a string
458
+
459
+ Examples:
460
+ sch.components.remove("R1")
461
+ sch.components.remove("C2")
462
+
463
+ Note:
464
+ For removing by UUID or component object, use remove_by_uuid() or remove_component()
465
+ respectively. This maintains a clear, simple API contract.
455
466
  """
467
+ if not isinstance(reference, str):
468
+ raise TypeError(f"reference must be a string, not {type(reference).__name__}")
469
+
456
470
  component = self._reference_index.get(reference)
457
471
  if not component:
458
472
  return False
@@ -466,6 +480,70 @@ class ComponentCollection(BaseCollection[Component]):
466
480
  logger.info(f"Removed component: {reference}")
467
481
  return True
468
482
 
483
+ def remove_by_uuid(self, component_uuid: str) -> bool:
484
+ """
485
+ Remove component by UUID.
486
+
487
+ Args:
488
+ component_uuid: Component UUID to remove
489
+
490
+ Returns:
491
+ True if component was removed, False if not found
492
+
493
+ Raises:
494
+ TypeError: If UUID is not a string
495
+ """
496
+ if not isinstance(component_uuid, str):
497
+ raise TypeError(f"component_uuid must be a string, not {type(component_uuid).__name__}")
498
+
499
+ if component_uuid not in self._uuid_index:
500
+ return False
501
+
502
+ component = self._items[self._uuid_index[component_uuid]]
503
+
504
+ # Remove from component-specific indexes
505
+ self._remove_from_indexes(component)
506
+
507
+ # Remove from base collection
508
+ super().remove(component_uuid)
509
+
510
+ logger.info(f"Removed component by UUID: {component_uuid}")
511
+ return True
512
+
513
+ def remove_component(self, component: "Component") -> bool:
514
+ """
515
+ Remove component by component object.
516
+
517
+ Args:
518
+ component: Component object to remove
519
+
520
+ Returns:
521
+ True if component was removed, False if not found
522
+
523
+ Raises:
524
+ TypeError: If component is not a Component instance
525
+
526
+ Examples:
527
+ comp = sch.components.get("R1")
528
+ sch.components.remove_component(comp)
529
+ """
530
+ if not isinstance(component, Component):
531
+ raise TypeError(
532
+ f"component must be a Component instance, not {type(component).__name__}"
533
+ )
534
+
535
+ if component.uuid not in self._uuid_index:
536
+ return False
537
+
538
+ # Remove from component-specific indexes
539
+ self._remove_from_indexes(component)
540
+
541
+ # Remove from base collection
542
+ super().remove(component.uuid)
543
+
544
+ logger.info(f"Removed component: {component.reference}")
545
+ return True
546
+
469
547
  def get(self, reference: str) -> Optional[Component]:
470
548
  """Get component by reference."""
471
549
  return self._reference_index.get(reference)
@@ -126,7 +126,7 @@ class ElementFactory:
126
126
  uuid=label_dict.get("uuid", str(uuid.uuid4())),
127
127
  position=pos,
128
128
  text=label_dict.get("text", ""),
129
- label_type=LabelType(label_dict.get("label_type", "local")),
129
+ label_type=LabelType(label_dict.get("label_type", "label")),
130
130
  rotation=label_dict.get("rotation", 0.0),
131
131
  size=label_dict.get("size", 1.27),
132
132
  shape=(
@@ -125,6 +125,10 @@ class ExactFormatter:
125
125
  self.rules["global_label"] = FormatRule(inline=False, quote_indices={1})
126
126
  self.rules["hierarchical_label"] = FormatRule(inline=False, quote_indices={1})
127
127
 
128
+ # Text elements
129
+ self.rules["text"] = FormatRule(inline=False, quote_indices={1})
130
+ self.rules["text_box"] = FormatRule(inline=False, quote_indices={1})
131
+
128
132
  # Effects and text formatting
129
133
  self.rules["effects"] = FormatRule(inline=False)
130
134
  self.rules["font"] = FormatRule(inline=False)
@@ -279,6 +283,8 @@ class ExactFormatter:
279
283
  "junction",
280
284
  "label",
281
285
  "hierarchical_label",
286
+ "text",
287
+ "text_box",
282
288
  "polyline",
283
289
  "rectangle",
284
290
  ):
@@ -384,7 +390,8 @@ class ExactFormatter:
384
390
  result += f"\n{next_indent}{self._format_element(element, indent_level + 1)}"
385
391
  else:
386
392
  if i in rule.quote_indices and isinstance(element, str):
387
- result += f' "{element}"'
393
+ escaped_element = self._escape_string(element)
394
+ result += f' "{escaped_element}"'
388
395
  else:
389
396
  result += f" {self._format_element(element, 0)}"
390
397
 
@@ -396,7 +403,8 @@ class ExactFormatter:
396
403
  indent = "\t" * indent_level
397
404
  next_indent = "\t" * (indent_level + 1)
398
405
 
399
- result = f"({lst[0]}"
406
+ tag = str(lst[0])
407
+ result = f"({tag}"
400
408
 
401
409
  for i, element in enumerate(lst[1:], 1):
402
410
  if isinstance(element, list):
@@ -425,9 +433,18 @@ class ExactFormatter:
425
433
  return True
426
434
 
427
435
  def _escape_string(self, text: str) -> str:
428
- """Escape quotes in string for S-expression formatting."""
429
- # Replace double quotes with escaped quotes
430
- return text.replace('"', '\\"')
436
+ """Escape special characters in string for S-expression formatting."""
437
+ # Escape backslashes first (must be done before other replacements)
438
+ text = text.replace('\\', '\\\\')
439
+ # Escape double quotes
440
+ text = text.replace('"', '\\"')
441
+ # Escape newlines (convert actual newlines to escaped representation)
442
+ text = text.replace('\n', '\\n')
443
+ # Escape carriage returns
444
+ text = text.replace('\r', '\\r')
445
+ # Escape tabs
446
+ text = text.replace('\t', '\\t')
447
+ return text
431
448
 
432
449
  def _needs_quoting(self, text: str) -> bool:
433
450
  """Check if string needs to be quoted."""
@@ -0,0 +1,63 @@
1
+ """
2
+ Utility functions for parsing S-expression data.
3
+
4
+ This module contains helper functions used by various parsers
5
+ to handle common parsing patterns safely and consistently.
6
+ """
7
+
8
+ import logging
9
+ from typing import Any
10
+
11
+ import sexpdata
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ def parse_bool_property(value: Any, default: bool = True) -> bool:
17
+ """
18
+ Parse a boolean property from S-expression data.
19
+
20
+ Handles both sexpdata.Symbol and string types, converting yes/no to bool.
21
+ This is the canonical way to parse boolean properties from KiCad files.
22
+
23
+ Args:
24
+ value: Value from S-expression (Symbol, str, bool, or None)
25
+ default: Default value if parsing fails or value is None
26
+
27
+ Returns:
28
+ bool: Parsed boolean value
29
+
30
+ Examples:
31
+ >>> parse_bool_property(sexpdata.Symbol('yes'))
32
+ True
33
+ >>> parse_bool_property('no')
34
+ False
35
+ >>> parse_bool_property(None, default=False)
36
+ False
37
+ >>> parse_bool_property('YES') # Case insensitive
38
+ True
39
+
40
+ Note:
41
+ This function was added to fix a critical bug where Symbol('yes') == 'yes'
42
+ returned False, causing properties like in_bom and on_board to be parsed
43
+ incorrectly.
44
+ """
45
+ # If value is None, use default
46
+ if value is None:
47
+ return default
48
+
49
+ # Convert Symbol to string
50
+ if isinstance(value, sexpdata.Symbol):
51
+ value = str(value)
52
+
53
+ # Handle string values (case-insensitive)
54
+ if isinstance(value, str):
55
+ return value.lower() == "yes"
56
+
57
+ # Handle boolean values directly
58
+ if isinstance(value, bool):
59
+ return value
60
+
61
+ # Unexpected type - use default
62
+ logger.warning(f"Unexpected type for boolean property: {type(value)}, using default={default}")
63
+ return default
@@ -10,6 +10,7 @@ from typing import Any, Dict, List, Optional
10
10
 
11
11
  import sexpdata
12
12
 
13
+ from ...core.parsing_utils import parse_bool_property
13
14
  from ...core.types import Point
14
15
  from ..base import BaseElementParser
15
16
 
@@ -74,9 +75,15 @@ class SymbolParser(BaseElementParser):
74
75
  prop_value = str(prop_value).replace('\\"', '"')
75
76
  symbol_data["properties"][prop_name] = prop_value
76
77
  elif element_type == "in_bom":
77
- symbol_data["in_bom"] = sub_item[1] == "yes" if len(sub_item) > 1 else True
78
+ symbol_data["in_bom"] = parse_bool_property(
79
+ sub_item[1] if len(sub_item) > 1 else None,
80
+ default=True
81
+ )
78
82
  elif element_type == "on_board":
79
- symbol_data["on_board"] = sub_item[1] == "yes" if len(sub_item) > 1 else True
83
+ symbol_data["on_board"] = parse_bool_property(
84
+ sub_item[1] if len(sub_item) > 1 else None,
85
+ default=True
86
+ )
80
87
 
81
88
  return symbol_data
82
89
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kicad-sch-api
3
- Version: 0.4.1
3
+ Version: 0.4.3
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,7 @@ kicad_sch_api/core/labels.py
53
53
  kicad_sch_api/core/nets.py
54
54
  kicad_sch_api/core/no_connects.py
55
55
  kicad_sch_api/core/parser.py
56
+ kicad_sch_api/core/parsing_utils.py
56
57
  kicad_sch_api/core/pin_utils.py
57
58
  kicad_sch_api/core/schematic.py
58
59
  kicad_sch_api/core/texts.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kicad-sch-api"
7
- version = "0.4.1"
7
+ version = "0.4.3"
8
8
  description = "Professional KiCAD schematic manipulation library with exact format preservation"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes