Skip to content

Commit a4ac600

Browse files
author
Victor Stinner
committed
Issue #13706: Support non-ASCII fill characters
1 parent a2a9071 commit a4ac600

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

‎Lib/test/test_format.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,26 @@ def test_exc(formatstr, args, exception, excmsg):
263263
else:
264264
raise TestFailed('"%*d"%(maxsize, -127) should fail')
265265

266+
def test_non_ascii(self):
267+
self.assertEqual(format("abc", "\u2007<5"), "abc\u2007\u2007")
268+
self.assertEqual(format(123, "\u2007<5"), "123\u2007\u2007")
269+
self.assertEqual(format(12.3, "\u2007<6"), "12.3\u2007\u2007")
270+
self.assertEqual(format(0j, "\u2007<4"), "0j\u2007\u2007")
271+
self.assertEqual(format(1+2j, "\u2007<8"), "(1+2j)\u2007\u2007")
272+
273+
self.assertEqual(format("abc", "\u2007>5"), "\u2007\u2007abc")
274+
self.assertEqual(format(123, "\u2007>5"), "\u2007\u2007123")
275+
self.assertEqual(format(12.3, "\u2007>6"), "\u2007\u200712.3")
276+
self.assertEqual(format(1+2j, "\u2007>8"), "\u2007\u2007(1+2j)")
277+
self.assertEqual(format(0j, "\u2007>4"), "\u2007\u20070j")
278+
279+
self.assertEqual(format("abc", "\u2007^5"), "\u2007abc\u2007")
280+
self.assertEqual(format(123, "\u2007^5"), "\u2007123\u2007")
281+
self.assertEqual(format(12.3, "\u2007^6"), "\u200712.3\u2007")
282+
self.assertEqual(format(1+2j, "\u2007^8"), "\u2007(1+2j)\u2007")
283+
self.assertEqual(format(0j, "\u2007^4"), "\u20070j\u2007")
284+
285+
266286
def test_main():
267287
support.run_unittest(FormatTest)
268288

‎Python/formatter_unicode.c‎

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,8 @@ parse_internal_render_format_spec(PyObject *format_spec,
274274
}
275275
}
276276

277-
if (format->fill_char > 127 || format->align > 127 ||
278-
format->sign > 127) {
279-
PyErr_SetString(PyExc_ValueError, "fill character too large");
280-
return 0;
281-
}
282-
277+
assert (format->align <= 127);
278+
assert (format->sign <= 127);
283279
return 1;
284280
}
285281

@@ -563,10 +559,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec,
563559
Py_ssize_t t;
564560
for (t = 0; t < spec->n_prefix; t++) {
565561
Py_UCS4 c = PyUnicode_READ(kind, data, pos + t);
566-
if (c > 127) {
567-
PyErr_SetString(PyExc_SystemError, "prefix not ASCII");
568-
return -1;
569-
}
562+
assert (c <= 127);
570563
PyUnicode_WRITE(kind, data, pos + t, Py_TOUPPER(c));
571564
}
572565
}
@@ -722,6 +715,9 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format)
722715

723716
calc_padding(len, format->width, format->align, &lpad, &rpad, &total);
724717

718+
if (lpad != 0 || rpad != 0)
719+
maxchar = Py_MAX(maxchar, format->fill_char);
720+
725721
/* allocate the resulting string */
726722
result = PyUnicode_New(total, maxchar);
727723
if (result == NULL)
@@ -791,21 +787,18 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
791787

792788
/* taken from unicodeobject.c formatchar() */
793789
/* Integer input truncated to a character */
794-
/* XXX: won't work for int */
795790
x = PyLong_AsLong(value);
796791
if (x == -1 && PyErr_Occurred())
797792
goto done;
798793
if (x < 0 || x > 0x10ffff) {
799794
PyErr_SetString(PyExc_OverflowError,
800-
"%c arg not in range(0x110000) "
801-
"(wide Python build)");
795+
"%c arg not in range(0x110000)");
802796
goto done;
803797
}
804798
tmp = PyUnicode_FromOrdinal(x);
805799
inumeric_chars = 0;
806800
n_digits = 1;
807-
if (x > maxchar)
808-
maxchar = x;
801+
maxchar = Py_MAX(maxchar, x);
809802

810803
/* As a sort-of hack, we tell calc_number_widths that we only
811804
have "remainder" characters. calc_number_widths thinks
@@ -882,6 +875,9 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
882875
n_total = calc_number_widths(&spec, n_prefix, sign_char, tmp, inumeric_chars,
883876
inumeric_chars + n_digits, n_remainder, 0, &locale, format);
884877

878+
if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding)
879+
maxchar = Py_MAX(maxchar, format->fill_char);
880+
885881
/* Allocate the memory. */
886882
result = PyUnicode_New(n_total, maxchar);
887883
if (!result)
@@ -1020,6 +1016,9 @@ format_float_internal(PyObject *value,
10201016
index + n_digits, n_remainder, has_decimal,
10211017
&locale, format);
10221018

1019+
if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding)
1020+
maxchar = Py_MAX(maxchar, format->fill_char);
1021+
10231022
/* Allocate the memory. */
10241023
result = PyUnicode_New(n_total, maxchar);
10251024
if (result == NULL)
@@ -1219,6 +1218,11 @@ format_complex_internal(PyObject *value,
12191218
calc_padding(n_re_total + n_im_total + 1 + add_parens * 2,
12201219
format->width, format->align, &lpad, &rpad, &total);
12211220

1221+
if (re_spec.n_lpadding || re_spec.n_spadding || re_spec.n_rpadding
1222+
|| im_spec.n_lpadding || im_spec.n_spadding || im_spec.n_rpadding
1223+
|| lpad || rpad)
1224+
maxchar = Py_MAX(maxchar, format->fill_char);
1225+
12221226
result = PyUnicode_New(total, maxchar);
12231227
if (result == NULL)
12241228
goto done;

0 commit comments

Comments
 (0)