mirror of
https://github.com/python/cpython.git
synced 2025-08-22 01:35:16 +00:00
Issue 27080: PEP 515: add '_' formatting option.
This commit is contained in:
parent
37d398ebd1
commit
89e1b1aae0
4 changed files with 93 additions and 22 deletions
|
@ -32,14 +32,20 @@ invalid_comma_type(Py_UCS4 presentation_type)
|
|||
{
|
||||
if (presentation_type > 32 && presentation_type < 128)
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Cannot specify ',' with '%c'.",
|
||||
"Cannot specify ',' or '_' with '%c'.",
|
||||
(char)presentation_type);
|
||||
else
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Cannot specify ',' with '\\x%x'.",
|
||||
"Cannot specify ',' or '_' with '\\x%x'.",
|
||||
(unsigned int)presentation_type);
|
||||
}
|
||||
|
||||
static void
|
||||
invalid_comma_and_underscore()
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "Cannot specify both ',' and '_'.");
|
||||
}
|
||||
|
||||
/*
|
||||
get_integer consumes 0 or more decimal digit characters from an
|
||||
input string, updates *result with the corresponding positive
|
||||
|
@ -108,6 +114,12 @@ is_sign_element(Py_UCS4 c)
|
|||
}
|
||||
}
|
||||
|
||||
/* Locale type codes. LT_NO_LOCALE must be zero. */
|
||||
#define LT_NO_LOCALE 0
|
||||
#define LT_DEFAULT_LOCALE 1
|
||||
#define LT_UNDERSCORE_LOCALE 2
|
||||
#define LT_UNDER_FOUR_LOCALE 3
|
||||
#define LT_CURRENT_LOCALE 4
|
||||
|
||||
typedef struct {
|
||||
Py_UCS4 fill_char;
|
||||
|
@ -223,9 +235,22 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
|||
|
||||
/* Comma signifies add thousands separators */
|
||||
if (end-pos && READ_spec(pos) == ',') {
|
||||
format->thousands_separators = 1;
|
||||
format->thousands_separators = LT_DEFAULT_LOCALE;
|
||||
++pos;
|
||||
}
|
||||
/* Underscore signifies add thousands separators */
|
||||
if (end-pos && READ_spec(pos) == '_') {
|
||||
if (format->thousands_separators != 0) {
|
||||
invalid_comma_and_underscore();
|
||||
return 0;
|
||||
}
|
||||
format->thousands_separators = LT_UNDERSCORE_LOCALE;
|
||||
++pos;
|
||||
}
|
||||
if (end-pos && READ_spec(pos) == ',') {
|
||||
invalid_comma_and_underscore();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse field precision */
|
||||
if (end-pos && READ_spec(pos) == '.') {
|
||||
|
@ -275,6 +300,16 @@ parse_internal_render_format_spec(PyObject *format_spec,
|
|||
case '\0':
|
||||
/* These are allowed. See PEP 378.*/
|
||||
break;
|
||||
case 'b':
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
/* Underscores are allowed in bin/oct/hex. See PEP 515. */
|
||||
if (format->thousands_separators == LT_UNDERSCORE_LOCALE) {
|
||||
/* Every four digits, not every three, in bin/oct/hex. */
|
||||
format->thousands_separators = LT_UNDER_FOUR_LOCALE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
invalid_comma_type(format->type);
|
||||
return 0;
|
||||
|
@ -351,11 +386,6 @@ fill_padding(_PyUnicodeWriter *writer,
|
|||
/*********** common routines for numeric formatting *********************/
|
||||
/************************************************************************/
|
||||
|
||||
/* Locale type codes. */
|
||||
#define LT_CURRENT_LOCALE 0
|
||||
#define LT_DEFAULT_LOCALE 1
|
||||
#define LT_NO_LOCALE 2
|
||||
|
||||
/* Locale info needed for formatting integers and the part of floats
|
||||
before and including the decimal. Note that locales only support
|
||||
8-bit chars, not unicode. */
|
||||
|
@ -667,8 +697,8 @@ static const char no_grouping[1] = {CHAR_MAX};
|
|||
|
||||
/* Find the decimal point character(s?), thousands_separator(s?), and
|
||||
grouping description, either for the current locale if type is
|
||||
LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE, or
|
||||
none if LT_NO_LOCALE. */
|
||||
LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE or
|
||||
LT_UNDERSCORE_LOCALE/LT_UNDER_FOUR_LOCALE, or none if LT_NO_LOCALE. */
|
||||
static int
|
||||
get_locale_info(int type, LocaleInfo *locale_info)
|
||||
{
|
||||
|
@ -691,16 +721,22 @@ get_locale_info(int type, LocaleInfo *locale_info)
|
|||
break;
|
||||
}
|
||||
case LT_DEFAULT_LOCALE:
|
||||
case LT_UNDERSCORE_LOCALE:
|
||||
case LT_UNDER_FOUR_LOCALE:
|
||||
locale_info->decimal_point = PyUnicode_FromOrdinal('.');
|
||||
locale_info->thousands_sep = PyUnicode_FromOrdinal(',');
|
||||
locale_info->thousands_sep = PyUnicode_FromOrdinal(
|
||||
type == LT_DEFAULT_LOCALE ? ',' : '_');
|
||||
if (!locale_info->decimal_point || !locale_info->thousands_sep) {
|
||||
Py_XDECREF(locale_info->decimal_point);
|
||||
Py_XDECREF(locale_info->thousands_sep);
|
||||
return -1;
|
||||
}
|
||||
locale_info->grouping = "\3"; /* Group every 3 characters. The
|
||||
if (type != LT_UNDER_FOUR_LOCALE)
|
||||
locale_info->grouping = "\3"; /* Group every 3 characters. The
|
||||
(implicit) trailing 0 means repeat
|
||||
infinitely. */
|
||||
else
|
||||
locale_info->grouping = "\4"; /* Bin/oct/hex group every four. */
|
||||
break;
|
||||
case LT_NO_LOCALE:
|
||||
locale_info->decimal_point = PyUnicode_FromOrdinal('.');
|
||||
|
@ -952,9 +988,7 @@ format_long_internal(PyObject *value, const InternalFormatSpec *format,
|
|||
|
||||
/* Determine the grouping, separator, and decimal point, if any. */
|
||||
if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
|
||||
(format->thousands_separators ?
|
||||
LT_DEFAULT_LOCALE :
|
||||
LT_NO_LOCALE),
|
||||
format->thousands_separators,
|
||||
&locale) == -1)
|
||||
goto done;
|
||||
|
||||
|
@ -1099,9 +1133,7 @@ format_float_internal(PyObject *value,
|
|||
|
||||
/* Determine the grouping, separator, and decimal point, if any. */
|
||||
if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
|
||||
(format->thousands_separators ?
|
||||
LT_DEFAULT_LOCALE :
|
||||
LT_NO_LOCALE),
|
||||
format->thousands_separators,
|
||||
&locale) == -1)
|
||||
goto done;
|
||||
|
||||
|
@ -1277,9 +1309,7 @@ format_complex_internal(PyObject *value,
|
|||
|
||||
/* Determine the grouping, separator, and decimal point, if any. */
|
||||
if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :
|
||||
(format->thousands_separators ?
|
||||
LT_DEFAULT_LOCALE :
|
||||
LT_NO_LOCALE),
|
||||
format->thousands_separators,
|
||||
&locale) == -1)
|
||||
goto done;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue