testsAndMisc/python_pkg/brother_printer/_page_count.py
Krzysztof kuhy Rudnicki a438652aaa Split brother_printer dropped-page detection out of consumables
consumables.py 279 -> 217. check_page_delivery and _snapshot_counters
move to _page_delivery.py.

The state-file primitives stay put: test_consumables.py patches
_load_consumable_state, _save_consumable_state and CONSUMABLE_STATE_FILE
on consumables, and moving them would have let a test write to the real
~/.config/brother_printer/state.json. Verified by mtime after the run,
not just by a green suite.

test_consumables_part2.py patches the same three primitives from both
sides of the seam, so it gains a second MOD_PD applied per class rather
than a blanket swap. Pass count is 402 before and after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:07:21 +02:00

116 lines
4.0 KiB
Python

"""Page-count estimates and the dropped-page warning.
Split out of :mod:`python_pkg.brother_printer.display` to keep it under the
250-line cap. ``estimate_consumable_life`` and ``check_page_delivery`` are
patched by ``tests/test_display_part3.py``, so they are imported here rather
than through ``display``.
"""
from __future__ import annotations
from python_pkg.brother_printer._page_delivery import check_page_delivery
from python_pkg.brother_printer._supply import render_life_bar
from python_pkg.brother_printer.constants import (
BOLD,
DIM,
DRUM_RATED_PAGES,
RED,
RESET,
TONER_RATED_PAGES,
YELLOW,
_out,
)
from python_pkg.brother_printer.consumables import estimate_consumable_life
def _display_page_delivery_warning(printer_total: int, *, queue_idle: bool) -> None:
"""Warn when CUPS claims more pages than the printer actually counted.
Args:
printer_total: Lifetime count from the printer's own counter.
queue_idle: False while a job is queued or printing, when the two
counters legitimately disagree.
"""
check = check_page_delivery(printer_total, queue_idle=queue_idle)
if not check.suspected:
return
_out(f"{BOLD}── Dropped Pages ──{RESET}")
_out()
_out(
f" {RED}{BOLD}⚠ {check.dropped} pages did not print.{RESET}"
f" {RED}CUPS sent {check.cups_pages} pages since the last check;"
f" the printer's own counter advanced by"
f" {check.printer_pages}.{RESET}"
)
_out()
_out(
f" {DIM}The printer discards pages whose 600 dpi raster does not fit"
f" its memory, stays READY, and reports no error - and CUPS still calls"
f" the job successful. Reprint at a lower resolution:{RESET}"
)
_out(f" {DIM} lp -o Resolution=300dpi <file>{RESET}")
_out()
def _display_page_count_estimate(printer_total: int = 0) -> None:
"""Show estimated consumable life based on the printer's page count.
Args:
printer_total: Lifetime count from the printer's own counter, or zero
when it could not be read and the CUPS page log has to stand in.
"""
estimate = estimate_consumable_life(printer_total)
if estimate.total_pages <= 0:
return
_out(f"{BOLD}── Page Count Estimate ──{RESET}")
_out()
_out(
f" {BOLD}Total pages printed:{RESET} {estimate.total_pages}"
f" (toner: {estimate.toner_pages} since replacement,"
f" drum: {estimate.drum_pages} since replacement)"
)
if estimate.approximate:
_out(
f" {YELLOW}Approximate: counted from the CUPS log, not the"
f" printer's own counter, so it misses pages CUPS never saw"
f" and reads high.{RESET}"
)
_out()
render_life_bar(
"Toner:",
estimate.toner_pct_remaining,
exhausted=estimate.toner_exhausted,
low=estimate.toner_low,
exhausted_note=" ← REPLACE NOW",
low_note=" ← order soon",
)
render_life_bar(
"Drum: ",
estimate.drum_pct_remaining,
low=estimate.drum_near_end,
low_note=" ← nearing end",
)
_out(
f" {DIM}Based on pages since last replacement"
f" vs rated capacity (toner ~{TONER_RATED_PAGES},"
f" drum ~{DRUM_RATED_PAGES}).{RESET}"
)
_out(f" {DIM}Reset after replacing: --reset-toner or --reset-drum{RESET}")
if estimate.toner_exhausted:
_out()
_out(
f" {RED}{BOLD}⚠ Toner is likely exhausted."
f" This is probably why the orange light is flashing.{RESET}"
)
_out()
def _display_consumables_reference() -> None:
"""Print compatible consumables reference."""
_out(f"{BOLD}── Compatible Consumables ──{RESET}")
_out()
_out(f" {BOLD}Toner:{RESET} TN-1050 / TN-1030 (or compatible third-party)")
_out(f" {BOLD}Drum:{RESET} DR-1050 / DR-1030 (or compatible third-party)")
_out(f" {DIM} Toner rated ~1000 pages; Drum rated ~10000 pages.{RESET}")
_out()