]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-130860: Fix width calculation, when separators in fractional part (GH-130865)
authorSergey B Kirpichev <skirpichev@gmail.com>
Thu, 6 Mar 2025 12:26:29 +0000 (15:26 +0300)
committerGitHub <noreply@github.com>
Thu, 6 Mar 2025 12:26:29 +0000 (14:26 +0200)
This amends f39a07be47

Lib/test/test_float.py
Python/formatter_unicode.c

index 231b1047f72b39a78020f7136edcc390d29c177e..ee8e28bf75b5a8a16a89f421a85951e443a141a0 100644 (file)
@@ -768,6 +768,22 @@ class FormatTestCase(unittest.TestCase):
         self.assertEqual(format(x, '<21._f'), '123456.123_456       ')
         self.assertEqual(format(x, '+.11_e'), '+1.234_561_234_56e+05')
         self.assertEqual(format(x, '+.11,e'), '+1.234,561,234,56e+05')
+        self.assertEqual(format(x, '021_._f'), '0_000_123_456.123_456')
+        self.assertEqual(format(x, '020_._f'), '0_000_123_456.123_456')
+        self.assertEqual(format(x, '+021_._f'), '+0_000_123_456.123_456')
+        self.assertEqual(format(x, '21_._f'), '      123_456.123_456')
+        self.assertEqual(format(x, '>021_._f'), '000000123_456.123_456')
+        self.assertEqual(format(x, '<021_._f'), '123_456.123_456000000')
+        self.assertEqual(format(x, '023_.10_f'), '0_123_456.123_456_000_0')
+        self.assertEqual(format(x, '022_.10_f'), '0_123_456.123_456_000_0')
+        self.assertEqual(format(x, '+023_.10_f'), '+0_123_456.123_456_000_0')
+        self.assertEqual(format(x, '023_.9_f'), '000_123_456.123_456_000')
+        self.assertEqual(format(x, '021_._e'), '0_000_001.234_561e+05')
+        self.assertEqual(format(x, '020_._e'), '0_000_001.234_561e+05')
+        self.assertEqual(format(x, '+021_._e'), '+0_000_001.234_561e+05')
+        self.assertEqual(format(x, '023_.10_e'), '0_001.234_561_234_6e+05')
+        self.assertEqual(format(x, '022_.10_e'), '0_001.234_561_234_6e+05')
+        self.assertEqual(format(x, '023_.9_e'), '000_001.234_561_235e+05')
 
         self.assertRaises(ValueError, format, x, '._6f')
         self.assertRaises(ValueError, format, x, '.,_f')
index 6e3dcb3dd66373fb06ad4cf35cacc007a21b7e25..dcfff2f5bc7d071fbfba5ca1f9d8a2c26e5d512b 100644 (file)
@@ -578,6 +578,22 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
         }
     }
 
+    if (spec->n_frac == 0) {
+        spec->n_grouped_frac_digits = 0;
+    }
+    else {
+        Py_UCS4 grouping_maxchar;
+        spec->n_grouped_frac_digits = _PyUnicode_InsertThousandsGrouping(
+            NULL, 0,
+            NULL, 0, spec->n_frac,
+            spec->n_frac,
+            locale->grouping, locale->frac_thousands_sep, &grouping_maxchar, 1);
+        if (spec->n_grouped_frac_digits == -1) {
+            return -1;
+        }
+        *maxchar = Py_MAX(*maxchar, grouping_maxchar);
+    }
+
     /* The number of chars used for non-digits and non-padding. */
     n_non_digit_non_padding = spec->n_sign + spec->n_prefix + spec->n_decimal +
         + spec->n_frac + spec->n_remainder;
@@ -585,7 +601,8 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
     /* min_width can go negative, that's okay. format->width == -1 means
        we don't care. */
     if (format->fill_char == '0' && format->align == '=')
-        spec->n_min_width = format->width - n_non_digit_non_padding;
+        spec->n_min_width = (format->width - n_non_digit_non_padding
+                             + spec->n_frac - spec->n_grouped_frac_digits);
     else
         spec->n_min_width = 0;
 
@@ -607,22 +624,6 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
         *maxchar = Py_MAX(*maxchar, grouping_maxchar);
     }
 
-    if (spec->n_frac == 0) {
-        spec->n_grouped_frac_digits = 0;
-    }
-    else {
-        Py_UCS4 grouping_maxchar;
-        spec->n_grouped_frac_digits = _PyUnicode_InsertThousandsGrouping(
-            NULL, 0,
-            NULL, 0, spec->n_frac,
-            spec->n_frac,
-            locale->grouping, locale->frac_thousands_sep, &grouping_maxchar, 1);
-        if (spec->n_grouped_frac_digits == -1) {
-            return -1;
-        }
-        *maxchar = Py_MAX(*maxchar, grouping_maxchar);
-    }
-
     /* Given the desired width and the total of digit and non-digit
        space we consume, see if we need any padding. format->width can
        be negative (meaning no padding), but this code still works in