Skip to content

Commit d5dddcf

Browse files
committed
fix: carry filesize suffix when mantissa rounds up to base
1 parent 77a8562 commit d5dddcf

2 files changed

Lines changed: 25 additions & 2 deletions

File tree

fs/filesize.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@ def _to_str(size, suffixes, base):
3333
elif size < base:
3434
return "{:,} bytes".format(size)
3535

36-
# TODO (dargueta): Don't rely on unit or suffix being defined in the loop.
36+
suffixes = list(suffixes)
3737
for i, suffix in enumerate(suffixes, 2): # noqa: B007
3838
unit = base**i
3939
if size < unit:
4040
break
41-
return "{:,.1f} {}".format((base * size / unit), suffix)
41+
42+
mantissa = base * size / unit
43+
# Rounding can push the mantissa to `base` (e.g. 999,999 B is 999.999 kB,
44+
# which formats as "1,000.0 kB"). Carry into the next suffix instead.
45+
if round(mantissa, 1) >= base and i - 1 < len(suffixes):
46+
suffix = suffixes[i - 1]
47+
mantissa = size / unit
48+
49+
return "{:,.1f} {}".format(mantissa, suffix)
4250

4351

4452
def traditional(size):

tests/test_filesize.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ def test_decimal(self):
4545

4646
self.assertEqual(filesize.decimal(1200 * 1000), "1.2 MB")
4747

48+
def test_rollover_decimal(self):
49+
# Mantissa rounds up to base — must carry to the next suffix
50+
self.assertEqual(filesize.decimal(999_999), "1.0 MB")
51+
self.assertEqual(filesize.decimal(999_999_999), "1.0 GB")
52+
self.assertEqual(filesize.decimal(999_999_999_999), "1.0 TB")
53+
54+
def test_rollover_traditional(self):
55+
# 1024**2 - 1 bytes is 1023.999 KB, which rounds to 1,024.0 KB
56+
self.assertEqual(filesize.traditional(1024**2 - 1), "1.0 MB")
57+
self.assertEqual(filesize.traditional(1024**3 - 1), "1.0 GB")
58+
59+
def test_rollover_binary(self):
60+
self.assertEqual(filesize.binary(1024**2 - 1), "1.0 MiB")
61+
self.assertEqual(filesize.binary(1024**3 - 1), "1.0 GiB")
62+
4863
def test_errors(self):
4964

5065
with self.assertRaises(TypeError):

0 commit comments

Comments
 (0)