schemaseed 1.0.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.
- schemaseed-1.0.0/LICENSE +21 -0
- schemaseed-1.0.0/PKG-INFO +232 -0
- schemaseed-1.0.0/README.md +201 -0
- schemaseed-1.0.0/pyproject.toml +58 -0
- schemaseed-1.0.0/schemaseed/__init__.py +3 -0
- schemaseed-1.0.0/schemaseed/__main__.py +56 -0
- schemaseed-1.0.0/schemaseed/_skeleton_demo.py +31 -0
- schemaseed-1.0.0/schemaseed/canonicalize/__init__.py +1 -0
- schemaseed-1.0.0/schemaseed/canonicalize/netnames.py +176 -0
- schemaseed-1.0.0/schemaseed/cli.py +201 -0
- schemaseed-1.0.0/schemaseed/connectivity/__init__.py +1 -0
- schemaseed-1.0.0/schemaseed/connectivity/label_emitter.py +82 -0
- schemaseed-1.0.0/schemaseed/connectivity/power_emitter.py +161 -0
- schemaseed-1.0.0/schemaseed/emit/__init__.py +1 -0
- schemaseed-1.0.0/schemaseed/emit/kicad10_writer.py +240 -0
- schemaseed-1.0.0/schemaseed/emit/uuids.py +74 -0
- schemaseed-1.0.0/schemaseed/errors.py +52 -0
- schemaseed-1.0.0/schemaseed/generate.py +174 -0
- schemaseed-1.0.0/schemaseed/input/__init__.py +1 -0
- schemaseed-1.0.0/schemaseed/input/native_loader.py +305 -0
- schemaseed-1.0.0/schemaseed/input/netlist_adapter.py +197 -0
- schemaseed-1.0.0/schemaseed/model.py +91 -0
- schemaseed-1.0.0/schemaseed/placement/__init__.py +1 -0
- schemaseed-1.0.0/schemaseed/placement/grid_placer.py +75 -0
- schemaseed-1.0.0/schemaseed/report.py +107 -0
- schemaseed-1.0.0/schemaseed/resolve.py +214 -0
- schemaseed-1.0.0/schemaseed/symbols/__init__.py +1 -0
- schemaseed-1.0.0/schemaseed/symbols/discovery.py +75 -0
- schemaseed-1.0.0/schemaseed/symbols/lib_table.py +263 -0
- schemaseed-1.0.0/schemaseed/symbols/resolved.py +87 -0
- schemaseed-1.0.0/schemaseed/symbols/symbol_reader.py +102 -0
- schemaseed-1.0.0/schemaseed/verify/__init__.py +1 -0
- schemaseed-1.0.0/schemaseed/verify/geometric_oracle.py +87 -0
- schemaseed-1.0.0/schemaseed/verify/roundtrip_oracle.py +98 -0
- schemaseed-1.0.0/schemaseed.egg-info/PKG-INFO +232 -0
- schemaseed-1.0.0/schemaseed.egg-info/SOURCES.txt +52 -0
- schemaseed-1.0.0/schemaseed.egg-info/dependency_links.txt +1 -0
- schemaseed-1.0.0/schemaseed.egg-info/entry_points.txt +2 -0
- schemaseed-1.0.0/schemaseed.egg-info/requires.txt +8 -0
- schemaseed-1.0.0/schemaseed.egg-info/top_level.txt +1 -0
- schemaseed-1.0.0/setup.cfg +4 -0
- schemaseed-1.0.0/tests/test_canonicalize.py +137 -0
- schemaseed-1.0.0/tests/test_check_integration.py +198 -0
- schemaseed-1.0.0/tests/test_connectivity.py +112 -0
- schemaseed-1.0.0/tests/test_emit.py +150 -0
- schemaseed-1.0.0/tests/test_generate_integration.py +178 -0
- schemaseed-1.0.0/tests/test_golden.py +85 -0
- schemaseed-1.0.0/tests/test_input.py +193 -0
- schemaseed-1.0.0/tests/test_netlist_adapter.py +145 -0
- schemaseed-1.0.0/tests/test_oracles.py +120 -0
- schemaseed-1.0.0/tests/test_placement.py +88 -0
- schemaseed-1.0.0/tests/test_power_emitter.py +114 -0
- schemaseed-1.0.0/tests/test_resolve.py +145 -0
- schemaseed-1.0.0/tests/test_symbols.py +317 -0
schemaseed-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PalBotics
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: schemaseed
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Data-driven KiCad schematic generator
|
|
5
|
+
Author-email: PalBotics <p.lydick@draftekdesign.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/PalBotics/schemaseed
|
|
8
|
+
Project-URL: Repository, https://github.com/PalBotics/schemaseed
|
|
9
|
+
Project-URL: Issues, https://github.com/PalBotics/schemaseed/issues
|
|
10
|
+
Keywords: kicad,schematic,eda,hardware,pcb
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Requires-Python: >=3.12
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: kiutils>=1.4.8
|
|
24
|
+
Requires-Dist: pyyaml>=6.0
|
|
25
|
+
Requires-Dist: typer>=0.12
|
|
26
|
+
Requires-Dist: sexpdata>=1.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# SchemaSeed
|
|
33
|
+
|
|
34
|
+
**Data-driven KiCad schematic generator.** Describe your circuit as a structured YAML or netlist file — SchemaSeed emits a `.kicad_sch` with symbols placed and connected, verified by two built-in correctness oracles.
|
|
35
|
+
|
|
36
|
+
[](https://github.com/PalBotics/schemaseed/actions/workflows/ci.yml)
|
|
37
|
+
[](https://pypi.org/project/schemaseed/)
|
|
38
|
+
[](https://www.python.org/downloads/)
|
|
39
|
+
[](https://www.kicad.org/)
|
|
40
|
+
[](LICENSE)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## What it does
|
|
45
|
+
|
|
46
|
+
SchemaSeed closes a gap in hardware workflows where the schematic is typically assembled by hand and used as the source of truth. SchemaSeed inverts this: you write a concise circuit description, and the tool generates a schematic you can open directly in KiCad, run ERC on, and push to PCB layout — without placing a single symbol by hand.
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
# power_protection.yaml
|
|
50
|
+
meta:
|
|
51
|
+
title: power_protection
|
|
52
|
+
|
|
53
|
+
parts:
|
|
54
|
+
- ref: Q1
|
|
55
|
+
symbol: Transistor_FET:Q_PMOS_GSD
|
|
56
|
+
value: DMG2305UX
|
|
57
|
+
footprint: Package_TO_SOT_SMD:SOT-23
|
|
58
|
+
- ref: R1
|
|
59
|
+
symbol: Device:R
|
|
60
|
+
value: 100k
|
|
61
|
+
footprint: Resistor_SMD:R_0402_1005Metric
|
|
62
|
+
# ...
|
|
63
|
+
|
|
64
|
+
nets:
|
|
65
|
+
GATE: [Q1.1, R1.1]
|
|
66
|
+
GND: [R1.2]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
schemaseed generate examples/power_protection.yaml
|
|
71
|
+
parts: 9 nets: 7 labels: 14 power symbols: 6
|
|
72
|
+
oracles: geometric PASS, round-trip PASS
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Requirements
|
|
78
|
+
|
|
79
|
+
- Python 3.12+
|
|
80
|
+
- KiCad 10.x installed (for symbol library resolution)
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Installation
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install schemaseed
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Or from source:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/PalBotics/schemaseed.git
|
|
94
|
+
cd schemaseed
|
|
95
|
+
pip install -e ".[dev]"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Quick start
|
|
101
|
+
|
|
102
|
+
### Generate a schematic from YAML
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
schemaseed generate examples/power_protection.yaml
|
|
106
|
+
schemaseed generate examples/power_protection.yaml -o out/my_circuit.kicad_sch
|
|
107
|
+
schemaseed generate examples/power_protection.yaml --grid-pitch 25.4
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Generate from a KiCad netlist
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
schemaseed generate my_project.net -o out/my_project.kicad_sch
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Validate without generating
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
schemaseed check examples/power_protection.yaml
|
|
120
|
+
schemaseed check examples/power_protection.yaml --strict --report-file out/report.txt
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Search available symbols
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
schemaseed symbols search R
|
|
127
|
+
schemaseed symbols search LM358 --lib-path /path/to/custom/libs
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Input format
|
|
133
|
+
|
|
134
|
+
SchemaSeed accepts two input formats:
|
|
135
|
+
|
|
136
|
+
**Native YAML/JSON** (recommended) — write your circuit description directly:
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
meta:
|
|
140
|
+
title: my_circuit
|
|
141
|
+
|
|
142
|
+
parts:
|
|
143
|
+
- ref: R1
|
|
144
|
+
symbol: Device:R # KiCad library:symbol
|
|
145
|
+
value: 10k
|
|
146
|
+
footprint: Resistor_SMD:R_0402_1005Metric
|
|
147
|
+
|
|
148
|
+
nets:
|
|
149
|
+
VIN: [R1.1] # terse form: ref.pin
|
|
150
|
+
GND: [R1.2]
|
|
151
|
+
# Verbose form with explicit pin discriminator:
|
|
152
|
+
SIG:
|
|
153
|
+
- {ref: R1, pin: "1", by: number}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**KiCad netlist** (`.net`, `kicadsexpr` format) — export from KiCad and feed directly:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
kicad-cli sch export netlist --format kicadsexpr my_project.kicad_sch -o my_project.net
|
|
160
|
+
schemaseed generate my_project.net
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Correctness oracles
|
|
166
|
+
|
|
167
|
+
SchemaSeed runs two oracles on every generated schematic:
|
|
168
|
+
|
|
169
|
+
**Geometric oracle** (pre-write): Every net label coordinate is verified against the known pin endpoint before the file is written. Catches arithmetic bugs before they reach disk.
|
|
170
|
+
|
|
171
|
+
**Round-trip oracle** (post-write): The emitted schematic is parsed back via kiutils, labels are matched to pin endpoints, and the reconstructed netlist is compared against the input. Catches kiutils serialization surprises.
|
|
172
|
+
|
|
173
|
+
Both oracles must pass for the generate command to succeed. Oracle failures exit with code 4 (generator bug) — not a user error.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## CLI reference
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
schemaseed generate INPUT [-o OUTPUT] [--lib-path PATH]
|
|
181
|
+
[--grid-pitch MM] [--no-power-symbols]
|
|
182
|
+
[--power-nets NET=power:SYMBOL]
|
|
183
|
+
[--strict] [--verify-erc]
|
|
184
|
+
|
|
185
|
+
schemaseed check INPUT [--strict] [--format yaml|json]
|
|
186
|
+
[--lib-path PATH] [--report-file PATH]
|
|
187
|
+
|
|
188
|
+
schemaseed symbols search QUERY [--lib-path PATH] [--project-dir PATH]
|
|
189
|
+
|
|
190
|
+
schemaseed version
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Exit codes
|
|
196
|
+
|
|
197
|
+
| Code | Meaning |
|
|
198
|
+
|------|---------|
|
|
199
|
+
| 0 | Success |
|
|
200
|
+
| 1 | Validation or data error (malformed input, ambiguous pin reference) |
|
|
201
|
+
| 2 | Symbol resolution failure (library not found, symbol not in library) |
|
|
202
|
+
| 4 | Generator bug — oracle assertion failed |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Known limitations (v1.0)
|
|
207
|
+
|
|
208
|
+
- **Grid placement only** — parts are placed in a single row with fixed spacing. Manual rearrangement in KiCad is expected for production schematics.
|
|
209
|
+
- **No rotation** — all symbols placed at angle 0.
|
|
210
|
+
- **Single-sheet schematics** — hierarchical sheets not yet supported.
|
|
211
|
+
- **KiCad 10 only** — earlier KiCad versions are not tested.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
git clone https://github.com/PalBotics/schemaseed.git
|
|
219
|
+
cd schemaseed
|
|
220
|
+
pip install -e ".[dev]"
|
|
221
|
+
python -m pytest tests/ -v
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Tests requiring a real KiCad install skip automatically on machines without one. The portable suite (non-KiCad tests) runs anywhere.
|
|
225
|
+
|
|
226
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## License
|
|
231
|
+
|
|
232
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# SchemaSeed
|
|
2
|
+
|
|
3
|
+
**Data-driven KiCad schematic generator.** Describe your circuit as a structured YAML or netlist file — SchemaSeed emits a `.kicad_sch` with symbols placed and connected, verified by two built-in correctness oracles.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/PalBotics/schemaseed/actions/workflows/ci.yml)
|
|
6
|
+
[](https://pypi.org/project/schemaseed/)
|
|
7
|
+
[](https://www.python.org/downloads/)
|
|
8
|
+
[](https://www.kicad.org/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
SchemaSeed closes a gap in hardware workflows where the schematic is typically assembled by hand and used as the source of truth. SchemaSeed inverts this: you write a concise circuit description, and the tool generates a schematic you can open directly in KiCad, run ERC on, and push to PCB layout — without placing a single symbol by hand.
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
# power_protection.yaml
|
|
19
|
+
meta:
|
|
20
|
+
title: power_protection
|
|
21
|
+
|
|
22
|
+
parts:
|
|
23
|
+
- ref: Q1
|
|
24
|
+
symbol: Transistor_FET:Q_PMOS_GSD
|
|
25
|
+
value: DMG2305UX
|
|
26
|
+
footprint: Package_TO_SOT_SMD:SOT-23
|
|
27
|
+
- ref: R1
|
|
28
|
+
symbol: Device:R
|
|
29
|
+
value: 100k
|
|
30
|
+
footprint: Resistor_SMD:R_0402_1005Metric
|
|
31
|
+
# ...
|
|
32
|
+
|
|
33
|
+
nets:
|
|
34
|
+
GATE: [Q1.1, R1.1]
|
|
35
|
+
GND: [R1.2]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
schemaseed generate examples/power_protection.yaml
|
|
40
|
+
parts: 9 nets: 7 labels: 14 power symbols: 6
|
|
41
|
+
oracles: geometric PASS, round-trip PASS
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Requirements
|
|
47
|
+
|
|
48
|
+
- Python 3.12+
|
|
49
|
+
- KiCad 10.x installed (for symbol library resolution)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install schemaseed
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or from source:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git clone https://github.com/PalBotics/schemaseed.git
|
|
63
|
+
cd schemaseed
|
|
64
|
+
pip install -e ".[dev]"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quick start
|
|
70
|
+
|
|
71
|
+
### Generate a schematic from YAML
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
schemaseed generate examples/power_protection.yaml
|
|
75
|
+
schemaseed generate examples/power_protection.yaml -o out/my_circuit.kicad_sch
|
|
76
|
+
schemaseed generate examples/power_protection.yaml --grid-pitch 25.4
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Generate from a KiCad netlist
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
schemaseed generate my_project.net -o out/my_project.kicad_sch
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Validate without generating
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
schemaseed check examples/power_protection.yaml
|
|
89
|
+
schemaseed check examples/power_protection.yaml --strict --report-file out/report.txt
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Search available symbols
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
schemaseed symbols search R
|
|
96
|
+
schemaseed symbols search LM358 --lib-path /path/to/custom/libs
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Input format
|
|
102
|
+
|
|
103
|
+
SchemaSeed accepts two input formats:
|
|
104
|
+
|
|
105
|
+
**Native YAML/JSON** (recommended) — write your circuit description directly:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
meta:
|
|
109
|
+
title: my_circuit
|
|
110
|
+
|
|
111
|
+
parts:
|
|
112
|
+
- ref: R1
|
|
113
|
+
symbol: Device:R # KiCad library:symbol
|
|
114
|
+
value: 10k
|
|
115
|
+
footprint: Resistor_SMD:R_0402_1005Metric
|
|
116
|
+
|
|
117
|
+
nets:
|
|
118
|
+
VIN: [R1.1] # terse form: ref.pin
|
|
119
|
+
GND: [R1.2]
|
|
120
|
+
# Verbose form with explicit pin discriminator:
|
|
121
|
+
SIG:
|
|
122
|
+
- {ref: R1, pin: "1", by: number}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**KiCad netlist** (`.net`, `kicadsexpr` format) — export from KiCad and feed directly:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
kicad-cli sch export netlist --format kicadsexpr my_project.kicad_sch -o my_project.net
|
|
129
|
+
schemaseed generate my_project.net
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Correctness oracles
|
|
135
|
+
|
|
136
|
+
SchemaSeed runs two oracles on every generated schematic:
|
|
137
|
+
|
|
138
|
+
**Geometric oracle** (pre-write): Every net label coordinate is verified against the known pin endpoint before the file is written. Catches arithmetic bugs before they reach disk.
|
|
139
|
+
|
|
140
|
+
**Round-trip oracle** (post-write): The emitted schematic is parsed back via kiutils, labels are matched to pin endpoints, and the reconstructed netlist is compared against the input. Catches kiutils serialization surprises.
|
|
141
|
+
|
|
142
|
+
Both oracles must pass for the generate command to succeed. Oracle failures exit with code 4 (generator bug) — not a user error.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## CLI reference
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
schemaseed generate INPUT [-o OUTPUT] [--lib-path PATH]
|
|
150
|
+
[--grid-pitch MM] [--no-power-symbols]
|
|
151
|
+
[--power-nets NET=power:SYMBOL]
|
|
152
|
+
[--strict] [--verify-erc]
|
|
153
|
+
|
|
154
|
+
schemaseed check INPUT [--strict] [--format yaml|json]
|
|
155
|
+
[--lib-path PATH] [--report-file PATH]
|
|
156
|
+
|
|
157
|
+
schemaseed symbols search QUERY [--lib-path PATH] [--project-dir PATH]
|
|
158
|
+
|
|
159
|
+
schemaseed version
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Exit codes
|
|
165
|
+
|
|
166
|
+
| Code | Meaning |
|
|
167
|
+
|------|---------|
|
|
168
|
+
| 0 | Success |
|
|
169
|
+
| 1 | Validation or data error (malformed input, ambiguous pin reference) |
|
|
170
|
+
| 2 | Symbol resolution failure (library not found, symbol not in library) |
|
|
171
|
+
| 4 | Generator bug — oracle assertion failed |
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Known limitations (v1.0)
|
|
176
|
+
|
|
177
|
+
- **Grid placement only** — parts are placed in a single row with fixed spacing. Manual rearrangement in KiCad is expected for production schematics.
|
|
178
|
+
- **No rotation** — all symbols placed at angle 0.
|
|
179
|
+
- **Single-sheet schematics** — hierarchical sheets not yet supported.
|
|
180
|
+
- **KiCad 10 only** — earlier KiCad versions are not tested.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Development
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
git clone https://github.com/PalBotics/schemaseed.git
|
|
188
|
+
cd schemaseed
|
|
189
|
+
pip install -e ".[dev]"
|
|
190
|
+
python -m pytest tests/ -v
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Tests requiring a real KiCad install skip automatically on machines without one. The portable suite (non-KiCad tests) runs anywhere.
|
|
194
|
+
|
|
195
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "schemaseed"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Data-driven KiCad schematic generator"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "PalBotics", email = "p.lydick@draftekdesign.com"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["kicad", "schematic", "eda", "hardware", "pcb"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
|
|
25
|
+
"Operating System :: OS Independent",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"kiutils>=1.4.8",
|
|
29
|
+
"pyyaml>=6.0",
|
|
30
|
+
"typer>=0.12",
|
|
31
|
+
"sexpdata>=1.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/PalBotics/schemaseed"
|
|
36
|
+
Repository = "https://github.com/PalBotics/schemaseed"
|
|
37
|
+
Issues = "https://github.com/PalBotics/schemaseed/issues"
|
|
38
|
+
|
|
39
|
+
[project.scripts]
|
|
40
|
+
schemaseed = "schemaseed.cli:app"
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
dev = ["pytest>=8", "ruff>=0.4"]
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.packages.find]
|
|
46
|
+
where = ["."]
|
|
47
|
+
include = ["schemaseed*"]
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
testpaths = ["tests"]
|
|
51
|
+
|
|
52
|
+
[tool.ruff]
|
|
53
|
+
line-length = 100
|
|
54
|
+
target-version = "py312"
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint]
|
|
57
|
+
select = ["E", "F", "I"]
|
|
58
|
+
ignore = ["E501"]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
__main__.py — SchemaSeed M1 walking-skeleton entry point (unchanged behavior).
|
|
3
|
+
|
|
4
|
+
Run with:
|
|
5
|
+
python -m schemaseed
|
|
6
|
+
|
|
7
|
+
Emits: out/skeleton.kicad_sch (relative to the project root)
|
|
8
|
+
|
|
9
|
+
NOTE (M2): this still uses the M1 demo shapes (SkeletonCircuit/SkeletonPart
|
|
10
|
+
from _skeleton_demo.py), NOT the real Circuit/Part model in model.py. That
|
|
11
|
+
real model is now used by `schemaseed check` (see cli.py) instead. This demo
|
|
12
|
+
entry point will be retired once `generate` (M4/M5) supersedes it.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
from schemaseed._skeleton_demo import SkeletonCircuit, SkeletonPart
|
|
20
|
+
from schemaseed.emit.kicad10_writer import write
|
|
21
|
+
|
|
22
|
+
_PKG_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
23
|
+
_PROJECT_ROOT = os.path.normpath(os.path.join(_PKG_DIR, ".."))
|
|
24
|
+
|
|
25
|
+
_TORTURE_LIB = os.path.normpath(
|
|
26
|
+
os.path.join(_PROJECT_ROOT, "spike", "fixtures", "torture.kicad_sym")
|
|
27
|
+
)
|
|
28
|
+
_OUT_PATH = os.path.normpath(
|
|
29
|
+
os.path.join(_PROJECT_ROOT, "out", "skeleton.kicad_sch")
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main() -> None:
|
|
34
|
+
if not os.path.exists(_TORTURE_LIB):
|
|
35
|
+
raise FileNotFoundError(
|
|
36
|
+
f"Torture fixture not found at: {_TORTURE_LIB}\n"
|
|
37
|
+
"Make sure the M0 spike fixtures are present at spike/fixtures/."
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
circuit = SkeletonCircuit(
|
|
41
|
+
name="skeleton",
|
|
42
|
+
parts=[
|
|
43
|
+
SkeletonPart(
|
|
44
|
+
ref="J1",
|
|
45
|
+
lib_path=_TORTURE_LIB,
|
|
46
|
+
symbol_name="MYPART",
|
|
47
|
+
value="MYPART",
|
|
48
|
+
)
|
|
49
|
+
],
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
write(circuit, _OUT_PATH)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if __name__ == "__main__":
|
|
56
|
+
main()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""
|
|
2
|
+
_skeleton_demo.py — M1's original throwaway data shapes, relocated.
|
|
3
|
+
|
|
4
|
+
These are NOT the spec's real Circuit/Part model (see model.py for that). They
|
|
5
|
+
were a deliberate M1 shortcut — lib_path/symbol_name point directly at a known
|
|
6
|
+
fixture so the emit pipeline could be proven end-to-end before symbol
|
|
7
|
+
resolution (M3) existed.
|
|
8
|
+
|
|
9
|
+
This module exists solely so `python -m schemaseed` keeps working unchanged
|
|
10
|
+
while model.py is free to hold the real, spec-true types. Nothing outside
|
|
11
|
+
__main__.py and its smoke test should import from here.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class SkeletonPart:
|
|
20
|
+
"""A single component to be placed on the schematic (M1 demo shape)."""
|
|
21
|
+
ref: str
|
|
22
|
+
lib_path: str
|
|
23
|
+
symbol_name: str
|
|
24
|
+
value: str = ""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class SkeletonCircuit:
|
|
29
|
+
"""The complete set of parts to be emitted into one schematic (M1 demo shape)."""
|
|
30
|
+
name: str
|
|
31
|
+
parts: list[SkeletonPart] = field(default_factory=list)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# canonicalize package — the net-name identity contract (Vector F1)
|