From d045e88043123d1b9336aedd87d2e19192bffbb7 Mon Sep 17 00:00:00 2001 From: xavierk Date: Mon, 28 Sep 2026 17:54:56 +0530 Subject: [PATCH] Clarify incomplete history readouts (#103) --- src/fenris/tui.py | 30 +++++++++++++++++++----------- tests/test_issue_92.py | 10 ++++++++++ tests/test_tui.py | 2 +- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/fenris/tui.py b/src/fenris/tui.py index e08387f..bb0bdf1 100644 --- a/src/fenris/tui.py +++ b/src/fenris/tui.py @@ -72,6 +72,13 @@ _ACTION_LEGEND = ( "p Pause · " + _RESUME_HINT + "\n" "c Collect now · t Today · [ ] Day · g Date · m Motion · d Disclosures · ? Help" ) +_LOCAL_ACTIVITY_STATE_LABELS = { + "so_far": "totals so far", + "incomplete": "incomplete", + "complete": "complete", + "zero": "measured zero", + "unavailable": "local activity unavailable", +} def _format_remaining(seconds: float) -> str: """Format remaining lifespan as human-readable string.""" @@ -490,7 +497,9 @@ class HistoryGraph(Widget): parts = [ "[bold]%s[/bold] · %s · %s" % (day.get("day", ""), day.get("timezone_label", ""), - day.get("activity_state", "incomplete")), + _LOCAL_ACTIVITY_STATE_LABELS.get( + day.get("activity_state"), "local activity unavailable", + )), "W %s · R %s" % (written_text, read_text), ] shared_written = day.get("shared_bytes_written", 0) @@ -601,7 +610,7 @@ class HistoryGraph(Widget): if h.get("timezone_label"): state = "future" if h.get("is_future") else ( "gap" if h.get("is_gap") else - "partial" if h.get("is_partial") else "measured" + "incomplete" if h.get("is_partial") else "measured" ) note = "" if self._drill_unallocated_bytes or self._drill_unallocated_read: @@ -1231,7 +1240,11 @@ def _query_local_hourly_graph_data( "unknown_seconds": unknown_seconds, "is_zero": written == 0 and read == 0 and not is_gap, "is_gap": is_gap, - "is_partial": hour_start <= current < hour_end, + "is_partial": ( + hour_start <= current < hour_end + or coverage < 1.0 + or unknown_seconds > 0 + ), "is_future": is_future, }) hour_start = hour_end @@ -2193,14 +2206,9 @@ class FenrisTuiApp(App): tz_display = "%s %s" % (local["tz_name"], local["tz_offset"]) state = local["activity_state"] - state_labels = { - "so_far": "totals so far", - "incomplete": "incomplete", - "complete": "complete", - "zero": "measured zero", - "unavailable": "local activity unavailable", - } - label = state_labels.get(state, "local activity unavailable") + label = _LOCAL_ACTIVITY_STATE_LABELS.get( + state, "local activity unavailable", + ) bw = local["bytes_written"] br = local["bytes_read"] if bw is None or br is None: diff --git a/tests/test_issue_92.py b/tests/test_issue_92.py index 4160035..d708a68 100644 --- a/tests/test_issue_92.py +++ b/tests/test_issue_92.py @@ -795,6 +795,11 @@ class TestHistoricalSelectionIdentity: (hour.isoformat(), (index + 1) * 1_000_000_000, (index + 1) * 2_000_000_000), ) + conn.execute( + "UPDATE hour_observations SET coverage = 0.5, unknown_seconds = 1800 " + "WHERE hour = ?", + ("2026-11-01T04:00:00+00:00",), + ) conn.commit() conn.close() app, patcher = _make_app(tmp_path, clock=clock) @@ -823,5 +828,10 @@ class TestHistoricalSelectionIdentity: assert "01:00 -0400" in first_occurrence assert "America/New_York -0400" in first_occurrence assert "05:00 UTC" in first_occurrence + + await pilot.press("left") + incomplete_hour = str(app.query_one("#bar-readout").render()) + assert "00:00 -0400" in incomplete_hour + assert "50% coverage · incomplete" in incomplete_hour finally: patcher.stop() diff --git a/tests/test_tui.py b/tests/test_tui.py index 5f74aa4..500787c 100644 --- a/tests/test_tui.py +++ b/tests/test_tui.py @@ -1044,7 +1044,7 @@ class TestBarGraphTUI: # Newest day is selected initially. readout = str(app.query_one("#bar-readout").render()) - assert "so_far" in readout + assert "totals so far" in readout assert "W 0.105 GB known" in readout # Moving left updates the selected-day readout.