Skip to content

Commit a6bf506

Browse files
author
Abhiram Mandala
committed
Return NaN/Inf unchanged from naturalsize()
naturalsize() raised ValueError for math.nan and produced malformed output like 'inf QB' for math.inf, unlike other numeric humanizers that consistently return 'NaN', '+Inf', or '-Inf' for non-finite input via number._format_not_finite(). Add the same isfinite() short-circuit to naturalsize(), reusing number._format_not_finite() for consistent formatting, plus docstring examples and a dedicated parametrized test.
1 parent 3201e70 commit a6bf506

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

‎src/humanize/filesize.py‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22

33
from __future__ import annotations
44

5-
__lazy_modules__ = {"humanize.i18n", "math"}
5+
__lazy_modules__ = {"humanize.i18n", "humanize.number", "math"}
66

7-
from math import log
7+
from math import isfinite, log
88

9+
# Import isfinite so we can check whether a number is
10+
# a normal finite number or NaN / positive infinity / negative infinity.
11+
12+
13+
# Reuse the existing helper from number.py so that
14+
# naturalsize() behaves consistently with other numeric
15+
# humanization functions in the library.
916
from humanize.i18n import _gettext as _
17+
from humanize.number import _format_not_finite
1018

1119
suffixes = {
1220
"decimal": (
@@ -91,13 +99,18 @@ def naturalsize(
9199
base = 1024 if (gnu or binary) else 1000
92100
bytes_ = float(value)
93101
abs_bytes = abs(bytes_)
102+
103+
# Handle NaN and infinity before filesize formatting.
104+
if not isfinite(bytes_):
105+
return _format_not_finite(bytes_)
94106

95107
if abs_bytes == 1 and not gnu:
96108
return _("%d Byte") % int(bytes_)
97109

98110
if abs_bytes < base:
99111
return f"{int(bytes_)}B" if gnu else _("%d Bytes") % int(bytes_)
100112

113+
101114
exp = int(min(log(abs_bytes, base), len(suffix)))
102115
# The suffix is chosen from the unrounded byte count, but `format` rounds the
103116
# mantissa afterward; rounding can push it up to `base` (e.g. 999999 is

‎tests/test_filesize.py‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from __future__ import annotations
66

7+
import math
8+
79
import pytest
810

911
import humanize
@@ -95,11 +97,23 @@
9597
)
9698
def test_naturalsize(test_args: list[int] | list[int | bool], expected: str) -> None:
9799
assert humanize.naturalsize(*test_args) == expected
98-
99100
# Retest with negative input
100101
if isinstance(test_args[0], int):
101102
test_args[0] *= -1
102103
else:
103104
test_args[0] = f"-{test_args[0]}"
104105

105106
assert humanize.naturalsize(*test_args) == "-" + expected
107+
108+
@pytest.mark.parametrize(
109+
"test_input, expected",
110+
[
111+
(math.nan, "NaN"),
112+
(math.inf, "+Inf"),
113+
(-math.inf, "-Inf"),
114+
],
115+
)
116+
def test_naturalsize_not_finite(test_input: float, expected: str) -> None:
117+
assert humanize.naturalsize(test_input) == expected
118+
assert humanize.naturalsize(test_input, binary=True) == expected
119+
assert humanize.naturalsize(test_input, gnu=True) == expected

0 commit comments

Comments
 (0)