https://github.com/python/cpython/commit/3e849d75f400569cbf3c29c356061c788284b71e
commit: 3e849d75f400569cbf3c29c356061c788284b71e
branch: main
author: Sergey B Kirpichev <[email protected]>
committer: hugovk <[email protected]>
date: 2025-07-07T11:16:31+03:00
summary:
gh-87790: support thousands separators for formatting fractional part of
Fraction (#132204)
files:
A Misc/NEWS.d/next/Library/2025-04-07-10-20-16.gh-issue-87790.X2SjJe.rst
M Lib/fractions.py
M Lib/test/test_fractions.py
diff --git a/Lib/fractions.py b/Lib/fractions.py
index a8c670685228d3..c1b12e7a1c091c 100644
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -170,7 +170,11 @@ def _round_to_figures(n, d, figures):
(?P<zeropad>0(?=[0-9]))?
(?P<minimumwidth>[0-9]+)?
(?P<thousands_sep>[,_])?
- (?:\.(?P<precision>[0-9]+))?
+ (?:\.
+ (?=[,_0-9]) # lookahead for digit or separator
+ (?P<precision>[0-9]+)?
+ (?P<frac_separators>[,_])?
+ )?
(?P<presentation_type>[eEfFgG%])
""", re.DOTALL | re.VERBOSE).fullmatch
@@ -499,6 +503,7 @@ def _format_float_style(self, match):
minimumwidth = int(match["minimumwidth"] or "0")
thousands_sep = match["thousands_sep"]
precision = int(match["precision"] or "6")
+ frac_sep = match["frac_separators"] or ""
presentation_type = match["presentation_type"]
trim_zeros = presentation_type in "gG" and not alternate_form
trim_point = not alternate_form
@@ -555,6 +560,9 @@ def _format_float_style(self, match):
if trim_zeros:
frac_part = frac_part.rstrip("0")
separator = "" if trim_point and not frac_part else "."
+ if frac_sep:
+ frac_part = frac_sep.join(frac_part[pos:pos + 3]
+ for pos in range(0, len(frac_part), 3))
trailing = separator + frac_part + suffix
# Do zero padding if required.
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
index 1875a2f529c957..cf42b86358dbca 100644
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -1322,6 +1322,8 @@ def test_format_e_presentation_type(self):
# Thousands separators
(F('1234567.123456'), ',.5e', '1.23457e+06'),
(F('123.123456'), '012_.2e', '0_001.23e+02'),
+ # Thousands separators for fractional part (or for integral too)
+ (F('1234567.123456'), '.5_e', '1.234_57e+06'),
# z flag is legal, but never makes a difference to the output
(F(-1, 7**100), 'z.6e', '-3.091690e-85'),
]
@@ -1447,6 +1449,12 @@ def test_format_f_presentation_type(self):
(F('1234567'), ',.2f', '1,234,567.00'),
(F('12345678'), ',.2f', '12,345,678.00'),
(F('12345678'), ',f', '12,345,678.000000'),
+ # Thousands separators for fractional part (or for integral too)
+ (F('123456.789123123'), '._f', '123456.789_123'),
+ (F('123456.789123123'), '.7_f', '123456.789_123_1'),
+ (F('123456.789123123'), '.9_f', '123456.789_123_123'),
+ (F('123456.789123123'), '.,f', '123456.789,123'),
+ (F('123456.789123123'), '_.,f', '123_456.789,123'),
# Underscore as thousands separator
(F(2, 3), '_.2f', '0.67'),
(F(2, 3), '_.7f', '0.6666667'),
@@ -1620,6 +1628,11 @@ def test_invalid_formats(self):
'.f',
'.g',
'.%',
+ # Thousands separators before precision
+ '._6e',
+ '._6f',
+ '._6g',
+ '._6%',
# Z instead of z for negative zero suppression
'Z.2f'
# z flag not supported for general formatting
diff --git
a/Misc/NEWS.d/next/Library/2025-04-07-10-20-16.gh-issue-87790.X2SjJe.rst
b/Misc/NEWS.d/next/Library/2025-04-07-10-20-16.gh-issue-87790.X2SjJe.rst
new file mode 100644
index 00000000000000..be2a30d69cab45
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-07-10-20-16.gh-issue-87790.X2SjJe.rst
@@ -0,0 +1,2 @@
+Support underscore and comma as thousands separators in the fractional part
+for :class:`~fractions.Fraction`'s formatting. Patch by Sergey B Kirpichev.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]