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.
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/review-implementation.md +2 -2
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/MANIFEST.in +7 -7
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/PKG-INFO +13 -17
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/README.md +11 -14
- kicad_sch_api-0.1.0/examples/advanced_usage.py +292 -0
- kicad_sch_api-0.1.0/examples/basic_usage.py +184 -0
- kicad_sch_api-0.1.0/examples/mcp_integration.py +337 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/components.py +63 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/formatter.py +56 -11
- kicad_sch_api-0.1.0/kicad_sch_api/core/ic_manager.py +187 -0
- kicad_sch_api-0.1.0/kicad_sch_api/core/junctions.py +206 -0
- kicad_sch_api-0.1.0/kicad_sch_api/core/parser.py +1036 -0
- kicad_sch_api-0.1.0/kicad_sch_api/core/schematic.py +1209 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/types.py +102 -7
- kicad_sch_api-0.1.0/kicad_sch_api/core/wires.py +248 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/library/cache.py +321 -10
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/utils/validation.py +1 -1
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/PKG-INFO +13 -17
- kicad_sch_api-0.1.0/kicad_sch_api.egg-info/SOURCES.txt +63 -0
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/pyproject.toml +9 -12
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/README.md +228 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_pro +412 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/blank_schematic/blank_schematic.kicad_sch +5 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/multi_unit_7400/multi_unit_7400.kicad_sch +1506 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/power_symbols/power_symbols.kicad_sch +564 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/resistor_divider/resistor_divider.kicad_sch +683 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_extended_component/single_extended_component.kicad_sch +450 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_pro +421 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/single_hierarchical_sheet.kicad_sch +96 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_hierarchical_sheet/subcircuit1.kicad_sch +52 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label/single_label.kicad_sch +24 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_label_hierarchical/single_label_hierarchical.kicad_sch +25 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_resistor/single_resistor.kicad_sch +209 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text/single_text.kicad_sch +24 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_text_box/single_text_box.kicad_sch +34 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/single_wire/single_wire.kicad_sch +24 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_pro +417 -0
- kicad_sch_api-0.1.0/tests/reference_tests/reference_kicad_projects/two_resistors/two_resistors.kicad_sch +279 -0
- kicad_sch_api-0.0.2/CHANGELOG.md +0 -77
- kicad_sch_api-0.0.2/CONTRIBUTING.md +0 -306
- kicad_sch_api-0.0.2/python/kicad_sch_api/core/parser.py +0 -456
- kicad_sch_api-0.0.2/python/kicad_sch_api/core/schematic.py +0 -478
- kicad_sch_api-0.0.2/python/kicad_sch_api.egg-info/SOURCES.txt +0 -31
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/dead-code-analysis.md +0 -0
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/publish-pypi.md +0 -0
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/run-tests.md +0 -0
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/update-and-commit.md +0 -0
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/dev/update-memory-bank.md +0 -0
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/.claude/commands/test/run-reference-tests.md +0 -0
- {kicad_sch_api-0.0.2 → kicad_sch_api-0.1.0}/LICENSE +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/__init__.py +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/core/__init__.py +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/library/__init__.py +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/py.typed +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api/utils/__init__.py +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/dependency_links.txt +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/entry_points.txt +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/requires.txt +0 -0
- {kicad_sch_api-0.0.2/python → kicad_sch_api-0.1.0}/kicad_sch_api.egg-info/top_level.txt +0 -0
- {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
|
|
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.
|
|
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
|
|
14
|
-
recursive-include
|
|
15
|
-
recursive-include
|
|
16
|
-
recursive-include
|
|
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
|
|
20
|
-
recursive-include
|
|
21
|
-
recursive-include
|
|
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
|
|
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 |
|
|
63
|
-
|
|
64
|
-
| **Schematic Support** | ✅ Full |
|
|
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 | ⚠️
|
|
68
|
-
| **Runtime Dependencies** | ❌ None |
|
|
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
|
-
#
|
|
93
|
-
sch = ksa.
|
|
91
|
+
# Create new schematic
|
|
92
|
+
sch = ksa.create_schematic('My Circuit')
|
|
94
93
|
|
|
95
94
|
# Add components
|
|
96
|
-
resistor = sch.components.add('Device:R',
|
|
97
|
-
capacitor = sch.components.add('Device:C',
|
|
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()
|
|
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
|
-
- **[
|
|
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 |
|
|
18
|
-
|
|
19
|
-
| **Schematic Support** | ✅ Full |
|
|
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 | ⚠️
|
|
23
|
-
| **Runtime Dependencies** | ❌ None |
|
|
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
|
-
#
|
|
48
|
-
sch = ksa.
|
|
47
|
+
# Create new schematic
|
|
48
|
+
sch = ksa.create_schematic('My Circuit')
|
|
49
49
|
|
|
50
50
|
# Add components
|
|
51
|
-
resistor = sch.components.add('Device:R',
|
|
52
|
-
capacitor = sch.components.add('Device:C',
|
|
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()
|
|
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
|
-
- **[
|
|
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()
|