kicad-sch-api 0.0.2__tar.gz → 0.1.0__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 (70) hide show
  1. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/review-implementation.md +2 -2
  2. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/MANIFEST.in +7 -7
  3. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/PKG-INFO +13 -17
  4. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/README.md +11 -14
  5. kicad_sch_api-0.1.0/examples/advanced_usage.py +292 -0
  6. kicad_sch_api-0.1.0/examples/basic_usage.py +184 -0
  7. kicad_sch_api-0.1.0/examples/mcp_integration.py +337 -0
  8. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/components.py +63 -0
  9. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/formatter.py +56 -11
  10. kicad_sch_api-0.1.0/kicad_sch_api/core/ic_manager.py +187 -0
  11. kicad_sch_api-0.1.0/kicad_sch_api/core/junctions.py +206 -0
  12. kicad_sch_api-0.1.0/kicad_sch_api/core/parser.py +1036 -0
  13. kicad_sch_api-0.1.0/kicad_sch_api/core/schematic.py +1209 -0
  14. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/types.py +102 -7
  15. kicad_sch_api-0.1.0/kicad_sch_api/core/wires.py +248 -0
  16. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/library/cache.py +321 -10
  17. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/utils/validation.py +1 -1
  18. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/PKG-INFO +13 -17
  19. kicad_sch_api-0.1.0/kicad_sch_api.egg-info/SOURCES.txt +63 -0
  20. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/pyproject.toml +9 -12
  21. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/README.md +228 -0
  22. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_pro +412 -0
  23. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_sch +5 -0
  24. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_pro +417 -0
  25. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_sch +1506 -0
  26. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_pro +417 -0
  27. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_sch +564 -0
  28. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_pro +417 -0
  29. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_sch +683 -0
  30. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_pro +417 -0
  31. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_sch +450 -0
  32. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_pro +421 -0
  33. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_sch +96 -0
  34. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/subcircuit1.kicad_sch +52 -0
  35. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_pro +417 -0
  36. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_sch +24 -0
  37. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_pro +417 -0
  38. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_sch +25 -0
  39. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_pro +417 -0
  40. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_sch +209 -0
  41. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_pro +417 -0
  42. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_sch +24 -0
  43. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_pro +417 -0
  44. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_sch +34 -0
  45. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_pro +417 -0
  46. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_sch +24 -0
  47. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_pro +417 -0
  48. kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_sch +279 -0
  49. kicad_sch_api-0.0.2/CHANGELOG.md +0 -77
  50. kicad_sch_api-0.0.2/CONTRIBUTING.md +0 -306
  51. kicad_sch_api-0.0.2/python/kicad_sch_api/core/parser.py +0 -456
  52. kicad_sch_api-0.0.2/python/kicad_sch_api/core/schematic.py +0 -478
  53. kicad_sch_api-0.0.2/python/kicad_sch_api.egg-info/SOURCES.txt +0 -31
  54. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/dead-code-analysis.md +0 -0
  55. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/publish-pypi.md +0 -0
  56. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/run-tests.md +0 -0
  57. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/update-and-commit.md +0 -0
  58. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/update-memory-bank.md +0 -0
  59. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/test/run-reference-tests.md +0 -0
  60. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/LICENSE +0 -0
  61. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/__init__.py +0 -0
  62. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/__init__.py +0 -0
  63. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/library/__init__.py +0 -0
  64. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/py.typed +0 -0
  65. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/utils/__init__.py +0 -0
  66. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/dependency_links.txt +0 -0
  67. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/entry_points.txt +0 -0
  68. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/requires.txt +0 -0
  69. {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/top_level.txt +0 -0
  70. {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/setup.cfg +0 -0
@@ -29,7 +29,7 @@ Performs comprehensive code review and analysis of kicad-sch-api implementation,
29
29
  - **Error handling** comprehensiveness and clarity
30
30
 
31
31
  **Key Questions**:
32
- - Does the API feel intuitive compared to kicad-skip?
32
+ - Does the API feel intuitive and pythonic?
33
33
  - Are bulk operations efficient for large schematics?
34
34
  - Is format preservation truly exact?
35
35
  - Do validation errors provide actionable feedback?
@@ -167,6 +167,6 @@ The review generates:
167
167
  - **Performance benchmarks** vs. targets
168
168
  - **API usability** assessment
169
169
  - **Improvement recommendations** prioritized by impact
170
- - **Comparison analysis** vs. kicad-skip and other alternatives
170
+ - **Comparison analysis** vs. other schematic manipulation solutions
171
171
 
172
172
  This ensures kicad-sch-api maintains professional quality standards while providing superior functionality to existing solutions.
@@ -10,15 +10,15 @@ include LICENSE
10
10
  include pyproject.toml
11
11
 
12
12
  # Include Python package data
13
- recursive-include python/kicad_sch_api *.py
14
- recursive-include python/kicad_sch_api *.json
15
- recursive-include python/kicad_sch_api *.yaml
16
- recursive-include python/kicad_sch_api *.yml
13
+ recursive-include kicad_sch_api *.py
14
+ recursive-include kicad_sch_api *.json
15
+ recursive-include kicad_sch_api *.yaml
16
+ recursive-include kicad_sch_api *.yml
17
17
 
18
18
  # Include test data (for validation)
19
- recursive-include python/tests/reference_kicad_projects *.kicad_sch
20
- recursive-include python/tests/reference_kicad_projects *.kicad_pro
21
- recursive-include python/tests/reference_kicad_projects *.md
19
+ recursive-include tests/reference_tests/reference_kicad_projects *.kicad_sch
20
+ recursive-include tests/reference_tests/reference_kicad_projects *.kicad_pro
21
+ recursive-include tests/reference_tests/reference_kicad_projects *.md
22
22
 
23
23
  # Include MCP server as documentation/examples
24
24
  recursive-include mcp-server/src *.ts
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kicad-sch-api
3
- Version: 0.0.2
3
+ Version: 0.1.0
4
4
  Summary: Professional KiCAD schematic manipulation library with exact format preservation and AI agent integration
5
5
  Author-email: Circuit-Synth <info@circuit-synth.com>
6
6
  Maintainer-email: Circuit-Synth <info@circuit-synth.com>
7
- License: MIT
7
+ License-Expression: MIT
8
8
  Project-URL: Homepage, https://github.com/circuit-synth/kicad-sch-api
9
9
  Project-URL: Documentation, https://circuit-synth.github.io/kicad-sch-api/
10
10
  Project-URL: Repository, https://github.com/circuit-synth/kicad-sch-api.git
@@ -15,7 +15,6 @@ Classifier: Development Status :: 4 - Beta
15
15
  Classifier: Intended Audience :: Developers
16
16
  Classifier: Intended Audience :: Science/Research
17
17
  Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
18
- Classifier: License :: OSI Approved :: MIT License
19
18
  Classifier: Programming Language :: Python :: 3
20
19
  Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
@@ -59,13 +58,13 @@ Dynamic: license-file
59
58
 
60
59
  ## 🆚 vs. Existing Solutions
61
60
 
62
- | Feature | kicad-sch-api | kicad-skip | KiCAD Official API |
63
- |---------|---------------|------------|-------------------|
64
- | **Schematic Support** | ✅ Full | Full | ❌ PCB Only |
61
+ | Feature | kicad-sch-api | Other Solutions | KiCAD Official API |
62
+ |---------|---------------|-----------------|-------------------|
63
+ | **Schematic Support** | ✅ Full | ⚠️ Varies | ❌ PCB Only |
65
64
  | **Format Preservation** | ✅ Exact | ❌ Basic | N/A |
66
65
  | **Performance** | ✅ Optimized | ⚠️ Basic | N/A |
67
- | **Library Management** | ✅ Advanced | ⚠️ Basic | N/A |
68
- | **Runtime Dependencies** | ❌ None | None | ✅ KiCAD Required |
66
+ | **Library Management** | ✅ Advanced | ⚠️ Limited | N/A |
67
+ | **Runtime Dependencies** | ❌ None | ⚠️ Varies | ✅ KiCAD Required |
69
68
 
70
69
  ## 📦 Installation
71
70
 
@@ -89,22 +88,19 @@ npm run build
89
88
  ```python
90
89
  import kicad_sch_api as ksa
91
90
 
92
- # Load existing schematic
93
- sch = ksa.load_schematic('my_circuit.kicad_sch')
91
+ # Create new schematic
92
+ sch = ksa.create_schematic('My Circuit')
94
93
 
95
94
  # Add components
96
- resistor = sch.components.add('Device:R', ref='R1', value='10k', pos=(100, 100))
97
- capacitor = sch.components.add('Device:C', ref='C1', value='0.1uF', pos=(150, 100))
95
+ resistor = sch.components.add('Device:R', reference='R1', value='10k', position=(100, 100))
96
+ capacitor = sch.components.add('Device:C', reference='C1', value='0.1uF', position=(150, 100))
98
97
 
99
98
  # Update properties
100
99
  resistor.footprint = 'Resistor_SMD:R_0603_1608Metric'
101
100
  resistor.set_property('MPN', 'RC0603FR-0710KL')
102
101
 
103
- # Connect components
104
- sch.add_wire(resistor.get_pin_position('2'), capacitor.get_pin_position('1'))
105
-
106
102
  # Save with exact format preservation
107
- sch.save() # Preserves original formatting exactly
103
+ sch.save('my_circuit.kicad_sch')
108
104
  ```
109
105
 
110
106
  ### Advanced Operations
@@ -204,7 +200,7 @@ MIT License - see [LICENSE](LICENSE) for details.
204
200
  ## 🔗 Related Projects
205
201
 
206
202
  - **[circuit-synth](https://github.com/circuit-synth/circuit-synth)**: Comprehensive circuit design automation
207
- - **[kicad-skip](https://github.com/psychogenic/kicad-skip)**: Foundation S-expression parser
203
+ - **[sexpdata](https://github.com/jd-boyd/sexpdata)**: S-expression parsing library
208
204
 
209
205
  ---
210
206
 
@@ -14,13 +14,13 @@
14
14
 
15
15
  ## 🆚 vs. Existing Solutions
16
16
 
17
- | Feature | kicad-sch-api | kicad-skip | KiCAD Official API |
18
- |---------|---------------|------------|-------------------|
19
- | **Schematic Support** | ✅ Full | Full | ❌ PCB Only |
17
+ | Feature | kicad-sch-api | Other Solutions | KiCAD Official API |
18
+ |---------|---------------|-----------------|-------------------|
19
+ | **Schematic Support** | ✅ Full | ⚠️ Varies | ❌ PCB Only |
20
20
  | **Format Preservation** | ✅ Exact | ❌ Basic | N/A |
21
21
  | **Performance** | ✅ Optimized | ⚠️ Basic | N/A |
22
- | **Library Management** | ✅ Advanced | ⚠️ Basic | N/A |
23
- | **Runtime Dependencies** | ❌ None | None | ✅ KiCAD Required |
22
+ | **Library Management** | ✅ Advanced | ⚠️ Limited | N/A |
23
+ | **Runtime Dependencies** | ❌ None | ⚠️ Varies | ✅ KiCAD Required |
24
24
 
25
25
  ## 📦 Installation
26
26
 
@@ -44,22 +44,19 @@ npm run build
44
44
  ```python
45
45
  import kicad_sch_api as ksa
46
46
 
47
- # Load existing schematic
48
- sch = ksa.load_schematic('my_circuit.kicad_sch')
47
+ # Create new schematic
48
+ sch = ksa.create_schematic('My Circuit')
49
49
 
50
50
  # Add components
51
- resistor = sch.components.add('Device:R', ref='R1', value='10k', pos=(100, 100))
52
- capacitor = sch.components.add('Device:C', ref='C1', value='0.1uF', pos=(150, 100))
51
+ resistor = sch.components.add('Device:R', reference='R1', value='10k', position=(100, 100))
52
+ capacitor = sch.components.add('Device:C', reference='C1', value='0.1uF', position=(150, 100))
53
53
 
54
54
  # Update properties
55
55
  resistor.footprint = 'Resistor_SMD:R_0603_1608Metric'
56
56
  resistor.set_property('MPN', 'RC0603FR-0710KL')
57
57
 
58
- # Connect components
59
- sch.add_wire(resistor.get_pin_position('2'), capacitor.get_pin_position('1'))
60
-
61
58
  # Save with exact format preservation
62
- sch.save() # Preserves original formatting exactly
59
+ sch.save('my_circuit.kicad_sch')
63
60
  ```
64
61
 
65
62
  ### Advanced Operations
@@ -159,7 +156,7 @@ MIT License - see [LICENSE](LICENSE) for details.
159
156
  ## 🔗 Related Projects
160
157
 
161
158
  - **[circuit-synth](https://github.com/circuit-synth/circuit-synth)**: Comprehensive circuit design automation
162
- - **[kicad-skip](https://github.com/psychogenic/kicad-skip)**: Foundation S-expression parser
159
+ - **[sexpdata](https://github.com/jd-boyd/sexpdata)**: S-expression parsing library
163
160
 
164
161
  ---
165
162
 
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Advanced usage example for kicad-sch-api.
4
+
5
+ Demonstrates advanced features like bulk operations, filtering,
6
+ validation, and performance optimization for large schematics.
7
+ """
8
+
9
+ import time
10
+
11
+ import kicad_sch_api as ksa
12
+ from kicad_sch_api.core.types import Point
13
+
14
+
15
+ def create_resistor_network():
16
+ """Create a large resistor network to demonstrate performance."""
17
+ print("🏗️ Creating large resistor network...")
18
+
19
+ sch = ksa.create_schematic("Resistor Network")
20
+
21
+ # Create a 10x10 grid of resistors (100 total)
22
+ resistors = []
23
+ start_time = time.time()
24
+
25
+ for row in range(10):
26
+ for col in range(10):
27
+ ref = f"R{row*10 + col + 1}"
28
+ value = f"{(row + 1) * (col + 1)}k" # Varied values
29
+ position = (col * 15 + 50, row * 15 + 50) # 15mm spacing
30
+
31
+ resistor = sch.components.add(
32
+ lib_id="Device:R",
33
+ reference=ref,
34
+ value=value,
35
+ position=position,
36
+ footprint="Resistor_SMD:R_0603_1608Metric",
37
+ )
38
+ resistors.append(resistor)
39
+
40
+ creation_time = time.time() - start_time
41
+ print(f"✅ Created {len(resistors)} resistors in {creation_time:.3f}s")
42
+
43
+ return sch, resistors
44
+
45
+
46
+ def demonstrate_filtering():
47
+ """Demonstrate advanced component filtering capabilities."""
48
+ print("\n🔍 Advanced Component Filtering:")
49
+
50
+ sch, resistors = create_resistor_network()
51
+
52
+ # Filter by lib_id
53
+ all_resistors = sch.components.filter(lib_id="Device:R")
54
+ print(f" All resistors: {len(all_resistors)}")
55
+
56
+ # Filter by value pattern
57
+ high_value = sch.components.filter(value_pattern="k")
58
+ print(f" High value (k-ohm): {len(high_value)}")
59
+
60
+ # Filter by reference pattern
61
+ import re
62
+
63
+ top_row = sch.components.filter(reference_pattern=r"R[1-9]$") # R1-R9
64
+ print(f" Top row (R1-R9): {len(top_row)}")
65
+
66
+ # Spatial filtering
67
+ center_area = sch.components.in_area(80, 80, 120, 120)
68
+ print(f" Components in center area: {len(center_area)}")
69
+
70
+ # Proximity filtering
71
+ center_point = Point(100, 100)
72
+ nearby = sch.components.near_point(center_point, radius=30)
73
+ print(f" Components near center: {len(nearby)}")
74
+
75
+ return sch
76
+
77
+
78
+ def demonstrate_bulk_operations():
79
+ """Demonstrate bulk update operations for large schematics."""
80
+ print("\n⚡ Bulk Operations Performance:")
81
+
82
+ sch = demonstrate_filtering()
83
+
84
+ # Bulk update all resistors
85
+ start_time = time.time()
86
+
87
+ updated_count = sch.components.bulk_update(
88
+ criteria={"lib_id": "Device:R"},
89
+ updates={
90
+ "properties": {
91
+ "Tolerance": "1%",
92
+ "Power": "0.1W",
93
+ "Manufacturer": "Yageo",
94
+ "Temperature_Coefficient": "100ppm/K",
95
+ }
96
+ },
97
+ )
98
+
99
+ bulk_time = time.time() - start_time
100
+ print(f"✅ Bulk updated {updated_count} components in {bulk_time:.3f}s")
101
+ print(f" Performance: {bulk_time/updated_count*1000:.2f}ms per component")
102
+
103
+ # Verify updates applied
104
+ sample_resistor = sch.components.get("R1")
105
+ if sample_resistor:
106
+ print(f" Sample properties: {len(sample_resistor.properties)} properties set")
107
+ print(f" Tolerance: {sample_resistor.get_property('Tolerance')}")
108
+ print(f" Power: {sample_resistor.get_property('Power')}")
109
+
110
+ return sch
111
+
112
+
113
+ def demonstrate_performance_monitoring():
114
+ """Demonstrate performance monitoring and statistics."""
115
+ print("\n📊 Performance Monitoring:")
116
+
117
+ sch = demonstrate_bulk_operations()
118
+
119
+ # Get comprehensive performance statistics
120
+ stats = sch.get_performance_stats()
121
+
122
+ print(" Schematic Performance:")
123
+ schematic_stats = stats.get("schematic", {})
124
+ print(f" Operations: {schematic_stats.get('operation_count', 0)}")
125
+ print(f" Avg time: {schematic_stats.get('avg_operation_time_ms', 0):.2f}ms")
126
+
127
+ print(" Component Collection:")
128
+ component_stats = stats.get("components", {})
129
+ print(f" Total components: {component_stats.get('total_components', 0)}")
130
+ print(f" Unique references: {component_stats.get('unique_references', 0)}")
131
+ print(f" Libraries used: {component_stats.get('libraries_used', 0)}")
132
+
133
+ print(" Symbol Cache:")
134
+ cache_stats = stats.get("symbol_cache", {})
135
+ print(f" Cache hit rate: {cache_stats.get('hit_rate_percent', 0):.1f}%")
136
+ print(f" Symbols cached: {cache_stats.get('total_symbols_cached', 0)}")
137
+ print(f" Total load time: {cache_stats.get('total_load_time_ms', 0):.1f}ms")
138
+
139
+ return sch
140
+
141
+
142
+ def demonstrate_validation_and_error_handling():
143
+ """Demonstrate comprehensive validation and error handling."""
144
+ print("\n✅ Validation and Error Handling:")
145
+
146
+ sch = ksa.create_schematic("Validation Test")
147
+
148
+ # Add valid components
149
+ sch.components.add("Device:R", "R1", "10k", (100, 50))
150
+ sch.components.add("Device:C", "C1", "0.1uF", (150, 50))
151
+
152
+ # Test validation
153
+ issues = sch.validate()
154
+ print(f" Validation issues found: {len(issues)}")
155
+
156
+ # Categorize issues
157
+ errors = [issue for issue in issues if issue.level.value in ("error", "critical")]
158
+ warnings = [issue for issue in issues if issue.level.value == "warning"]
159
+
160
+ print(f" Errors: {len(errors)}")
161
+ print(f" Warnings: {len(warnings)}")
162
+
163
+ if issues:
164
+ print(" Issue details:")
165
+ for issue in issues[:3]: # Show first 3
166
+ print(f" {issue.level.value.upper()}: {issue.message}")
167
+
168
+ # Demonstrate error handling
169
+ print("\n🛡️ Error Handling Examples:")
170
+
171
+ try:
172
+ # Try to add component with invalid reference
173
+ sch.components.add("Device:R", "1R", "10k") # Invalid reference
174
+ except ksa.ValidationError as e:
175
+ print(f" ✅ Caught validation error: {e}")
176
+
177
+ try:
178
+ # Try to add duplicate reference
179
+ sch.components.add("Device:C", "R1", "22uF") # Duplicate reference
180
+ except ksa.ValidationError as e:
181
+ print(f" ✅ Caught duplicate reference: {e}")
182
+
183
+ try:
184
+ # Try invalid lib_id
185
+ sch.components.add("InvalidFormat", "R5", "10k") # Missing colon
186
+ except ksa.ValidationError as e:
187
+ print(f" ✅ Caught invalid lib_id: {e}")
188
+
189
+ return sch
190
+
191
+
192
+ def demonstrate_format_preservation():
193
+ """Demonstrate exact format preservation capabilities."""
194
+ print("\n💎 Format Preservation:")
195
+
196
+ sch = ksa.create_schematic("Format Test")
197
+ sch.components.add("Device:R", "R1", "10k", (100, 50))
198
+
199
+ import os
200
+ import tempfile
201
+
202
+ # Save with format preservation
203
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".kicad_sch", delete=False) as f:
204
+ output_path = f.name
205
+
206
+ try:
207
+ start_time = time.time()
208
+ sch.save(output_path, preserve_format=True)
209
+ save_time = time.time() - start_time
210
+
211
+ print(f" ✅ Saved with format preservation in {save_time:.3f}s")
212
+
213
+ # Reload and verify
214
+ start_time = time.time()
215
+ sch2 = ksa.load_schematic(output_path)
216
+ load_time = time.time() - start_time
217
+
218
+ print(f" ✅ Reloaded in {load_time:.3f}s")
219
+ print(f" ✅ Component preservation: {len(sch2.components)} components")
220
+
221
+ # Verify component data preserved
222
+ r1_original = sch.components.get("R1")
223
+ r1_reloaded = sch2.components.get("R1")
224
+
225
+ if r1_original and r1_reloaded:
226
+ print(f" Reference: {r1_reloaded.reference} ✅")
227
+ print(f" Value: {r1_reloaded.value} ✅")
228
+ print(f" Position: {r1_reloaded.position} ✅")
229
+ print(f" Lib ID: {r1_reloaded.lib_id} ✅")
230
+
231
+ finally:
232
+ if os.path.exists(output_path):
233
+ os.unlink(output_path)
234
+
235
+
236
+ def demonstrate_library_integration():
237
+ """Demonstrate symbol library integration."""
238
+ print("\n📚 Symbol Library Integration:")
239
+
240
+ # Get global symbol cache
241
+ cache = ksa.get_symbol_cache()
242
+
243
+ # Library discovery
244
+ discovered = cache.discover_libraries()
245
+ print(f" Libraries discovered: {discovered}")
246
+
247
+ # Symbol search
248
+ symbols = cache.search_symbols("resistor", limit=5)
249
+ print(f" Resistor symbols found: {len(symbols)}")
250
+
251
+ for symbol in symbols[:3]: # Show first 3
252
+ print(f" {symbol.lib_id}: {symbol.description}")
253
+
254
+ # Cache performance
255
+ cache_stats = cache.get_performance_stats()
256
+ print(f" Cache performance:")
257
+ print(f" Hit rate: {cache_stats.get('hit_rate_percent', 0):.1f}%")
258
+ print(f" Total symbols: {cache_stats.get('total_symbols_cached', 0)}")
259
+
260
+
261
+ def main():
262
+ """Run all advanced usage examples."""
263
+ print("🚀 kicad-sch-api Advanced Usage Examples")
264
+ print("=" * 60)
265
+
266
+ try:
267
+ # Run all demonstrations
268
+ demonstrate_filtering()
269
+ demonstrate_bulk_operations()
270
+ demonstrate_performance_monitoring()
271
+ demonstrate_validation_and_error_handling()
272
+ demonstrate_format_preservation()
273
+ demonstrate_library_integration()
274
+
275
+ print("\n🎉 All advanced examples completed successfully!")
276
+ print("\nAdvanced features demonstrated:")
277
+ print(" ✅ High-performance component collections")
278
+ print(" ✅ Bulk operations for large schematics")
279
+ print(" ✅ Comprehensive validation and error handling")
280
+ print(" ✅ Exact format preservation")
281
+ print(" ✅ Symbol library caching and discovery")
282
+ print(" ✅ Performance monitoring and statistics")
283
+
284
+ except Exception as e:
285
+ print(f"\n❌ Example failed: {e}")
286
+ import traceback
287
+
288
+ traceback.print_exc()
289
+
290
+
291
+ if __name__ == "__main__":
292
+ main()
@@ -0,0 +1,184 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Basic usage example for kicad-sch-api.
4
+
5
+ This example demonstrates the core functionality of kicad-sch-api,
6
+ showing how to create, manipulate, and save KiCAD schematic files.
7
+ """
8
+
9
+ import kicad_sch_api as ksa
10
+
11
+
12
+ def main():
13
+ """Demonstrate basic kicad-sch-api usage."""
14
+ print("🚀 kicad-sch-api Basic Usage Example")
15
+ print("=" * 50)
16
+
17
+ # 1. Create a new schematic
18
+ print("\n📋 Creating new schematic...")
19
+ sch = ksa.create_schematic("Voltage Divider Example")
20
+ print(f"✅ Created schematic: {sch.title_block.get('title', 'Untitled')}")
21
+
22
+ # 2. Add components
23
+ print("\n🔧 Adding components...")
24
+
25
+ # Add input resistor
26
+ r1 = sch.components.add(
27
+ lib_id="Device:R",
28
+ reference="R1",
29
+ value="10k",
30
+ position=(100, 100),
31
+ footprint="Resistor_SMD:R_0603_1608Metric",
32
+ )
33
+ print(f"✅ Added {r1.reference}: {r1.value} at {r1.position}")
34
+
35
+ # Add output resistor
36
+ r2 = sch.components.add(
37
+ lib_id="Device:R",
38
+ reference="R2",
39
+ value="10k",
40
+ position=(100, 150),
41
+ footprint="Resistor_SMD:R_0603_1608Metric",
42
+ )
43
+ print(f"✅ Added {r2.reference}: {r2.value} at {r2.position}")
44
+
45
+ # Add input capacitor for filtering
46
+ c1 = sch.components.add(
47
+ lib_id="Device:C",
48
+ reference="C1",
49
+ value="0.1uF",
50
+ position=(50, 125),
51
+ footprint="Capacitor_SMD:C_0603_1608Metric",
52
+ )
53
+ print(f"✅ Added {c1.reference}: {c1.value} at {c1.position}")
54
+
55
+ # 3. Set component properties
56
+ print("\n📝 Setting component properties...")
57
+
58
+ r1.set_property("MPN", "RC0603FR-0710KL")
59
+ r1.set_property("Tolerance", "1%")
60
+ r2.set_property("MPN", "RC0603FR-0710KL")
61
+ r2.set_property("Tolerance", "1%")
62
+ c1.set_property("MPN", "CL10B104KB8NNNC")
63
+ c1.set_property("Voltage", "50V")
64
+
65
+ print(f"✅ Set properties for all components")
66
+
67
+ # 4. Add connections
68
+ print("\n🔗 Adding wire connections...")
69
+
70
+ # Get pin positions for connections
71
+ r1_pin1 = r1.get_pin_position("1") # Top of R1
72
+ r1_pin2 = r1.get_pin_position("2") # Bottom of R1
73
+ r2_pin1 = r2.get_pin_position("1") # Top of R2
74
+ r2_pin2 = r2.get_pin_position("2") # Bottom of R2
75
+ c1_pin1 = c1.get_pin_position("1") # Left of C1
76
+
77
+ if all([r1_pin1, r1_pin2, r2_pin1, r2_pin2, c1_pin1]):
78
+ # Connect R1 bottom to R2 top (voltage divider middle)
79
+ wire1 = sch.add_wire(r1_pin2, r2_pin1)
80
+ print(f"✅ Connected R1 pin 2 to R2 pin 1")
81
+
82
+ # Connect input capacitor to R1 top
83
+ wire2 = sch.add_wire(c1_pin1, r1_pin1)
84
+ print(f"✅ Connected C1 to R1 input")
85
+ else:
86
+ print("⚠️ Could not determine pin positions for connections")
87
+
88
+ # 5. Display schematic information
89
+ print("\n📊 Schematic Summary:")
90
+ summary = sch.get_summary()
91
+ print(f" Components: {summary['component_count']}")
92
+ print(f" Title: {summary['title']}")
93
+ print(f" Modified: {summary['modified']}")
94
+
95
+ # 6. Component analysis
96
+ print("\n🔍 Component Analysis:")
97
+
98
+ # Find all resistors
99
+ resistors = sch.components.filter(lib_id="Device:R")
100
+ print(f" Resistors found: {len(resistors)}")
101
+
102
+ # Find components by value
103
+ ten_k_components = sch.components.filter(value="10k")
104
+ print(f" 10k components: {len(ten_k_components)}")
105
+
106
+ # Find components in area
107
+ left_side = sch.components.in_area(40, 90, 80, 160)
108
+ print(f" Components on left side: {len(left_side)}")
109
+
110
+ # 7. Bulk operations
111
+ print("\n⚡ Bulk Operations:")
112
+
113
+ # Update all resistors with tolerance
114
+ updated_count = sch.components.bulk_update(
115
+ criteria={"lib_id": "Device:R"}, updates={"properties": {"Power": "0.1W"}}
116
+ )
117
+ print(f"✅ Updated {updated_count} resistors with power rating")
118
+
119
+ # 8. Validation
120
+ print("\n✅ Validation:")
121
+ issues = sch.validate()
122
+ errors = [issue for issue in issues if issue.level.value in ("error", "critical")]
123
+ warnings = [issue for issue in issues if issue.level.value == "warning"]
124
+
125
+ print(f" Validation issues: {len(issues)} total")
126
+ print(f" Errors: {len(errors)}")
127
+ print(f" Warnings: {len(warnings)}")
128
+
129
+ if errors:
130
+ print(" ❌ Critical errors found:")
131
+ for error in errors[:3]: # Show first 3
132
+ print(f" - {error}")
133
+ else:
134
+ print(" ✅ No critical errors found")
135
+
136
+ # 9. Performance statistics
137
+ print("\n⚡ Performance Statistics:")
138
+ perf_stats = sch.get_performance_stats()
139
+
140
+ if "symbol_cache" in perf_stats:
141
+ cache_stats = perf_stats["symbol_cache"]
142
+ print(f" Symbol cache hit rate: {cache_stats.get('hit_rate_percent', 0)}%")
143
+ print(f" Symbols cached: {cache_stats.get('total_symbols_cached', 0)}")
144
+
145
+ comp_stats = perf_stats.get("components", {})
146
+ print(f" Total components: {comp_stats.get('total_components', 0)}")
147
+
148
+ # 10. Save schematic
149
+ print("\n💾 Saving schematic...")
150
+ import os
151
+ import tempfile
152
+
153
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".kicad_sch", delete=False) as f:
154
+ output_path = f.name
155
+
156
+ try:
157
+ sch.save(output_path, preserve_format=True)
158
+ print(f"✅ Saved schematic to: {output_path}")
159
+
160
+ # Verify file was created and has content
161
+ file_size = os.path.getsize(output_path)
162
+ print(f" File size: {file_size} bytes")
163
+
164
+ # Quick validation by reloading
165
+ sch2 = ksa.load_schematic(output_path)
166
+ print(f"✅ Reload verification: {len(sch2.components)} components")
167
+
168
+ finally:
169
+ # Clean up temporary file
170
+ if os.path.exists(output_path):
171
+ os.unlink(output_path)
172
+ print(f"🧹 Cleaned up temporary file")
173
+
174
+ print("\n🎉 Basic usage example completed successfully!")
175
+ print("\nKey takeaways:")
176
+ print(" • Modern API: Clean, pythonic interface for schematic manipulation")
177
+ print(" • Fast operations: O(1) component lookup and bulk updates")
178
+ print(" • Format preservation: Exact KiCAD compatibility guaranteed")
179
+ print(" • Professional validation: Comprehensive error detection")
180
+ print(" • Performance monitoring: Built-in statistics and optimization")
181
+
182
+
183
+ if __name__ == "__main__":
184
+ main()