units: Ohms.__str__ uses engineering notation (kΩ, MΩ, GΩ) - #33
Merged
Conversation
The previous `Ohms.__str__` formatted with bare `:.3g`, producing
unreadable scientific output for clean kilo / mega multiples:
str(Ohms(10_000)) == "1e+04 Ω" → now "10 kΩ"
str(Ohms(100_000)) == "1e+05 Ω" → now "100 kΩ"
str(Ohms(1_000_000)) == "1e+06 Ω" → now "1 MΩ"
The breadboard SVG visualiser surfaced the problem: a resistor body
labelled "100000Ω" makes a reader count zeros, while a label of
"100 kΩ" reads at a glance — exactly the convention every schematic
and parts catalogue uses. Centralising the engineering notation in
`Ohms.__str__` means every downstream consumer (assembly guide,
breadboard SVG, kicad netlist, BOM, reports) inherits the readable
form without each format adapter rolling its own formatter.
- `Ohms.__str__` returns "47 Ω", "4.7 kΩ", "10 kΩ", "100 kΩ",
"1 MΩ", "10 MΩ", "1 GΩ" per the kilo / mega / giga thresholds.
- `Resistor.__str__` delegates to `str(self._ohms)` so it
inherits the new notation (was producing the noisy "47.0 Ω"
via raw float).
- The breadboard visualiser's resistor body label uses
`str(part.ohms)` directly (previously had a private
`_format_ohms_compact` helper; removed).
- `tests/components/test_resistor.py::test_str` updated for
"47 Ω" (was "47.0 Ω"); new `test_str_renders_in_engineering_notation`
pins kΩ / MΩ output across the kilo and mega thresholds.
- All demo docs / goldens refreshed where the Ohms.__str__
change affected the rendered output (breadboard SVGs, kicad
sch value fields, BOM rows).
There was a problem hiding this comment.
Pull request overview
This PR improves resistance string rendering across the codebase by switching Ohms.__str__ to canonical engineering notation (e.g., 10 kΩ, 1 MΩ) so exports (breadboard SVG, KiCad schematics, BOM/report outputs) show human-friendly resistor values.
Changes:
- Update
Ohms.__str__to emit engineering notation for kΩ/MΩ/GΩ thresholds. - Simplify
Resistor.__str__and breadboard SVG rendering to delegate toOhms.__str__. - Refresh tests and golden/demo artifacts to match the new formatting.
Reviewed changes
Copilot reviewed 15 out of 27 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/framework/units.py |
Implements engineering-notation formatting in Ohms.__str__. |
src/components/passives/resistor.py |
Delegates Resistor.__str__ to Ohms.__str__. |
src/framework/export/breadboard/renderer.py |
Renders resistor body labels using str(part.ohms) (engineering notation). |
tests/components/test_resistor.py |
Updates __str__ expectations and adds coverage for kΩ/MΩ formatting. |
tests/golden/kicad_sch/water_alarm.kicad_sch |
Refreshes KiCad schematic golden to use engineering notation. |
tests/golden/breadboard/water_alarm.breadboard.svg |
Refreshes breadboard SVG golden resistor value labels. |
tests/golden/breadboard/hello_led.breadboard.svg |
Refreshes breadboard SVG golden resistor value labels (adds space / Ω formatting). |
tests/golden/breadboard/doorbell_protector.breadboard.svg |
Refreshes breadboard SVG golden resistor value labels (kΩ/MΩ). |
tests/golden/breadboard/digital_thermometer.breadboard.svg |
Refreshes breadboard SVG golden resistor value labels (adds space / Ω formatting). |
tests/golden/breadboard/dice.breadboard.svg |
Refreshes breadboard SVG golden resistor value labels (adds space / Ω + kΩ). |
demos/water_alarm/docs/WaterAlarm.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/water_alarm/docs/WaterAlarm.breadboard.svg |
Refreshes demo breadboard SVG resistor labels. |
demos/penfold_one_second_timer/docs/OneSecondTimer.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/penfold_one_second_timer/docs/OneSecondTimer.breadboard.svg |
Refreshes demo breadboard SVG resistor labels. |
demos/li_ion_fuel_gauge/docs/BatteryPackBoard.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/hello_led/docs/HelloLED.breadboard.svg |
Refreshes demo breadboard SVG resistor label formatting. |
demos/fan_cooling/docs/FanCoolingBoard.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/fan_cooling/docs/CooledSystem__FanCoolingBoard.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/doorbell_protector/docs/DoorbellProtector.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/doorbell_protector/docs/DoorbellProtector.breadboard.svg |
Refreshes demo breadboard SVG resistor labels (kΩ/MΩ). |
demos/digital_thermometer/docs/DigitalThermometer.breadboard.svg |
Refreshes demo breadboard SVG resistor label formatting. |
demos/dice/docs/Dice.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/dice/docs/Dice.breadboard.svg |
Refreshes demo breadboard SVG resistor label formatting. |
demos/bldc_motor/docs/BLDCSystem__BLDCControllerBoard.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/bldc_motor/docs/BLDCControllerBoard.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation. |
demos/backup_power/docs/BackupPower.kicad_sch |
Refreshes demo KiCad schematic values to engineering notation (including non-integer kΩ). |
demos/5v_rail_power/docs/FiveVoltRailPower.breadboard.svg |
Refreshes demo breadboard SVG resistor label formatting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+67
to
+77
| def test_str_renders_in_engineering_notation(): | ||
| """Resistor.__str__ delegates to Ohms.__str__, which uses | ||
| canonical engineering notation (kΩ, MΩ) rather than raw ohms. | ||
| A schematic / bench builder reads `10 kΩ` instantly; `10000 Ω` | ||
| forces them to count zeros.""" | ||
| assert str(Resistor(ohms=1_000, refdes_number=1)) == "1 kΩ" | ||
| assert str(Resistor(ohms=4_700, refdes_number=2)) == "4.7 kΩ" | ||
| assert str(Resistor(ohms=10_000, refdes_number=3)) == "10 kΩ" | ||
| assert str(Resistor(ohms=100_000, refdes_number=4)) == "100 kΩ" | ||
| assert str(Resistor(ohms=1_000_000, refdes_number=5)) == "1 MΩ" | ||
| assert str(Resistor(ohms=10_000_000, refdes_number=6)) == "10 MΩ" |
Same treatment as `Ohms.__str__` (previous commit) for the other two
passive engineering quantities. Demos contain caps and inductors
with values that the bare `:.3g` formatter would emit in scientific
form (`1e-07 F` for a 100 nF decoupling cap); centralising the
engineering notation on the unit class means every consumer
(reports, BOM, breadboard SVG, etc.) inherits the readable form.
- `Farads.__str__` returns `100 pF`, `22 nF`, `100 nF`, `1 µF`,
`4.7 µF`, `470 µF`, `1 mF`, `1 F` across the standard
capacitance bands.
- `Henries.__str__` returns `100 nH`, `10 µH`, `22 mH`, `1 H`
across the standard inductance bands.
- `Capacitor.__str__` and `Inductor.__str__` delegate to the
unit class's str (were rolling raw-float formatters).
- `framework.export.reports_common.part_description` now uses
`str(part.ohms / farads / henries)` directly instead of the
parallel `_format_ohms` / `_format_farads` / `_format_henries`
helpers (removed — they duplicated the new logic on raw
floats).
- Breadboard SVG renderer now also labels capacitor and inductor
bodies with their engineering-notation value (was only
resistors).
- `tests/framework/test_units.py`: parametrised regression tests
for both unit classes across every band.
- All affected demo docs / goldens refreshed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The previous
Ohms.__str__used a bare:.3gformatter, producing scientific output for clean kilo / mega multiples that no schematic or bench builder would actually write:1e+04 Ω10 kΩ1e+05 Ω100 kΩ1e+06 Ω1 MΩThe breadboard SVG visualiser (#28) surfaced the problem — a resistor body labelled
100000Ωmakes the reader count zeros. Centralising the engineering notation inOhms.__str__means every downstream format (assembly guide, breadboard SVG, kicad netlist, BOM, reports) inherits the readable form.Ohms.__str__returns47 Ω,4.7 kΩ,10 kΩ,100 kΩ,1 MΩ,10 MΩ,1 GΩ.Resistor.__str__delegates tostr(self._ohms)instead of rolling its own raw-float format.str(part.ohms)directly (its private compact-format helper is gone).tests/components/test_resistor.py::test_strupdated (47 Ω, was47.0 Ω); new parametrisedtest_str_renders_in_engineering_notationpins kΩ / MΩ output across the thresholds.Test plan
uv run pytest— 4383 passed.uv run mypy src/ demos/clean.