Skip to content

Replace termcolor Printer with loguru + rich logger#109

Merged
ajslater merged 1 commit intoprogressfrom
claude/adoring-solomon-19d764
Apr 29, 2026
Merged

Replace termcolor Printer with loguru + rich logger#109
ajslater merged 1 commit intoprogressfrom
claude/adoring-solomon-19d764

Conversation

@ajslater
Copy link
Copy Markdown
Owner

Summary

  • Replaces the old picopt.Printer (termcolor-based, scattered dot prints from workers) with a centralized logger modeled on nudebomb's progress branch: loguru for log lines, a Rich Progress with a streaming per-file char column, a Stats + summary table, and a Reporter that bundles them.
  • New picopt/log/ package — styles.py is the single source of truth for marks/colors used by the progress chars, log lines, summary table, and --help epilogue legend. Style choices intentionally mirror the old termcolor palette so longtime users see the same colors for the same outcomes.
  • Worker-side dot/lifecycle calls (scan_archive, container_unpacking, container_repacking, packed, etc.) are dropped — workers in a ProcessPoolExecutor can't reach the parent's live region, so per-file progress is now driven from the scheduler when each ReportStats comes back. Worker warnings/errors still surface via loguru.
  • Totals removed; report.py is a pure ReportStats data class. The scheduler takes a Reporter and runs every result through reporter.record_report() for stats + progress + log in one place.
  • doctor.py and the CLI --help epilogue rewritten with rich (with rich.markup.escape() for path strings).
  • Grovestamps now constructed with verbose=0 so treestamps's own internal printer doesn't bypass the Rich Live region.
  • Added loguru~=0.7; removed all termcolor usage.

Test plan

  • uv run ruff check picopt/ — clean
  • uv run basedpyright picopt/ — 0 errors (12 stylistic warnings pre-existing or stylistic)
  • uv run pytest — 149 passed, 6 skipped, 1 pre-existing treestamps-v4 failure (test_timestamp_parents) unrelated to this change
  • picopt --help renders the new colorized progress char key
  • picopt doctor renders the rich tool tree with version/path
  • picopt -v file.jpg runs end-to-end and prints the new summary table

Notes for reviewers

  • The single failing test (tests/test_timestamps.py::TestTimestamps::test_timestamp_parents) reproduces on the un-modified branch with termcolor installed — it's a treestamps v4 path-handling regression where loaded timestamps from a parent .picopt_treestamps.yaml keep their absolute path, then fail on dump because path.relative_to(root_dir) rejects above-root paths. Out of scope for this PR.
  • Worker processes don't share the parent's loguru config; warnings/errors from workers fall back to loguru's default stderr sink, which doesn't fight the Rich live region on stdout.

🤖 Generated with Claude Code

The old Printer class wrote dots and messages directly to stdout from
both the main process and worker processes. This change discards it for
a centralized logger modeled on nudebomb's progress branch:

- New picopt/log/ package: shared rich Console, loguru sink, a streaming
  CharStreamColumn progress bar, a Stats + render() summary, and a
  Reporter that bundles them and dispatches each ReportStats outcome.
- All call sites converted: Printer.{saved,converted,lost,error,skip,
  warn,config,...} → logger.* and progress.mark_*. Worker-side dot and
  lifecycle calls dropped — workers can't reach the parent's live region,
  so per-file progress is now driven from the scheduler when each result
  comes back.
- Centralized MARKS table in picopt/log/styles.py drives the streaming
  chars, the loguru sink colors, the summary table row colors, and the
  --help epilogue legend, so the same outcome reads identically
  everywhere. Style choices mirror the old termcolor palette so longtime
  users see the same colors for the same outcomes.
- Scheduler now takes a Reporter; Totals removed. report.py is a pure
  data class (ReportStats) with no printer dependency.
- doctor.py and the cli help epilogue rewritten with rich (rich.markup
  escape() for path strings).
- Grovestamps now constructed with verbose=0 so treestamps's internal
  printer doesn't bypass the rich Live region.
- loguru~=0.7 added; termcolor dropped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ajslater ajslater changed the base branch from main to progress April 29, 2026 00:47
@ajslater ajslater merged commit 6a46d43 into progress Apr 29, 2026
1 of 2 checks passed
ajslater added a commit that referenced this pull request Apr 29, 2026
commit 83a5253785fccc471a6dbd75b4d1eba3074c9e8c
Author: AJ Slater <aj@slater.net>
Date:   Wed Apr 29 02:18:19 2026 -0700

    bump version and news

commit 9b03aed
Author: AJ Slater <aj@slater.net>
Date:   Tue Apr 28 20:44:04 2026 -0700

    update treestamp loggins

commit 1b7bdc7
Author: AJ Slater <aj@slater.net>
Date:   Tue Apr 28 20:32:59 2026 -0700

    fix implementation of timestamp loggins to log after not before

commit 8d25937
Author: AJ Slater <aj@slater.net>
Date:   Tue Apr 28 20:25:28 2026 -0700

    Log timestamp load/dump and surface INFO at default verbose=1 (#111)

    Treestamps 4 dropped its own load/dump prints, and picopt's new logger
    mapped INFO to verbose>=2, so default runs went silent for messages the
    old termcolor Printer always showed (config-style force_verbose=True).

    - _VERBOSE_LEVEL: bump so verbose=1 (the argparse default) emits INFO,
      matching the old printer's "force_verbose" tier.
    - walk.py: log "Loading timestamps for: …" before Grovestamps init and
      "Dumping timestamps for: …" before dumpf(). INFO renders cyan via the
      existing LEVEL_STYLES.

    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

commit 4415376
Author: AJ Slater <aj@slater.net>
Date:   Tue Apr 28 18:41:23 2026 -0700

    Pre-walk file count for a determinate progress bar (#110)

    * Pre-walk file count for a determinate progress bar

    Without a total the bar showed only an indeterminate spinner + count.
    Add ``Walk._count_total`` that mirrors ``walk_file``'s recursion gate
    (symlinks, timestamp filenames, ignore patterns, recurse flag) so each
    non-recursing visit contributes one mark — matching the events the
    scheduler dispatches through Reporter — and pass it as ``total=`` to
    ``make_progress``.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    * Use os.scandir for the pre-walk count

    DirEntry caches ``is_dir`` / ``is_symlink`` from the directory listing,
    so deep trees skip an extra ``stat`` per entry — meaningful on slow or
    network filesystems.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    ---------

    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

commit 6a46d43
Author: AJ Slater <aj@slater.net>
Date:   Tue Apr 28 17:48:59 2026 -0700

    Replace termcolor Printer with loguru + rich logger (#109)

    The old Printer class wrote dots and messages directly to stdout from
    both the main process and worker processes. This change discards it for
    a centralized logger modeled on nudebomb's progress branch:

    - New picopt/log/ package: shared rich Console, loguru sink, a streaming
      CharStreamColumn progress bar, a Stats + render() summary, and a
      Reporter that bundles them and dispatches each ReportStats outcome.
    - All call sites converted: Printer.{saved,converted,lost,error,skip,
      warn,config,...} → logger.* and progress.mark_*. Worker-side dot and
      lifecycle calls dropped — workers can't reach the parent's live region,
      so per-file progress is now driven from the scheduler when each result
      comes back.
    - Centralized MARKS table in picopt/log/styles.py drives the streaming
      chars, the loguru sink colors, the summary table row colors, and the
      --help epilogue legend, so the same outcome reads identically
      everywhere. Style choices mirror the old termcolor palette so longtime
      users see the same colors for the same outcomes.
    - Scheduler now takes a Reporter; Totals removed. report.py is a pure
      data class (ReportStats) with no printer dependency.
    - doctor.py and the cli help epilogue rewritten with rich (rich.markup
      escape() for path strings).
    - Grovestamps now constructed with verbose=0 so treestamps's internal
      printer doesn't bypass the rich Live region.
    - loguru~=0.7 added; termcolor dropped.

    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

commit 03cdcb0
Author: AJ Slater <aj@slater.net>
Date:   Tue Apr 28 17:34:02 2026 -0700

    move set_jpeg_xmp into jpeg plugin

commit b283374
Author: AJ Slater <aj@slater.net>
Date:   Tue Apr 28 17:06:50 2026 -0700

    update devenv. treestamps 4, rich 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.

1 participant