23
23
import decimal
24
24
import re
25
25
import warnings
26
- from typing import TYPE_CHECKING , Any , overload
26
+ from typing import TYPE_CHECKING , Any , cast , overload
27
27
28
28
from babel .core import Locale , default_locale , get_global
29
29
from babel .localedata import LocaleDataDict
@@ -428,7 +428,7 @@ def get_decimal_quantum(precision: int | decimal.Decimal) -> decimal.Decimal:
428
428
429
429
def format_decimal (
430
430
number : float | decimal .Decimal | str ,
431
- format : str | None = None ,
431
+ format : str | NumberPattern | None = None ,
432
432
locale : Locale | str | None = LC_NUMERIC ,
433
433
decimal_quantization : bool = True ,
434
434
group_separator : bool = True ,
@@ -474,8 +474,8 @@ def format_decimal(
474
474
number format.
475
475
"""
476
476
locale = Locale .parse (locale )
477
- if not format :
478
- format = locale .decimal_formats . get ( format )
477
+ if format is None :
478
+ format = locale .decimal_formats [ format ]
479
479
pattern = parse_pattern (format )
480
480
return pattern .apply (
481
481
number , locale , decimal_quantization = decimal_quantization , group_separator = group_separator )
@@ -513,15 +513,15 @@ def format_compact_decimal(
513
513
number , format = _get_compact_format (number , compact_format , locale , fraction_digits )
514
514
# Did not find a format, fall back.
515
515
if format is None :
516
- format = locale .decimal_formats . get ( None )
516
+ format = locale .decimal_formats [ None ]
517
517
pattern = parse_pattern (format )
518
518
return pattern .apply (number , locale , decimal_quantization = False )
519
519
520
520
521
521
def _get_compact_format (
522
522
number : float | decimal .Decimal | str ,
523
523
compact_format : LocaleDataDict ,
524
- locale : Locale | str | None ,
524
+ locale : Locale ,
525
525
fraction_digits : int ,
526
526
) -> tuple [decimal .Decimal , NumberPattern | None ]:
527
527
"""Returns the number after dividing by the unit and the format pattern to use.
@@ -543,7 +543,7 @@ def _get_compact_format(
543
543
break
544
544
# otherwise, we need to divide the number by the magnitude but remove zeros
545
545
# equal to the number of 0's in the pattern minus 1
546
- number = number / (magnitude // (10 ** (pattern .count ("0" ) - 1 )))
546
+ number = cast ( decimal . Decimal , number / (magnitude // (10 ** (pattern .count ("0" ) - 1 ) )))
547
547
# round to the number of fraction digits requested
548
548
rounded = round (number , fraction_digits )
549
549
# if the remaining number is singular, use the singular format
@@ -565,7 +565,7 @@ class UnknownCurrencyFormatError(KeyError):
565
565
def format_currency (
566
566
number : float | decimal .Decimal | str ,
567
567
currency : str ,
568
- format : str | None = None ,
568
+ format : str | NumberPattern | None = None ,
569
569
locale : Locale | str | None = LC_NUMERIC ,
570
570
currency_digits : bool = True ,
571
571
format_type : Literal ["name" , "standard" , "accounting" ] = "standard" ,
@@ -680,7 +680,7 @@ def format_currency(
680
680
def _format_currency_long_name (
681
681
number : float | decimal .Decimal | str ,
682
682
currency : str ,
683
- format : str | None = None ,
683
+ format : str | NumberPattern | None = None ,
684
684
locale : Locale | str | None = LC_NUMERIC ,
685
685
currency_digits : bool = True ,
686
686
format_type : Literal ["name" , "standard" , "accounting" ] = "standard" ,
@@ -706,7 +706,7 @@ def _format_currency_long_name(
706
706
707
707
# Step 5.
708
708
if not format :
709
- format = locale .decimal_formats . get ( format )
709
+ format = locale .decimal_formats [ format ]
710
710
711
711
pattern = parse_pattern (format )
712
712
@@ -758,13 +758,15 @@ def format_compact_currency(
758
758
# compress adjacent spaces into one
759
759
format = re .sub (r'(\s)\s+' , r'\1' , format ).strip ()
760
760
break
761
+ if format is None :
762
+ raise ValueError ('No compact currency format found for the given number and locale.' )
761
763
pattern = parse_pattern (format )
762
764
return pattern .apply (number , locale , currency = currency , currency_digits = False , decimal_quantization = False )
763
765
764
766
765
767
def format_percent (
766
768
number : float | decimal .Decimal | str ,
767
- format : str | None = None ,
769
+ format : str | NumberPattern | None = None ,
768
770
locale : Locale | str | None = LC_NUMERIC ,
769
771
decimal_quantization : bool = True ,
770
772
group_separator : bool = True ,
@@ -808,15 +810,15 @@ def format_percent(
808
810
"""
809
811
locale = Locale .parse (locale )
810
812
if not format :
811
- format = locale .percent_formats . get ( format )
813
+ format = locale .percent_formats [ format ]
812
814
pattern = parse_pattern (format )
813
815
return pattern .apply (
814
816
number , locale , decimal_quantization = decimal_quantization , group_separator = group_separator )
815
817
816
818
817
819
def format_scientific (
818
820
number : float | decimal .Decimal | str ,
819
- format : str | None = None ,
821
+ format : str | NumberPattern | None = None ,
820
822
locale : Locale | str | None = LC_NUMERIC ,
821
823
decimal_quantization : bool = True ,
822
824
) -> str :
@@ -847,7 +849,7 @@ def format_scientific(
847
849
"""
848
850
locale = Locale .parse (locale )
849
851
if not format :
850
- format = locale .scientific_formats . get ( format )
852
+ format = locale .scientific_formats [ format ]
851
853
pattern = parse_pattern (format )
852
854
return pattern .apply (
853
855
number , locale , decimal_quantization = decimal_quantization )
@@ -856,7 +858,7 @@ def format_scientific(
856
858
class NumberFormatError (ValueError ):
857
859
"""Exception raised when a string cannot be parsed into a number."""
858
860
859
- def __init__ (self , message : str , suggestions : str | None = None ) -> None :
861
+ def __init__ (self , message : str , suggestions : list [ str ] | None = None ) -> None :
860
862
super ().__init__ (message )
861
863
#: a list of properly formatted numbers derived from the invalid input
862
864
self .suggestions = suggestions
@@ -1140,7 +1142,7 @@ def scientific_notation_elements(self, value: decimal.Decimal, locale: Locale |
1140
1142
1141
1143
def apply (
1142
1144
self ,
1143
- value : float | decimal .Decimal ,
1145
+ value : float | decimal .Decimal | str ,
1144
1146
locale : Locale | str | None ,
1145
1147
currency : str | None = None ,
1146
1148
currency_digits : bool = True ,
@@ -1211,9 +1213,9 @@ def apply(
1211
1213
number = '' .join ([
1212
1214
self ._quantize_value (value , locale , frac_prec , group_separator ),
1213
1215
get_exponential_symbol (locale ),
1214
- exp_sign ,
1215
- self ._format_int (
1216
- str ( exp ), self . exp_prec [ 0 ], self . exp_prec [ 1 ], locale ) ])
1216
+ exp_sign , # type: ignore # exp_sign is always defined here
1217
+ self ._format_int (str ( exp ), self . exp_prec [ 0 ], self . exp_prec [ 1 ], locale ) # type: ignore # exp is always defined here
1218
+ ])
1217
1219
1218
1220
# Is it a significant digits pattern?
1219
1221
elif '@' in self .pattern :
@@ -1234,9 +1236,8 @@ def apply(
1234
1236
number if self .number_pattern != '' else '' ,
1235
1237
self .suffix [is_negative ]])
1236
1238
1237
- if '¤' in retval :
1238
- retval = retval .replace ('¤¤¤' ,
1239
- get_currency_name (currency , value , locale ))
1239
+ if '¤' in retval and currency is not None :
1240
+ retval = retval .replace ('¤¤¤' , get_currency_name (currency , value , locale ))
1240
1241
retval = retval .replace ('¤¤' , currency .upper ())
1241
1242
retval = retval .replace ('¤' , get_currency_symbol (currency , locale ))
1242
1243
0 commit comments