Skip to content

Commit b9c1966

Browse files
committed
Clamp negative precision in scientific()
scientific() built its format spec as f"{{:.{int(precision)}e}}", so a negative precision produced an invalid spec ("{:.-1e}") and raised ValueError. This is reachable from the public API through metric(value, precision=0): for magnitudes that fall back to scientific notation, metric() calls scientific(value, precision - 1), i.e. scientific(value, -1). PR #159 added the same max(0, ...) clamp to metric()'s main path but not to scientific(). Clamp the precision to zero.
1 parent c3a124c commit b9c1966

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

src/humanize/number.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,8 @@ def scientific(value: NumberOrString, precision: int = 2) -> str:
416416
return _format_not_finite(value)
417417
except (ValueError, TypeError):
418418
return str(value)
419-
fmt = f"{{:.{int(precision)}e}}"
419+
# max(0): a negative precision builds an invalid format spec ("{:.-1e}").
420+
fmt = f"{{:.{max(0, int(precision))}e}}"
420421
n = fmt.format(value)
421422
part1, part2 = n.split("e")
422423
# Normalise exponent: int() strips the "+" sign and leading zeros,

tests/test_number.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ def test_fractional(test_input: float | str, expected: str) -> None:
218218
([-math.inf], "-Inf"),
219219
(["nan"], "NaN"),
220220
(["-inf"], "-Inf"),
221+
# Negative precision clamps to zero instead of building an invalid spec.
222+
([1e300, -1], "1 x 10³⁰⁰"),
223+
([1e300, -5], "1 x 10³⁰⁰"),
224+
([-1000, -1], "-1 x 10³"),
221225
],
222226
)
223227
def test_scientific(test_args: list[typing.Any], expected: str) -> None:
@@ -310,6 +314,11 @@ def test_clamp(test_args: list[typing.Any], expected: str) -> None:
310314
([math.nan, "m"], "NaN"),
311315
([math.inf], "+Inf"),
312316
([-math.inf], "-Inf"),
317+
# precision=0 on a scientific-fallback magnitude passed -1 to scientific(); see #159.
318+
([1e300, "m", 0], "1 x 10³⁰⁰m"),
319+
([-1e300, "m", 0], "-1 x 10³⁰⁰m"),
320+
([1e-300, "m", 0], "1 x 10⁻³⁰⁰m"),
321+
([1e40, "", 0], "1 x 10⁴⁰"),
313322
],
314323
ids=str,
315324
)

0 commit comments

Comments
 (0)