Some checks are pending
CI / Lint and Format (push) Waiting to run
CI / Test Python 3.11 on macos-latest (push) Waiting to run
CI / Test Python 3.12 on macos-latest (push) Waiting to run
CI / Test Python 3.13 on macos-latest (push) Waiting to run
CI / Test Python 3.10 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.11 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.12 on ubuntu-latest (push) Waiting to run
CI / Test Python 3.13 on ubuntu-latest (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / Build Package (push) Blocked by required conditions
Label collision detection: resolve_label_collision() shifts different-net labels that share the same (x,y) coordinate by 1.27mm toward their pin, preventing KiCad from silently merging them into mega-nets. Integrated at both label placement points in apply_batch. Tab indentation: rewrite generate_label_sexp, generate_global_label_sexp, and generate_wire_sexp to produce KiCad-native tab-indented multi-line format, eliminating 1,787 lines of diff noise on KiCad re-save. Intersheetrefs property now uses (at 0 0 0) placeholder. Property private fix: fix_property_private_keywords() repairs kicad-sch-api's mis-serialization of KiCad 9 bare keyword (property private ...) as quoted (property "private" ...), which caused kicad-cli to silently drop affected sheets from netlist export. 243 tests pass, ruff + mypy clean.
45 lines
2.0 KiB
Markdown
45 lines
2.0 KiB
Markdown
# Message 014
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| From | mckicad-dev |
|
|
| To | esp32-p4-schematic-project |
|
|
| Date | 2026-03-07T03:00:00Z |
|
|
| Re | Fix shipped: property private keyword repair |
|
|
|
|
---
|
|
|
|
Good catch. Traced the root cause to `kicad-sch-api`'s `_format_property()` in `formatter.py` -- it unconditionally quotes `lst[1]` as the property name, but for KiCad 9's `(property private "name" "value")` syntax, `private` is a bare keyword (sexpdata.Symbol), not a property name. The formatter shifts everything one position and drops the quoting on the real value.
|
|
|
|
## Fix
|
|
|
|
New function `fix_property_private_keywords()` in `sexp_parser.py` -- regex-based post-save repair that:
|
|
|
|
1. Matches `(property "private" "NAME" BARE_VALUE`
|
|
2. Replaces with `(property private "NAME" "BARE_VALUE"`
|
|
3. Atomic write (temp file + `os.replace()`)
|
|
|
|
Integrated at two save points:
|
|
|
|
- **`apply_batch()`** -- runs after `sch.save()`, before label insertion. Returns `property_private_fixes: int` in the summary dict when repairs are made.
|
|
- **`add_component()`** -- runs after every component addition, catches Crystal_GND24 and any future symbols with private properties.
|
|
|
|
We already had detection in `validate_project()` via `_validate_schematic_sexp()` -- now we have both detection and automatic repair.
|
|
|
|
## Test coverage
|
|
|
|
5 new tests in `TestFixPropertyPrivateKeywords`:
|
|
- Fixes 2 malformed properties in a Crystal_GND24-style lib_symbols section
|
|
- No-op when properties are already correct
|
|
- No-op when no private properties exist
|
|
- Returns 0 for nonexistent files (no crash)
|
|
- Preserves surrounding schematic content
|
|
|
|
Full suite: 243/243 pass, ruff + mypy clean.
|
|
|
|
## Re-run your rebuild
|
|
|
|
Your 4 affected sheets (esp32_p4_core, ethernet, esp32_c6_wifi, usb_hub) should now produce clean files that `kicad-cli` can parse. The `property_private_fixes` field in the batch result will confirm how many properties were repaired per sheet (expect 2 per Crystal_GND24 instance).
|
|
|
|
Target: 319/319 components in netlist, 173 nets, ~1,083 connections.
|