From fb3a69a7bd648a13dd89f6beab8e99947dc9e9e8 Mon Sep 17 00:00:00 2001 From: ANSHUL SINGH <72524975+ekanshul@users.noreply.github.com> Date: Thu, 5 Nov 2026 22:36:32 +0530 Subject: [PATCH] Fix naturalsize() truncating non-integer bytes below base Fixes https://github.com/python-humanize/humanize/issues/459 Below-base values used int(bytes_), so naturalsize(1.5) returned '1 Bytes' while larger units kept the fraction. Format non-integers with the format string (1.5 Bytes / 1.5B); keep integer behavior ('300 Bytes', '1 Byte') unchanged. Co-authored-by: CommandCodeBot --- src/humanize/filesize.py | 4 +++- tests/test_filesize.py | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/humanize/filesize.py b/src/humanize/filesize.py index 063affe0..3ee79e6c 100644 --- a/src/humanize/filesize.py +++ b/src/humanize/filesize.py @@ -90,10 +90,12 @@ def naturalsize( bytes_ = float(value) abs_bytes = abs(bytes_) - if abs_bytes == 1 and not gnu: + if abs_bytes == 1 and not gnu and float(bytes_).is_integer(): return _("%d Byte") % int(bytes_) if abs_bytes < base: + if not float(bytes_).is_integer(): + return f"{format % bytes_}B" if gnu else _("%s Bytes") % (format % bytes_) return f"{int(bytes_)}B" if gnu else _("%d Bytes") % int(bytes_) from math import log diff --git a/tests/test_filesize.py b/tests/test_filesize.py index 645751b9..44d9aa14 100644 --- a/tests/test_filesize.py +++ b/tests/test_filesize.py @@ -74,10 +74,12 @@ ([3000, False, True, "%.3f"], "2.930K"), ([3000000000, False, True, "%.0f"], "3G"), ([10**26 * 30, True, False, "%.3f"], "2.423 RiB"), - ([1.123456789], "1 Bytes"), + ([1.123456789], "1.1 Bytes"), + ([1.5], "1.5 Bytes"), + ([1.5, False, True], "1.5B"), ([1.123456789 * 10**3], "1.1 kB"), ([1.123456789 * 10**6], "1.1 MB"), - ([1.123456789, False, True], "1B"), + ([1.123456789, False, True], "1.1B"), ([1.123456789 * 10**3, False, True], "1.1K"), ([1.123456789 * 10**6, False, True], "1.1M"), # Rounding must not leave the mantissa at the base while a larger suffix