From 530aba7e90ba058da2cb9195169230f1483363fd Mon Sep 17 00:00:00 2001 From: amlaban65 Date: Sat, 17 Oct 2026 12:54:18 -0400 Subject: [PATCH] Fix naturalsize() with custom formats containing text The rounding rollover added in #329 calls float() on the formatted string, which raises ValueError when the format has text around the number. Skip the rollover check in that case. Fixes #366 --- src/humanize/filesize.py | 9 +++++++-- tests/test_filesize.py | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/humanize/filesize.py b/src/humanize/filesize.py index 063affe0..7722dbf5 100644 --- a/src/humanize/filesize.py +++ b/src/humanize/filesize.py @@ -103,8 +103,13 @@ def naturalsize( # mantissa afterward; rounding can push it up to `base` (e.g. 999999 is # 999.999 kB, which formats to "1000.0 kB"). When that happens and a larger # suffix is available, step up one suffix so the result reads "1.0 MB". - if exp < len(suffix) and abs(float(format % (abs_bytes / (base**exp)))) >= base: - exp += 1 + if exp < len(suffix): + try: + if abs(float(format % (abs_bytes / (base**exp)))) >= base: + exp += 1 + except ValueError: + # Format has text around the number, so skip the rollover check. + pass space = "" if gnu else " " ret: str = format % (bytes_ / (base**exp)) + space + _(suffix[exp - 1]) return ret diff --git a/tests/test_filesize.py b/tests/test_filesize.py index 645751b9..6f016a98 100644 --- a/tests/test_filesize.py +++ b/tests/test_filesize.py @@ -101,3 +101,14 @@ def test_naturalsize(test_args: list[int] | list[int | bool], expected: str) -> test_args[0] = f"-{test_args[0]}" assert humanize.naturalsize(*test_args) == "-" + expected + + +@pytest.mark.parametrize( + "fmt, expected", + [ + ("Size: %.1f", "Size: 976.6K"), + ("%.1f (approx)", "976.6 (approx)K"), + ], +) +def test_naturalsize_format_with_text(fmt: str, expected: str) -> None: + assert humanize.naturalsize(999_999, gnu=True, format=fmt) == expected