From 400e111f83b8b8bc465fa86730394bec1c295c00 Mon Sep 17 00:00:00 2001 From: Cole Gentry Date: Fri, 2 Oct 2026 16:03:20 -0400 Subject: [PATCH 01/11] =?UTF-8?q?docs(plans):=20batch=20C=20design=20?= =?UTF-8?q?=E2=80=94=20errors,=20wire=20count,=20include,=20twisted=20pair?= =?UTF-8?q?s,=20shorts,=20sheet=20PDF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/plans/2026-10-02-batch-c-design.md | 137 ++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 docs/plans/2026-10-02-batch-c-design.md diff --git a/docs/plans/2026-10-02-batch-c-design.md b/docs/plans/2026-10-02-batch-c-design.md new file mode 100644 index 00000000..d4a82836 --- /dev/null +++ b/docs/plans/2026-10-02-batch-c-design.md @@ -0,0 +1,137 @@ +# Batch C — larger upstream features (design) + +Date: 2026-10-02. Branch: `fix/upstream-batch-c`. Issues from +[the upstream triage](2026-10-02-upstream-issue-triage.md). Decisions marked +**Decided** were confirmed by Cole on 2026-10-02. + +Upstream `dev` implements none of these. Open upstream PRs (#382, #455, +#506) are on `dev` or unreviewed, so only their ideas are used. + +Implementation order: C1 (#505, #508), C2 (#220), C3 (#3/#353), C4 +(#350), C5 (#32/#304). Each is one commit with tests in +`tests/test_upstream_issues.py`. + +## C1a. Error messages (#505, #207) + +Stage 1 only. + +- New `wireviz.wv_errors.WireVizError(ValueError)`. +- `parse()` wraps the processing of each connection set. An error is + re-raised with the prefix `connection set N (X1 → W1 → X2): `, and keeps + its class when it is a `ValueError` or `TypeError`; any other exception + becomes `WireVizError`. `raise ... from exc` keeps the cause. +- The `style: simple` error names the connector. +- CLI: `WireVizError`, `ValueError`, `TypeError`, `yaml.YAMLError` and + `FileNotFoundError` from `parse()` print one line through + `click.ClickException` (exit 1). New `--debug` flag re-raises for a + traceback. +- Not now: YAML line numbers (stage 2, needs mark tracking in the loader). + +## C1b. Infer the wire count (#508) + +**Decided:** a bare named cable means wires 1..n. + +- A pre-pass in `parse()` over all connection sets, before components + are created. For each cable designator with no `wirecount` and no + `colors`, the implied wire count is the largest of: the integer wire + numbers used for it, and the connection count of any set where it + appears as a bare name. +- A bare named cable (`- B1`, no template separator) in a set with n + parallel connections means wires 1..n (before: wire 1, n times). An + autogenerated cable (`- W.`) keeps its meaning: one new instance per + connection. +- Color or label references cannot imply a count: the existing error + stays, with a better message. +- CHANGELOG: list the bare-name change under "Behavior changes". + +## C2. Include files (#220) + +**Decided:** top-level `include:` list, merged at dict level. + +```yaml +include: + - lib/connectors.yml + - lib/cables.yml +connectors: ... +``` + +- Paths resolve against the including file's directory (or `source_path` + for str/dict input), then against `include_paths` (new `parse()` + argument, CLI `-I/--include-path`, repeatable). +- Recursive. A cycle or a depth over 16 is an error naming the files. +- Merge `connectors`, `cables` and `additional_bom_items` (list append) + from includes into the main data. The main file wins on a duplicate + key. The same key in two included files is an error naming both + files. `metadata`, `options`, `tweak` and `connections` come from the + main file only; in an included file they are an error (say so, do not + drop them silently). +- `image.src` of an included component is made absolute against the + included file's directory before merging. +- YAML anchors and `<<:` do not cross files: each file is parsed on its + own. Documented. +- `untrusted=True` refuses `include` (it reads files). +- PNG embedding stores the merged YAML, so a PNG is self-contained. +- `--prepend` stays as it is, and is now documented in syntax.md. + +## C3. Twisted pairs (#3, #353) + +Syntax as kvid proposed in #353: + +```yaml +cables: + W1: + colors: [RD, BK, WH, BU] + twisted: [[RD, BK], [WH, BU]] # or wire numbers / wire labels + # optional rate: twisted: [{wires: [1, 2], rate: 20/m}] +``` + +- Each group is 2 or more wires, referenced by number, color or wire + label (same resolution as connections). A wire in two groups, a group + under 2 wires, or an unknown wire is an error. +- Rendering in the wire table: the rows of a group are made contiguous + (the group starts at the row of its first wire) and wrapped in a + nested table with a thin **solid** border and a caption row + "Twisted pair" / "Twisted triad" / "Twisted group", plus `: `. + Solid, because a dashed border means a shield (IEC) and bundles + already use a dashed box. Ports keep the original wire number + (`w{i}`), so edges do not change. +- No drawn twist (split splines are a Graphviz limitation; out of scope). +- The grouping helper is generic, so shielded cores (#330) can reuse it. + +## C4. Jumpers / internal shorts (#350) + +**Decided:** `shorts:`, shorted pins count as populated. + +```yaml +connectors: + TB1: + pincount: 6 + shorts: [[1, 2, 3], {RD: [5, 6]}] # pin numbers or labels +``` + +- Each short is 2 or more pins, by number or label. Optional color as a + one-key mapping, like loops. +- Drawn in the pin table: one narrow column per short, a filled cell at + each member pin and a solid bar between the first and last member. + Plain HTML table cells; no gvpr/neato. +- Shorted pins are activated (visible with `hide_disconnected_pins`) and + count as `populated`. +- No automatic BOM entry; users add `additional_components`. +- `loops` keep their meaning (external wire loops). + +## C5. Print-ready sheet PDF (#32, #304) + +**Decided:** WeasyPrint as an optional extra, new format code. + +1. Template fixes (`din-6771.html`): named CSS pages per sheet size, so + a browser and WeasyPrint print one page at the right size; the + diagram area scales the SVG to fit above the BOM and title block; + `%date%` placeholder. +2. New output format `sheet` (CLI `-f D`, file `.sheet.pdf`): the + HTML output rendered to PDF with WeasyPrint. `pip install + "wireviz[pdf]"` adds it; without it a clear error says how to + install it. WeasyPrint gets a `url_fetcher` that refuses every URL + (all images are already inlined), so it reads no files or network. + `-f P` keeps its meaning (Graphviz diagram-only PDF). +3. Later (not this batch): BOM headings in `options.terminology`, page + orientation, BOM auto-scaling. From 3ebf21f9bc36245f878e8825eda2b289ed91a99d Mon Sep 17 00:00:00 2001 From: Cole Gentry Date: Fri, 2 Oct 2026 16:09:12 -0400 Subject: [PATCH 02/11] =?UTF-8?q?feat(errors):=20name=20the=20connection?= =?UTF-8?q?=20set=20in=20errors,=20infer=20wire=20count=20=E2=80=94=20#505?= =?UTF-8?q?,=20#207,=20#508?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - every error raised while a connection set is processed is prefixed with 'connection set N (X1 → W1 → X2): '; ValueError/TypeError keep their class, anything else becomes wv_errors.WireVizError(ValueError) - the CLI prints input errors as one line (exit 1); --debug re-raises - a cable without wirecount/colors takes its wire count from the wire numbers used for it (all sets; per template instance) - behavior change: a bare named cable (- B1) uses wires 1..n instead of wire 1 n times; autogenerated '- W.' is unchanged - clearer style: simple and unknown-wire-count messages --- docs/CHANGELOG.md | 7 + docs/syntax.md | 4 + src/wireviz/DataClasses.py | 6 +- src/wireviz/wireviz.py | 393 +++++++++++++++++++++------------- src/wireviz/wv_cli.py | 40 +++- src/wireviz/wv_errors.py | 11 + tests/test_dataclasses.py | 4 +- tests/test_upstream_issues.py | 131 +++++++++++- 8 files changed, 435 insertions(+), 161 deletions(-) create mode 100644 src/wireviz/wv_errors.py diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 0f719609..0bdb0475 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -21,8 +21,15 @@ Fixes for open issues in the original [wireviz/WireViz](https://github.com/wirev - `image: file.png` works as a short form of `image: {src: file.png}` ([#292](https://github.com/wireviz/WireViz/issues/292)). - Loops accept pin labels ([#432](https://github.com/wireviz/WireViz/issues/432)); loops on non-sequential pin numbers have a regression test ([#465](https://github.com/wireviz/WireViz/issues/465)). +### Behavior changes + +- A cable named alone in a connection set (`- B1`) now uses wires 1 to n instead of wire 1 n times ([#508](https://github.com/wireviz/WireViz/issues/508)). Autogenerated cables (`- W.`) are unchanged. +- Errors in the input name the connection set (`connection set 2 (X1 → W1 → X2): ...`) and the CLI prints them as one line with exit code 1; `--debug` shows the traceback ([#505](https://github.com/wireviz/WireViz/issues/505), [#207](https://github.com/wireviz/WireViz/issues/207)). Library callers can catch `wireviz.wv_errors.WireVizError` (a `ValueError`). + ### New features +- A cable with no `wirecount` or `colors` takes its wire count from the wire numbers used in the connections ([#508](https://github.com/wireviz/WireViz/issues/508)). + - CSV BOM output: `-f c` / `output_formats="csv"` writes `.bom.csv` ([#98](https://github.com/wireviz/WireViz/issues/98)). - Loop colors: `loops: [{RD: [VCC, SENSE]}]` ([#457](https://github.com/wireviz/WireViz/issues/457)). - `options.show_title: true` draws `metadata.title` above the diagram in PNG, SVG and PDF ([#460](https://github.com/wireviz/WireViz/issues/460)). diff --git a/docs/syntax.md b/docs/syntax.md index 44993508..3aa94870 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -266,6 +266,10 @@ connections: - `-` auto-expands to a range. - `` to refer to a wire's label or color, if unambiguous. +- `` alone (no wire list) uses wires 1 to n, where n is the number of parallel connections in the set. An autogenerated cable (`