Skip to content

Commit 34fb04e

Browse files
authored
Merge pull request #692 from zwimer/fix/691-file_size_formatting
Add small_formatting argument to file_size
2 parents 2113c2c + 2b28dcf commit 34fb04e

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

src/human_readable/files.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33

44
def file_size(
5-
value: int, binary: bool = False, gnu: bool = False, formatting: str = ".1f"
5+
value: int,
6+
binary: bool = False,
7+
gnu: bool = False,
8+
formatting: str = ".1f",
9+
small_formatting: str = "",
610
) -> str:
711
"""Return human-readable file size.
812
@@ -12,12 +16,16 @@ def file_size(
1216
`10**3`. If ``gnu`` is True, the binary argument is ignored and GNU-style
1317
(``ls -sh`` style) prefixes are used (K, M) with the `2**10` definition.
1418
Non-gnu modes are compatible with jinja2's ``filesizeformat`` filter.
19+
small_formatting is used instead of formatting when the number of bytes
20+
is small enough that the applied suffix is B / Byte / Bytes, since files
21+
cannot have a decimal number of bytes in a file size
1522
1623
Args:
1724
value: size number.
1825
binary: binary format. Defaults to False.
1926
gnu: GNU format. Defaults to False.
20-
formatting: format pattern. Defaults to ".1f".
27+
formatting: format pattern (applied to a float). Defaults to ".1f".
28+
small_formatting: format pattern for small values (applied to an int). Defaults to "".
2129
2230
Returns:
2331
str: file size in natural language.
@@ -27,16 +35,16 @@ def file_size(
2735
elif binary:
2836
suffixes = (" KiB", " MiB", " GiB", " TiB", " PiB", " EiB", " ZiB", " YiB")
2937
else:
30-
suffixes = (" kB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB")
38+
suffixes = (" KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB")
3139

3240
base = 1024 if (gnu or binary) else 1000
3341

3442
if value == 1 and not gnu:
35-
return f"{1:{formatting}} Byte"
43+
return f"{1:{small_formatting}} Byte"
3644
if value < base and not gnu:
37-
return f"{value:{formatting}} Bytes"
45+
return f"{value:{small_formatting}} Bytes"
3846
if value < base and gnu:
39-
return f"{value:{formatting}}B"
47+
return f"{value:{small_formatting}}B"
4048

4149
byte_size = float(value)
4250
suffix = ""

tests/unit/test_files.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33

44
import pytest
55

6-
import human_readable.files as files
6+
from human_readable import files
77

88

99
@pytest.mark.parametrize(
1010
"params, expected",
1111
[
12-
(1, "1.0 Byte"), # unit number
13-
(300, "300.0 Bytes"), # hundreds number
12+
(1, "1 Byte"), # unit number
13+
(300, "300 Bytes"), # hundreds number
1414
(2900000, "2.9 MB"), # millions number
1515
(2000000000, "2.0 GB"), # billions number
1616
(10**26 * 30, "3000.0 YB"), # giant number
@@ -24,8 +24,8 @@ def test_file_size(params: int, expected: str) -> None:
2424
@pytest.mark.parametrize(
2525
"params, expected",
2626
[
27-
((1, True), "1.0 Byte"), # unit number
28-
((300, True), "300.0 Bytes"), # hundreds number
27+
((1, True), "1 Byte"), # unit number
28+
((300, True), "300 Bytes"), # hundreds number
2929
((2900000, True), "2.8 MiB"), # millions number
3030
((2000000000, True), "1.9 GiB"), # billions number
3131
((10**26 * 30, True), "2481.5 YiB"), # giant number
@@ -39,8 +39,8 @@ def test_file_size_binary(params: tuple[int, bool], expected: str) -> None:
3939
@pytest.mark.parametrize(
4040
"params, expected",
4141
[
42-
((1, False, True), "1.0B"), # unit number
43-
((300, False, True), "300.0B"), # hundreds number
42+
((1, False, True), "1B"), # unit number
43+
((300, False, True), "300B"), # hundreds number
4444
((2900000, False, True), "2.8M"), # millions number
4545
((2000000000, False, True), "1.9G"), # billions number
4646
((10**26 * 30, False, True), "2481.5Y"), # giant number
@@ -54,9 +54,14 @@ def test_file_size_gnu(params: tuple[int, bool, bool], expected: str) -> None:
5454
@pytest.mark.parametrize(
5555
"params, expected",
5656
[
57-
((1, False, True, ".0f"), "1B"), # unit number
58-
((300, True, False, ".2f"), "300.00 Bytes"), # hundreds number
59-
((2900000, False, True, ".3f"), "2.766M"), # millions number
57+
((1, False, True, ".3f", ".1f"), "1.0B"), # unit number (small formatting)
58+
((999, False, False, ".3f", ".1f"), "999.0 Bytes"), # hundreds number (small formatting)
59+
((1000, False, False, ".3f", ".1f"), "1.000 KB"), # hundreds number (small formatting boundary)
60+
((1023, False, True, ".3f", ".1f"), "1023.0B"), # hundreds number (small formatting boundary)
61+
((1024, False, True, ".3f", ".1f"), "1.000K"), # hundreds number (small formatting boundary)
62+
((1023, True, False, ".3f", ".1f"), "1023.0 Bytes"), # hundreds number (small formatting boundary)
63+
((1024, True, False, ".3f", ".1f"), "1.000 KiB"), # hundreds number (small formatting boundary)
64+
((2900000, False, True, ".3f"), "2.766M"), # millions number (large formatting)
6065
(
6166
(2000000000, True, False, ".3f"),
6267
"1.863 GiB",

0 commit comments

Comments
 (0)