Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
address review: support comma
  • Loading branch information
skirpichev committed Nov 16, 2024
commit 28b91378bd4552a1159526cc0a8e7b4b5d8b7bfd
11 changes: 5 additions & 6 deletions Doc/library/string.rst
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,12 @@ non-empty format specification typically modifies the result.
The general form of a *standard format specifier* is:

.. productionlist:: format-spec
format_spec: [[`fill`]`align`][`sign`]["z"]["#"]["0"][`width`][`grouping_option`]["." `precision` [`fraction_grouping`]][`type`]
format_spec: [[`fill`]`align`][`sign`]["z"]["#"]["0"][`width`][`grouping_option`]["." `precision` [`grouping_option`]][`type`]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not accurate. More accurate would be ["." `precision` [`grouping_option`] | "." `grouping_option`] or ["." (`precision` [`grouping_option`] | `grouping_option`)] or ["." [`precision`][`grouping_option`]] with addition that either precision or grouping_option should be specified after ".".

@skirpichev skirpichev Nov 19, 2024 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this:

.. productionlist:: format-spec
   format_spec: [`options`][`width_and_precision`][`type`]
   options: [[`fill`]`align`][`sign`]["z"]["#"]["0"]
   fill: <any character>
   align: "<" | ">" | "=" | "^"
   sign: "+" | "-" | " "
   width_and_precision: [`width_with_grouping`][`precision_with_grouping`]
   width_with_grouping: [`width`][`grouping_option`]
   precision_with_grouping: "." (`precision`[`grouping_option`] | `grouping_option`)
   width: `~python-grammar:digit`+
   grouping_option: "_" | ","
   precision: `~python-grammar:digit`+
   type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g"
       : | "G" | "n" | "o" | "s" | "x" | "X" | "%"

?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant [...] in precision_with_grouping.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

fill: <any character>
align: "<" | ">" | "=" | "^"
sign: "+" | "-" | " "
width: `~python-grammar:digit`+
grouping_option: "_" | ","
fraction_grouping: "_"
precision: `~python-grammar:digit`+
type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

Expand Down Expand Up @@ -450,12 +449,12 @@ indicates the maximum field size - in other words, how many characters will be
used from the field content. The *precision* is not allowed for integer
presentation types.

The ``'_'`` option after *precision* means the use of an underscore for a
thousands separator of the fractional part for floating-point presentation
types.
The ``'_'`` or ``','`` option after *precision* means the use of an underscore
or a comma for a thousands separator of the fractional part for floating-point
presentation types.

.. versionchanged:: 3.14
Support underscore as a thousands separator for the fractional part.
Support thousands separators for the fractional part.

Finally, the *type* determines how the data should be presented.

Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ def test_format(self):
self.assertEqual(format(x, '>21._f'), ' 123456.123_456')
self.assertEqual(format(x, '<21._f'), '123456.123_456 ')
Comment thread
skirpichev marked this conversation as resolved.
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.assertRaises(ValueError, format, x , '._6f')

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Support underscore as a thousands separator in the fractional part for
Support underscore and comma as thousands separators in the fractional part for
floating-point presentation types of the new-style string formatting (with
:func:`format` or :ref:`f-strings`). Patch by Sergey B Kirpichev.
Comment thread
skirpichev marked this conversation as resolved.
15 changes: 13 additions & 2 deletions Python/formatter_unicode.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,16 @@ parse_internal_render_format_spec(PyObject *obj,
++pos;
++consumed;
}
if (end-pos && READ_spec(pos) == ','
&& format->frac_thousands_separator == LT_NO_LOCALE)
Comment thread
skirpichev marked this conversation as resolved.
Outdated
{
if (consumed == 0) {
format->precision = -1;
}
format->frac_thousands_separator = LT_DEFAULT_LOCALE;
++pos;
++consumed;
}

/* Not having a precision or underscore after a dot is an error. */
if (consumed == 0) {
Expand Down Expand Up @@ -800,8 +810,9 @@ get_locale_info(enum LocaleType type, enum LocaleType frac_type,
locale_info->grouping = no_grouping;
break;
}
if (frac_type == LT_UNDERSCORE_LOCALE) {
locale_info->frac_thousands_sep = PyUnicode_FromOrdinal('_');
if (frac_type != LT_NO_LOCALE) {
locale_info->frac_thousands_sep = PyUnicode_FromOrdinal(
frac_type == LT_DEFAULT_LOCALE ? ',' : '_');
if (!locale_info->frac_thousands_sep) {
return -1;
}
Expand Down