Skip to content

Commit 5476414

Browse files
Kasper JungeRalphify
authored andcommitted
refactor: move format_count from _IterationPanel to _output module
format_count is a pure utility function that doesn't depend on any class state — it was a @staticmethod on _IterationPanel but logically belongs next to format_duration in _output.py, where both serve as "format a number for human display" utilities. This removes the class coupling and moves tests to test_output.py alongside the other formatting tests. Co-authored-by: Ralphify <noreply@ralphify.co>
1 parent 0138787 commit 5476414

File tree

4 files changed

+55
-36
lines changed

4 files changed

+55
-36
lines changed

src/ralphify/_console_emitter.py

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
)
4242
from ralphify import _brand
4343
from ralphify._agent import CLAUDE_BINARY
44-
from ralphify._output import format_duration
44+
from ralphify._output import format_count, format_duration
4545

4646
_ICON_SUCCESS = "✓"
4747
_ICON_FAILURE = "✗"
@@ -182,14 +182,6 @@ def _extract_tool_arg(name: str, tool_input: dict[str, Any]) -> str:
182182
return ", ".join(sorted(tool_input.keys()))
183183

184184

185-
def _format_tool_summary(name: str, tool_input: dict[str, Any]) -> str:
186-
"""Return a compact one-liner describing a tool call."""
187-
arg = _extract_tool_arg(name, tool_input)
188-
if arg:
189-
return f"{name} {arg}"
190-
return name
191-
192-
193185
# ── Helpers ───────────────────────────────────────────────────────────
194186

195187

@@ -502,23 +494,11 @@ def _format_tokens(self) -> str:
502494
parts: list[str] = []
503495
total_in = self._input_tokens
504496
if total_in > 0:
505-
parts.append(f"ctx {self._format_count(total_in)}")
497+
parts.append(f"ctx {format_count(total_in)}")
506498
if self._output_tokens > 0:
507-
parts.append(f"out {self._format_count(self._output_tokens)}")
499+
parts.append(f"out {format_count(self._output_tokens)}")
508500
return " · ".join(parts)
509501

510-
@staticmethod
511-
def _format_count(n: int) -> str:
512-
if n >= 1_000_000:
513-
return f"{n / 1_000_000:.1f}M"
514-
if n >= 1_000:
515-
# Use rounded value to avoid "1000.0k" when rounding crosses
516-
# into the next unit (same guard as format_duration's 59.95→1m).
517-
if round(n / 1_000, 1) >= 1_000:
518-
return f"{n / 1_000_000:.1f}M"
519-
return f"{n / 1_000:.1f}k"
520-
return str(n)
521-
522502
def _format_categories(self) -> str:
523503
if not self._tool_categories:
524504
return ""

src/ralphify/_output.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,28 @@ def warn(message: str) -> None:
8787
print(f"ralphify: warning: {message}", file=sys.stderr)
8888

8989

90+
def format_count(n: int) -> str:
91+
"""Format *n* as a compact human-readable count string.
92+
93+
Returns ``"500"`` for sub-thousand, ``"1.5k"`` for sub-million,
94+
and ``"1.5M"`` for larger values. Used in console rendering for
95+
token counts and similar metrics.
96+
97+
Handles the boundary where rounding ``k`` crosses into ``M`` —
98+
e.g. 999_950 → ``"1.0M"`` instead of ``"1000.0k"`` (same guard
99+
as :func:`format_duration`'s 59.95 → ``"1m 0s"``).
100+
"""
101+
if n >= 1_000_000:
102+
return f"{n / 1_000_000:.1f}M"
103+
if n >= 1_000:
104+
# Use rounded value to avoid "1000.0k" when rounding crosses
105+
# into the next unit (same guard as format_duration's 59.95→1m).
106+
if round(n / 1_000, 1) >= 1_000:
107+
return f"{n / 1_000_000:.1f}M"
108+
return f"{n / 1_000:.1f}k"
109+
return str(n)
110+
111+
90112
_SECONDS_PER_MINUTE = 60
91113
_MINUTES_PER_HOUR = 60
92114

tests/test_console_emitter.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,17 +1410,6 @@ def test_format_tokens_does_not_double_count_cached_input(self):
14101410
f"Expected ctx 1.0k (input_tokens already includes cache), got: {result!r}"
14111411
)
14121412

1413-
def test_format_count(self):
1414-
assert _IterationPanel._format_count(500) == "500"
1415-
assert _IterationPanel._format_count(1500) == "1.5k"
1416-
assert _IterationPanel._format_count(1_500_000) == "1.5M"
1417-
1418-
def test_format_count_boundary_k_to_m(self):
1419-
"""Values that round up to 1000.0k should display as 1.0M instead."""
1420-
assert _IterationPanel._format_count(999_949) == "999.9k"
1421-
assert _IterationPanel._format_count(999_950) == "1.0M"
1422-
assert _IterationPanel._format_count(999_999) == "1.0M"
1423-
14241413
def test_apply_stores_scroll_lines_in_buffer(self):
14251414
"""apply() stores scroll lines in the internal buffer."""
14261415
panel = _IterationPanel()

tests/test_output.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
"""Tests for ralphify._output — ProcessResult, output collection, and duration formatting."""
1+
"""Tests for ralphify._output — ProcessResult, output collection, and formatting utilities."""
22

33
import pytest
44

5-
from ralphify._output import ProcessResult, collect_output, ensure_str, format_duration
5+
from ralphify._output import (
6+
ProcessResult,
7+
collect_output,
8+
ensure_str,
9+
format_count,
10+
format_duration,
11+
)
612

713

814
class TestProcessResult:
@@ -136,3 +142,25 @@ def test_hours(self):
136142

137143
def test_multi_day(self):
138144
assert format_duration(90000) == "25h 0m"
145+
146+
147+
class TestFormatCount:
148+
def test_sub_thousand(self):
149+
assert format_count(0) == "0"
150+
assert format_count(500) == "500"
151+
assert format_count(999) == "999"
152+
153+
def test_thousands(self):
154+
assert format_count(1000) == "1.0k"
155+
assert format_count(1500) == "1.5k"
156+
assert format_count(10_000) == "10.0k"
157+
158+
def test_millions(self):
159+
assert format_count(1_000_000) == "1.0M"
160+
assert format_count(1_500_000) == "1.5M"
161+
162+
def test_boundary_k_to_m(self):
163+
"""Values that round up to 1000.0k should display as 1.0M instead."""
164+
assert format_count(999_949) == "999.9k"
165+
assert format_count(999_950) == "1.0M"
166+
assert format_count(999_999) == "1.0M"

0 commit comments

Comments
 (0)