diff --git a/src/humanize/filesize.py b/src/humanize/filesize.py index fb675fd..35fb59c 100644 --- a/src/humanize/filesize.py +++ b/src/humanize/filesize.py @@ -103,7 +103,9 @@ 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: + # `format` may contain text around the conversion, so compare the rendered + # mantissa with the rendered base instead of parsing it back to a float. + if exp < len(suffix) and format % (abs_bytes / (base**exp)) == format % base: exp += 1 space = "" if gnu else " " ret: str = format % (bytes_ / (base**exp)) + space + _(suffix[exp - 1]) diff --git a/tests/test_filesize.py b/tests/test_filesize.py index e695639..fc1ceef 100644 --- a/tests/test_filesize.py +++ b/tests/test_filesize.py @@ -91,6 +91,10 @@ ([1024**2 - 1, True], "1.0 MiB"), ([1024**3 - 1, True], "1.0 GiB"), ([1024**2 - 1, False, True], "1.0M"), + # A custom format may contain text around the numeric conversion, which + # must not break the rounding carry-over check above. + ([999999, False, True, "%.1f~"], "976.6~K"), + ([999999, False, False, "%.1f~"], "1.0~ MB"), ], ) def test_naturalsize(test_args: list[int] | list[int | bool], expected: str) -> None: