Skip to content

Commit

Permalink
Support for formatting NaN, Infinity (#955)
Browse files Browse the repository at this point in the history
  • Loading branch information
DenverCoder1 authored Jan 25, 2023
1 parent 2a4b784 commit 79bcdf2
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
24 changes: 22 additions & 2 deletions babel/numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ def get_currency_name(
"""
loc = Locale.parse(locale)
if count is not None:
plural_form = loc.plural_form(count)
try:
plural_form = loc.plural_form(count)
except (OverflowError, ValueError):
plural_form = 'other'
plural_names = loc._data['currency_names_plural']
if currency in plural_names:
currency_plural_names = plural_names[currency]
Expand Down Expand Up @@ -371,6 +374,17 @@ def get_group_symbol(locale: Locale | str | None = LC_NUMERIC) -> str:
return Locale.parse(locale).number_symbols.get('group', ',')


def get_infinity_symbol(locale: Locale | str | None = LC_NUMERIC) -> str:
"""Return the symbol used by the locale to represent infinity.
>>> get_infinity_symbol('en_US')
u'∞'
:param locale: the `Locale` object or locale identifier
"""
return Locale.parse(locale).number_symbols.get('infinity', '∞')


def format_number(number: float | decimal.Decimal | str, locale: Locale | str | None = LC_NUMERIC) -> str:
"""Return the given number formatted for a specific locale.
Expand Down Expand Up @@ -400,7 +414,8 @@ def get_decimal_precision(number: decimal.Decimal) -> int:
# Copied from: https://github.com/mahmoud/boltons/pull/59
assert isinstance(number, decimal.Decimal)
decimal_tuple = number.normalize().as_tuple()
if decimal_tuple.exponent >= 0:
# Note: DecimalTuple.exponent can be 'n' (qNaN), 'N' (sNaN), or 'F' (Infinity)
if not isinstance(decimal_tuple.exponent, int) or decimal_tuple.exponent >= 0:
return 0
return abs(decimal_tuple.exponent)

Expand Down Expand Up @@ -515,6 +530,8 @@ def _get_compact_format(
"""
if not isinstance(number, decimal.Decimal):
number = decimal.Decimal(str(number))
if number.is_nan() or number.is_infinite():
return number, None
format = None
for magnitude in sorted([int(m) for m in compact_format["other"]], reverse=True):
if abs(number) >= magnitude:
Expand Down Expand Up @@ -1287,6 +1304,9 @@ def _format_int(self, value: str, min: int, max: int, locale: Locale | str | Non
return value + ret

def _quantize_value(self, value: decimal.Decimal, locale: Locale | str | None, frac_prec: tuple[int, int], group_separator: bool) -> str:
# If the number is +/-Infinity, we can't quantize it
if value.is_infinite():
return get_infinity_symbol(locale)
quantum = get_decimal_quantum(frac_prec[1])
rounded = value.quantize(quantum)
a, sep, b = f"{rounded:f}".partition(".")
Expand Down
10 changes: 10 additions & 0 deletions tests/test_numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ def test_formatting_of_very_small_decimals(self):
number = decimal.Decimal("7E-7")
assert numbers.format_decimal(number, format="@@@", locale='en_US') == '0.000000700'

def test_nan_and_infinity(self):
assert numbers.format_decimal(decimal.Decimal('Infinity'), locale='en_US') == '∞'
assert numbers.format_decimal(decimal.Decimal('-Infinity'), locale='en_US') == '-∞'
assert numbers.format_decimal(decimal.Decimal('NaN'), locale='en_US') == 'NaN'
assert numbers.format_compact_decimal(decimal.Decimal('Infinity'), locale='en_US', format_type="short") == '∞'
assert numbers.format_compact_decimal(decimal.Decimal('-Infinity'), locale='en_US', format_type="short") == '-∞'
assert numbers.format_compact_decimal(decimal.Decimal('NaN'), locale='en_US', format_type="short") == 'NaN'
assert numbers.format_currency(decimal.Decimal('Infinity'), 'USD', locale='en_US') == '$∞'
assert numbers.format_currency(decimal.Decimal('-Infinity'), 'USD', locale='en_US') == '-$∞'

def test_group_separator(self):
assert numbers.format_decimal(29567.12, locale='en_US', group_separator=False) == '29567.12'
assert numbers.format_decimal(29567.12, locale='fr_CA', group_separator=False) == '29567,12'
Expand Down

0 comments on commit 79bcdf2

Please sign in to comment.