Skip to content

Implement CLI output formatting enhancements#47

Merged
toddysm merged 9 commits intomainfrom
feature/cli-formatting
Mar 14, 2026
Merged

Implement CLI output formatting enhancements#47
toddysm merged 9 commits intomainfrom
feature/cli-formatting

Conversation

@toddysm
Copy link
Owner

@toddysm toddysm commented Mar 14, 2026

Summary

Implements the CLI output formatting enhancements specified in #33. Creates a centralized cli/formatting.py module with reusable output helpers and migrates all 9 CLI modules to use them, eliminating duplicated code and improving output consistency.

Closes #33

Changes

New module: src/regshape/cli/formatting.py

Seven stateless helper functions that replace scattered, duplicated patterns:

Function Purpose
emit_json(data, output_path) Consistent 2-space-indented JSON to stdout or file
emit_text(content, output_path) Plain text to stdout or file (replaces 4 duplicate _write())
emit_error(reference, reason, exit_code) Standardized Error [ref]: reason to stderr + exit
emit_table(rows, headers) Column-aligned table output with optional headers
emit_list(items, output_path) One-item-per-line list output
format_key_value(pairs) Aligned key-value pair formatting
progress_status(message) Status messages to stderr for long operations

Migrated CLI modules (9 files)

  • manifest.py_write/_erroremit_text/emit_json/emit_error/format_key_value
  • tag.py_write/_erroremit_list/emit_json/emit_error
  • catalog.py_write/_erroremit_list/emit_json/emit_error
  • referrer.py_write/_erroremit_table/emit_json/emit_error; referrer list now shows column-aligned headers (DIGEST, ARTIFACT TYPE, SIZE)
  • blob.py_error/json.dumpsemit_error/emit_json
  • ping.pyjson.dumpsemit_json; fixed dead code for non-reachable result path
  • auth.py_erroremit_error; standardized from "Error for" to "Error [...]" format
  • layout.py_error/json.dumps/click.echo(err=True)emit_error/emit_json/progress_status
  • docker.py_error/json.dumpsemit_error/emit_json

Tests

  • test_formatting.py — 19 new tests covering all 7 helpers
  • test_manifest_cli.py — Updated assertion to match new format_key_value alignment

Design spec

  • specs/cli/formatting.md — Full design specification (committed in prior push)

What was removed

  • Four identical _write() helper definitions (manifest, tag, catalog, referrer)
  • Nine _error() helper definitions with minor format variations
  • Direct json.dumps(..., indent=2) + click.echo() patterns throughout
  • Dead code block in ping.py that was unreachable after sys.exit(1)

Testing

All 19 new formatting tests pass. Full suite: 1036 passed, 5 failed (all 5 pre-existing in test_catalog_operations and test_transport_client, unrelated to this PR).

toddysm added 2 commits March 13, 2026 18:29
- Define formatting.py API: emit_json, emit_text, emit_error, emit_table,
  emit_list, format_key_value, progress_status
- Document migration plan for replacing duplicated _write/_emit_error helpers
- Address all acceptance criteria from issue #33
- Create cli/formatting.py with reusable helpers: emit_json, emit_text,
  emit_error, emit_table, emit_list, format_key_value, progress_status
- Migrate all 9 CLI modules to use centralized formatters, removing
  duplicated _write() and _error() helpers
- Add emit_table with column-aligned headers to referrer list output
- Use format_key_value for manifest info aligned key-value display
- Replace inline json.dumps/click.echo patterns with emit_json
- Replace stderr progress messages with progress_status in layout push
- Standardize error format to 'Error [ref]: reason' across all commands
- Fix dead code in ping command for non-reachable result handling
- Add 19 unit tests for all formatting helpers
- Update test_manifest_cli for new key-value alignment format
Copilot AI review requested due to automatic review settings March 14, 2026 02:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Centralizes common CLI output logic (JSON/text/file writes, errors, tables) into a new regshape.cli.formatting module and migrates multiple CLI commands to use it for more consistent output.

Changes:

  • Added src/regshape/cli/formatting.py with reusable emit/format helpers (+ unit tests).
  • Migrated CLI modules (manifest/tag/catalog/referrer/blob/auth/docker/layout/ping) away from duplicated _write() / _error() implementations.
  • Updated manifest info output formatting and adjusted tests accordingly.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/regshape/tests/test_manifest_cli.py Adjusts assertions to match updated manifest info formatting.
src/regshape/tests/test_formatting.py Adds unit tests for new CLI formatting helpers.
src/regshape/cli/formatting.py Introduces centralized output helpers (JSON/text/errors/tables/lists/key-values).
src/regshape/cli/manifest.py Switches manifest commands to formatting helpers; formats info via aligned key/value output.
src/regshape/cli/tag.py Replaces ad-hoc output/error handling with formatting helpers.
src/regshape/cli/catalog.py Replaces duplicated write/error helpers with centralized emitters.
src/regshape/cli/referrer.py Uses formatting helpers; adds table output for terminal display.
src/regshape/cli/blob.py Uses centralized error/JSON emission helpers.
src/regshape/cli/auth.py Uses centralized error emission (and exits via helper).
src/regshape/cli/docker.py Uses centralized error/JSON emission helpers.
src/regshape/cli/layout.py Uses centralized error/JSON emission; routes progress/status text via progress_status.
src/regshape/cli/ping.py Uses centralized JSON emission; refactors error formatting paths.
specs/cli/formatting.md Adds design/spec documentation for the new formatting module and migration plan.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

toddysm and others added 7 commits March 13, 2026 19:51
progress_status is imported but never used in this module, which will trip basic linting/static checks and adds noise. Either remove the import or use it for any intended status output.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Toddy Mladenov <me@toddysm.com>
The spec states that when headers are provided to emit_table, they are printed “with a separator line”, but the implementation in src/regshape/cli/formatting.py prints only the header row (no separator). Either update the spec or add the separator line behavior so the documentation matches reality.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Toddy Mladenov <me@toddysm.com>
The early return when result.manifests is empty means --output no longer creates/writes the requested file (and stdout output changes from a blank line to no output). If callers rely on the output file being created even when there are zero referrers, consider emitting an empty string via emit_text("", output) when output is set (and optionally emitting nothing for stdout).

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Toddy Mladenov <me@toddysm.com>
TestEmitTable.test_column_alignment computes col2_positions but never asserts anything about it, so it doesn't actually validate alignment (it only asserts the line count). This makes the test a false positive and won't catch regressions in emit_table spacing.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Toddy Mladenov <me@toddysm.com>
Unused imports (os, tempfile, patch) in this test module add noise and may fail linting if/when it’s enabled. Please remove them or use them.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Toddy Mladenov <me@toddysm.com>
Docs say format_key_value(...) returns output with “right-aligned keys”, but the implemented behavior left-pads keys with ljust() so the separator is aligned (keys are left-aligned). Update the wording/example to match the actual alignment to avoid confusing future contributors.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Toddy Mladenov <me@toddysm.com>
- Add err: bool parameter to emit_text() and emit_json() so callers
  can direct output to stderr, keeping stdout machine-parseable
- Update ping _error() to pass err=True for JSON error output
- Add tests for stderr routing in both emit_json and emit_text
@toddysm toddysm merged commit 22278f7 into main Mar 14, 2026
3 checks passed
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.

CLI Output Formatting Enhancements

2 participants