Skip to content

Commit 87bcb24

Browse files
committed
Issue #6902: Fix problem with built-in types format incorrectly with 0 padding.
1 parent ae3db0a commit 87bcb24

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

Lib/test/test_types.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,17 @@ def test(i, format_spec, result):
435435
self.assertEqual(value.__format__(format_spec),
436436
float(value).__format__(format_spec))
437437

438+
# Issue 6902
439+
test(123456, "0<20", '12345600000000000000')
440+
test(123456, "1<20", '12345611111111111111')
441+
test(123456, "*<20", '123456**************')
442+
test(123456, "0>20", '00000000000000123456')
443+
test(123456, "1>20", '11111111111111123456')
444+
test(123456, "*>20", '**************123456')
445+
test(123456, "0=20", '00000000000000123456')
446+
test(123456, "1=20", '11111111111111123456')
447+
test(123456, "*=20", '**************123456')
448+
438449
def test_long__format__(self):
439450
def test(i, format_spec, result):
440451
# make sure we're not accidentally checking ints
@@ -532,6 +543,16 @@ def test(i, format_spec, result):
532543
for value in [0L, 1L, -1L, 100L, -100L, 1234567890L, -1234567890L]:
533544
self.assertEqual(value.__format__(format_spec),
534545
float(value).__format__(format_spec))
546+
# Issue 6902
547+
test(123456L, "0<20", '12345600000000000000')
548+
test(123456L, "1<20", '12345611111111111111')
549+
test(123456L, "*<20", '123456**************')
550+
test(123456L, "0>20", '00000000000000123456')
551+
test(123456L, "1>20", '11111111111111123456')
552+
test(123456L, "*>20", '**************123456')
553+
test(123456L, "0=20", '00000000000000123456')
554+
test(123456L, "1=20", '11111111111111123456')
555+
test(123456L, "*=20", '**************123456')
535556

536557
@run_with_locale('LC_NUMERIC', 'en_US.UTF8')
537558
def test_float__format__locale(self):
@@ -689,6 +710,17 @@ def test(f, format_spec, result):
689710
self.assertRaises(ValueError, format, 0.0, '#')
690711
self.assertRaises(ValueError, format, 0.0, '#20f')
691712

713+
# Issue 6902
714+
test(12345.6, "0<20", '12345.60000000000000')
715+
test(12345.6, "1<20", '12345.61111111111111')
716+
test(12345.6, "*<20", '12345.6*************')
717+
test(12345.6, "0>20", '000000000000012345.6')
718+
test(12345.6, "1>20", '111111111111112345.6')
719+
test(12345.6, "*>20", '*************12345.6')
720+
test(12345.6, "0=20", '000000000000012345.6')
721+
test(12345.6, "1=20", '111111111111112345.6')
722+
test(12345.6, "*=20", '*************12345.6')
723+
692724
def test_format_spec_errors(self):
693725
# int, float, and string all share the same format spec
694726
# mini-language parser.

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 4?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #6902: Fix problem with built-in types format incorrectly with
16+
0 padding.
17+
1518
- Issue #2560: remove an unnecessary 'for' loop from my_fgets() in
1619
Parser/myreadline.c.
1720

Objects/stringlib/formatter.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ DEBUG_PRINT_FORMAT_SPEC(InternalFormatSpec *format)
151151
printf("internal format spec: align %d\n", format->align);
152152
printf("internal format spec: alternate %d\n", format->alternate);
153153
printf("internal format spec: sign %d\n", format->sign);
154-
printf("internal format spec: width %d\n", format->width);
154+
printf("internal format spec: width %zd\n", format->width);
155155
printf("internal format spec: thousands_separators %d\n",
156156
format->thousands_separators);
157-
printf("internal format spec: precision %d\n", format->precision);
157+
printf("internal format spec: precision %zd\n", format->precision);
158158
printf("internal format spec: type %c\n", format->type);
159159
printf("\n");
160160
}
@@ -181,6 +181,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
181181
the input string */
182182

183183
Py_ssize_t consumed;
184+
int align_specified = 0;
184185

185186
format->fill_char = '\0';
186187
format->align = default_align;
@@ -196,10 +197,12 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
196197
if (end-ptr >= 2 && is_alignment_token(ptr[1])) {
197198
format->align = ptr[1];
198199
format->fill_char = ptr[0];
200+
align_specified = 1;
199201
ptr += 2;
200202
}
201203
else if (end-ptr >= 1 && is_alignment_token(ptr[0])) {
202204
format->align = ptr[0];
205+
align_specified = 1;
203206
++ptr;
204207
}
205208

@@ -219,7 +222,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec,
219222
/* The special case for 0-padding (backwards compat) */
220223
if (format->fill_char == '\0' && end-ptr >= 1 && ptr[0] == '0') {
221224
format->fill_char = '0';
222-
if (format->align == '\0') {
225+
if (!align_specified) {
223226
format->align = '=';
224227
}
225228
++ptr;
@@ -495,7 +498,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,
495498

496499
/* min_width can go negative, that's okay. format->width == -1 means
497500
we don't care. */
498-
if (format->fill_char == '0')
501+
if (format->fill_char == '0' && format->align == '=')
499502
spec->n_min_width = format->width - n_non_digit_non_padding;
500503
else
501504
spec->n_min_width = 0;

0 commit comments

Comments
 (0)