Skip to content

Commit 90a5b44

Browse files
gh-87790: support thousands separators for formatting fractional part of Decimal (#132202)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 0c3e3da commit 90a5b44

File tree

3 files changed

+28
-1
lines changed

3 files changed

+28
-1
lines changed

Lib/_pydecimal.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6122,7 +6122,11 @@ def _convert_for_comparison(self, other, equality_op=False):
61226122
(?P<zeropad>0)?
61236123
(?P<minimumwidth>\d+)?
61246124
(?P<thousands_sep>[,_])?
6125-
(?:\.(?P<precision>\d+))?
6125+
(?:\.
6126+
(?=[\d,_]) # lookahead for digit or separator
6127+
(?P<precision>\d+)?
6128+
(?P<frac_separators>[,_])?
6129+
)?
61266130
(?P<type>[eEfFgGn%])?
61276131
\z
61286132
""", re.VERBOSE|re.DOTALL)
@@ -6215,6 +6219,9 @@ def _parse_format_specifier(format_spec, _localeconv=None):
62156219
format_dict['grouping'] = [3, 0]
62166220
format_dict['decimal_point'] = '.'
62176221

6222+
if format_dict['frac_separators'] is None:
6223+
format_dict['frac_separators'] = ''
6224+
62186225
return format_dict
62196226

62206227
def _format_align(sign, body, spec):
@@ -6334,6 +6341,11 @@ def _format_number(is_negative, intpart, fracpart, exp, spec):
63346341

63356342
sign = _format_sign(is_negative, spec)
63366343

6344+
frac_sep = spec['frac_separators']
6345+
if fracpart and frac_sep:
6346+
fracpart = frac_sep.join(fracpart[pos:pos + 3]
6347+
for pos in range(0, len(fracpart), 3))
6348+
63376349
if fracpart or spec['alt']:
63386350
fracpart = spec['decimal_point'] + fracpart
63396351

Lib/test/test_decimal.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,15 @@ def test_formatting(self):
10891089
('07_', '1234.56', '1_234.56'),
10901090
('_', '1.23456789', '1.23456789'),
10911091
('_%', '123.456789', '12_345.6789%'),
1092+
# and now for something completely different...
1093+
('.,', '1.23456789', '1.234,567,89'),
1094+
('._', '1.23456789', '1.234_567_89'),
1095+
('.6_f', '12345.23456789', '12345.234_568'),
1096+
(',._%', '123.456789', '12,345.678_9%'),
1097+
(',._e', '123456', '1.234_56e+5'),
1098+
(',.4_e', '123456', '1.234_6e+5'),
1099+
(',.3_e', '123456', '1.235e+5'),
1100+
(',._E', '123456', '1.234_56E+5'),
10921101

10931102
# negative zero: default behavior
10941103
('.1f', '-0', '-0.0'),
@@ -1162,6 +1171,10 @@ def test_formatting(self):
11621171
# bytes format argument
11631172
self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
11641173

1174+
# precision or fractional part separator should follow after dot
1175+
self.assertRaises(ValueError, format, Decimal(1), '.f')
1176+
self.assertRaises(ValueError, format, Decimal(1), '._6f')
1177+
11651178
def test_negative_zero_format_directed_rounding(self):
11661179
with self.decimal.localcontext() as ctx:
11671180
ctx.rounding = ROUND_CEILING
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Support underscore and comma as thousands separators in the fractional part
2+
for :class:`~decimal.Decimal`'s formatting. Patch by Sergey B Kirpichev.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy