Skip to content

Commit 9a55cd8

Browse files
committed
Issue #12546: Allow \x00 as a fill character for builtin type __format__ methods.
1 parent 6c939cb commit 9a55cd8

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

Lib/test/test_unicode.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,27 @@ def __format__(self, format_spec):
14631463
self.assertEqual(u'{0:10000}'.format(u''), u' ' * 10000)
14641464
self.assertEqual(u'{0:10000000}'.format(u''), u' ' * 10000000)
14651465

1466+
# issue 12546: use \x00 as a fill character
1467+
self.assertEqual('{0:\x00<6s}'.format('foo'), 'foo\x00\x00\x00')
1468+
self.assertEqual('{0:\x01<6s}'.format('foo'), 'foo\x01\x01\x01')
1469+
self.assertEqual('{0:\x00^6s}'.format('foo'), '\x00foo\x00\x00')
1470+
self.assertEqual('{0:^6s}'.format('foo'), ' foo ')
1471+
1472+
self.assertEqual('{0:\x00<6}'.format(3), '3\x00\x00\x00\x00\x00')
1473+
self.assertEqual('{0:\x01<6}'.format(3), '3\x01\x01\x01\x01\x01')
1474+
self.assertEqual('{0:\x00^6}'.format(3), '\x00\x003\x00\x00\x00')
1475+
self.assertEqual('{0:<6}'.format(3), '3 ')
1476+
1477+
self.assertEqual('{0:\x00<6}'.format(3.14), '3.14\x00\x00')
1478+
self.assertEqual('{0:\x01<6}'.format(3.14), '3.14\x01\x01')
1479+
self.assertEqual('{0:\x00^6}'.format(3.14), '\x003.14\x00')
1480+
self.assertEqual('{0:^6}'.format(3.14), ' 3.14 ')
1481+
1482+
self.assertEqual('{0:\x00<12}'.format(3+2.0j), '(3+2j)\x00\x00\x00\x00\x00\x00')
1483+
self.assertEqual('{0:\x01<12}'.format(3+2.0j), '(3+2j)\x01\x01\x01\x01\x01\x01')
1484+
self.assertEqual('{0:\x00^12}'.format(3+2.0j), '\x00\x00\x00(3+2j)\x00\x00\x00')
1485+
self.assertEqual('{0:^12}'.format(3+2.0j), ' (3+2j) ')
1486+
14661487
# format specifiers for user defined type
14671488
self.assertEqual(u'{0:abc}'.format(C()), u'abc')
14681489

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ Core and Builtins
4040
- Issue #19638: Fix possible crash / undefined behaviour from huge (more than 2
4141
billion characters) input strings in _Py_dg_strtod.
4242

43+
- Issue #12546: Allow \x00 to be used as a fill character when using str, int,
44+
float, and complex __format__ methods.
45+
4346
Library
4447
-------
4548

Objects/stringlib/formatter.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,9 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
180180

181181
Py_ssize_t consumed;
182182
int align_specified = 0;
183+
int fill_char_specified = 0;
183184

184-
format->fill_char = '\0';
185+
format->fill_char = ' ';
185186
format->align = default_align;
186187
format->alternate = 0;
187188
format->sign = '\0';
@@ -195,6 +196,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
195196
if (end-ptr >= 2 && is_alignment_token(ptr[1])) {
196197
format->align = ptr[1];
197198
format->fill_char = ptr[0];
199+
fill_char_specified = 1;
198200
align_specified = 1;
199201
ptr += 2;
200202
}
@@ -218,7 +220,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
218220
}
219221

220222
/* The special case for 0-padding (backwards compat) */
221-
if (format->fill_char == '\0' && end-ptr >= 1 && ptr[0] == '0') {
223+
if (!fill_char_specified && end-ptr >= 1 && ptr[0] == '0') {
222224
format->fill_char = '0';
223225
if (!align_specified) {
224226
format->align = '=';
@@ -715,8 +717,7 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format)
715717

716718
/* Write into that space. First the padding. */
717719
p = fill_padding(STRINGLIB_STR(result), len,
718-
format->fill_char=='\0'?' ':format->fill_char,
719-
lpad, rpad);
720+
format->fill_char, lpad, rpad);
720721

721722
/* Then the source string. */
722723
memcpy(p, STRINGLIB_STR(value), len * sizeof(STRINGLIB_CHAR));
@@ -893,8 +894,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
893894

894895
/* Populate the memory. */
895896
fill_number(STRINGLIB_STR(result), &spec, pnumeric_chars, n_digits,
896-
prefix, format->fill_char == '\0' ? ' ' : format->fill_char,
897-
&locale, format->type == 'X');
897+
prefix, format->fill_char, &locale, format->type == 'X');
898898

899899
done:
900900
Py_XDECREF(tmp);
@@ -1048,8 +1048,7 @@ format_float_internal(PyObject *value,
10481048

10491049
/* Populate the memory. */
10501050
fill_number(STRINGLIB_STR(result), &spec, p, n_digits, NULL,
1051-
format->fill_char == '\0' ? ' ' : format->fill_char, &locale,
1052-
0);
1051+
format->fill_char, &locale, 0);
10531052

10541053
done:
10551054
PyMem_Free(buf);
@@ -1265,8 +1264,7 @@ format_complex_internal(PyObject *value,
12651264
/* Populate the memory. First, the padding. */
12661265
p = fill_padding(STRINGLIB_STR(result),
12671266
n_re_total + n_im_total + 1 + add_parens * 2,
1268-
format->fill_char=='\0' ? ' ' : format->fill_char,
1269-
lpad, rpad);
1267+
format->fill_char, lpad, rpad);
12701268

12711269
if (add_parens)
12721270
*p++ = '(';

0 commit comments

Comments
 (0)