Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/utils/numberformat.py: 5%

54 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1from decimal import Decimal 

2 

3from django.conf import settings 

4from django.utils.safestring import mark_safe 

5 

6 

7def format( 

8 number, 

9 decimal_sep, 

10 decimal_pos=None, 

11 grouping=0, 

12 thousand_sep="", 

13 force_grouping=False, 

14 use_l10n=None, 

15): 

16 """ 

17 Get a number (as a number or string), and return it as a string, 

18 using formats defined as arguments: 

19 

20 * decimal_sep: Decimal separator symbol (for example ".") 

21 * decimal_pos: Number of decimal positions 

22 * grouping: Number of digits in every group limited by thousand separator. 

23 For non-uniform digit grouping, it can be a sequence with the number 

24 of digit group sizes following the format used by the Python locale 

25 module in locale.localeconv() LC_NUMERIC grouping (e.g. (3, 2, 0)). 

26 * thousand_sep: Thousand separator symbol (for example ",") 

27 """ 

28 use_grouping = ( 

29 use_l10n or (use_l10n is None and settings.USE_L10N) 

30 ) and settings.USE_THOUSAND_SEPARATOR 

31 use_grouping = use_grouping or force_grouping 

32 use_grouping = use_grouping and grouping != 0 

33 # Make the common case fast 

34 if isinstance(number, int) and not use_grouping and not decimal_pos: 

35 return mark_safe(number) 

36 # sign 

37 sign = "" 

38 # Treat potentially very large/small floats as Decimals. 

39 if isinstance(number, float) and "e" in str(number).lower(): 

40 number = Decimal(str(number)) 

41 if isinstance(number, Decimal): 

42 

43 if decimal_pos is not None: 

44 # If the provided number is too small to affect any of the visible 

45 # decimal places, consider it equal to '0'. 

46 cutoff = Decimal("0." + "1".rjust(decimal_pos, "0")) 

47 if abs(number) < cutoff: 

48 number = Decimal("0") 

49 

50 # Format values with more than 200 digits (an arbitrary cutoff) using 

51 # scientific notation to avoid high memory usage in {:f}'.format(). 

52 _, digits, exponent = number.as_tuple() 

53 if abs(exponent) + len(digits) > 200: 

54 number = "{:e}".format(number) 

55 coefficient, exponent = number.split("e") 

56 # Format the coefficient. 

57 coefficient = format( 

58 coefficient, 

59 decimal_sep, 

60 decimal_pos, 

61 grouping, 

62 thousand_sep, 

63 force_grouping, 

64 use_l10n, 

65 ) 

66 return "{}e{}".format(coefficient, exponent) 

67 else: 

68 str_number = "{:f}".format(number) 

69 else: 

70 str_number = str(number) 

71 if str_number[0] == "-": 

72 sign = "-" 

73 str_number = str_number[1:] 

74 # decimal part 

75 if "." in str_number: 

76 int_part, dec_part = str_number.split(".") 

77 if decimal_pos is not None: 

78 dec_part = dec_part[:decimal_pos] 

79 else: 

80 int_part, dec_part = str_number, "" 

81 if decimal_pos is not None: 

82 dec_part = dec_part + ("0" * (decimal_pos - len(dec_part))) 

83 dec_part = dec_part and decimal_sep + dec_part 

84 # grouping 

85 if use_grouping: 

86 try: 

87 # if grouping is a sequence 

88 intervals = list(grouping) 

89 except TypeError: 

90 # grouping is a single value 

91 intervals = [grouping, 0] 

92 active_interval = intervals.pop(0) 

93 int_part_gd = "" 

94 cnt = 0 

95 for digit in int_part[::-1]: 

96 if cnt and cnt == active_interval: 

97 if intervals: 

98 active_interval = intervals.pop(0) or active_interval 

99 int_part_gd += thousand_sep[::-1] 

100 cnt = 0 

101 int_part_gd += digit 

102 cnt += 1 

103 int_part = int_part_gd[::-1] 

104 return sign + int_part + dec_part