Skip to content

Merge CLI formatting stacks: Rich becomes the sole human renderer (#100)#106

Merged
eman merged 4 commits into
mainfrom
pr-100-cli-formatting
Jul 6, 2026
Merged

Merge CLI formatting stacks: Rich becomes the sole human renderer (#100)#106
eman merged 4 commits into
mainfrom
pr-100-cli-formatting

Conversation

@eman

@eman eman commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Properly merges the two CLI formatting stacks. Because the CLI hard-requires rich (no plain-text fallback), the redundant plain-text human renderer and the rich-vs-plain fallback machinery are removed, leaving a single data-shaping layer feeding a single Rich renderer.

What changed vs the first attempt

The initial version added presentation.py but left rich_output.py untouched with its own internal plain/rich fallback, so total CLI code grew. This revision finishes the job:

  • rich_output.py: removed all fallback machinery — _should_use_rich, _rich_available, the try/except ImportError shim, the NWP500_NO_RICH toggle, and every _print_*_plain method. Rich imports are now unconditional; each public method renders with Rich directly. The energy renderers consume the neutral EnergyReport/EnergyPeriodRow/DailyEnergyReport dataclasses directly (no dict adapters) and now render the TOTAL SUMMARY in Rich, so no information is lost.
  • output_formatters.py: deleted the dead plain-text energy builders (format_energy_usage, format_daily_energy_usage, _format_total_summary) and the _month_rows_to_dicts/_day_rows_to_dicts adapters. It now holds only JSON/CSV rendering plus thin human-output dispatch.
  • presentation.py: unchanged — the single data-shaping layer.

Result

  • Net CLI code: 2088 → 1838 lines (−250), a real reduction, with one data-shaping layer and one human renderer.
  • Non-energy output (device status/info, JSON, device list, reservations, TOU, tree, success/info/error) is byte-for-byte identical — verified with a golden-output capture diff before/after.
  • Energy output now renders a summary table + breakdown table entirely in Rich, instead of printing a plain-text report and a Rich table (the previous doubled output is gone).

Validation

  • scripts/lint.py (ruff + pyright): passed
  • mypy src/nwp500: no issues in 50 files
  • pytest: 611 passed

Closes #100

Introduce cli/presentation.py owning all CLI data-shaping (field
selection, labels, units, ordering, value formatting and energy
aggregation) as presentation-neutral structures. The plain-text/CSV/JSON
renderer and the Rich renderer now consume these structures instead of
re-deriving the same values, removing the duplicated device status/info
row building and monthly/daily energy aggregation. CLI output is
unchanged for existing commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the CLI formatting subsystem to eliminate duplicated “data-shaping” logic across the plain-text/CSV/JSON renderer and the Rich renderer by introducing a presentation-neutral intermediate layer that both output modes consume.

Changes:

  • Added cli/presentation.py to centralize CLI data-shaping into neutral row structures for device status/info and neutral dataclass reports for energy aggregation.
  • Updated output_formatters.py to render from the neutral structures, removing duplicated aggregation and row-building logic.
  • Documented the refactor in CHANGELOG.rst under “Unreleased”.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/nwp500/cli/presentation.py New presentation-neutral builders for device/status rows and monthly/daily energy report aggregation.
src/nwp500/cli/output_formatters.py Plain-text/CSV/JSON rendering updated to consume the neutral builders; removes duplicated formatting/aggregation logic.
CHANGELOG.rst Adds an “Unreleased” changelog entry describing the CLI formatting architecture change.

eman added 2 commits July 6, 2026 09:59
The CLI hard-requires rich (no fallback), so the plain-text human renderer
was redundant. Remove the rich-vs-plain fallback machinery from rich_output.py
(_should_use_rich, _rich_available, NWP500_NO_RICH, all _print_*_plain methods)
and make rich the sole human renderer that consumes the neutral presentation
layer directly (EnergyReport/EnergyPeriodRow instead of dict adapters). Rich now
renders the energy TOTAL SUMMARY too, so removing the plain-text summary loses
no information. Drop the now-dead plain-text energy builders and dict adapters
from output_formatters.py, which retains only JSON/CSV rendering plus thin
human-output dispatch.

Net CLI code drops from 2088 to 1838 lines with a single data-shaping layer
(presentation.py) and a single human renderer (rich_output.py). Non-energy
output verified byte-identical via golden capture; energy now renders summary +
breakdown entirely in rich instead of doubling plain text and a rich table.
@eman eman changed the title Merge CLI formatting stacks behind a presentation-neutral layer (#100) Merge CLI formatting stacks: Rich becomes the sole human renderer (#100) Jul 6, 2026
@eman
eman requested a review from Copilot July 6, 2026 17:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread src/nwp500/cli/presentation.py Outdated
Comment thread src/nwp500/cli/rich_output.py Outdated
Comment thread src/nwp500/cli/output_formatters.py Outdated
- Update presentation.py module docstring: the plain-text renderer was
  removed and Rich is now mandatory, so drop the stale reference.
- Derive year/month for print_daily_energy_table() from
  DailyEnergyReport instead of passing them separately, removing the
  duplicated source of truth and possible argument drift.
@eman
eman merged commit e057c6e into main Jul 6, 2026
7 checks passed
@eman
eman deleted the pr-100-cli-formatting branch July 6, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Merge doubled CLI formatting stacks (output_formatters.py + rich_output.py) behind a presentation-neutral layer

2 participants