From 87bcb243acfd758b3e91e194bf8f1198ae68a792 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Tue, 23 Feb 2010 00:11:16 +0000 Subject: Issue #6902: Fix problem with built-in types format incorrectly with 0 padding. --- Lib/test/test_types.py | 32 ++++++++++++++++++++++++++++++++ Misc/NEWS | 3 +++ Objects/stringlib/formatter.h | 11 +++++++---- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 498f73a..e4b4b5b 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -435,6 +435,17 @@ class TypesTests(unittest.TestCase): self.assertEqual(value.__format__(format_spec), float(value).__format__(format_spec)) + # Issue 6902 + test(123456, "0<20", '12345600000000000000') + test(123456, "1<20", '12345611111111111111') + test(123456, "*<20", '123456**************') + test(123456, "0>20", '00000000000000123456') + test(123456, "1>20", '11111111111111123456') + test(123456, "*>20", '**************123456') + test(123456, "0=20", '00000000000000123456') + test(123456, "1=20", '11111111111111123456') + test(123456, "*=20", '**************123456') + def test_long__format__(self): def test(i, format_spec, result): # make sure we're not accidentally checking ints @@ -532,6 +543,16 @@ class TypesTests(unittest.TestCase): for value in [0L, 1L, -1L, 100L, -100L, 1234567890L, -1234567890L]: self.assertEqual(value.__format__(format_spec), float(value).__format__(format_spec)) + # Issue 6902 + test(123456L, "0<20", '12345600000000000000') + test(123456L, "1<20", '12345611111111111111') + test(123456L, "*<20", '123456**************') + test(123456L, "0>20", '00000000000000123456') + test(123456L, "1>20", '11111111111111123456') + test(123456L, "*>20", '**************123456') + test(123456L, "0=20", '00000000000000123456') + test(123456L, "1=20", '11111111111111123456') + test(123456L, "*=20", '**************123456') @run_with_locale('LC_NUMERIC', 'en_US.UTF8') def test_float__format__locale(self): @@ -689,6 +710,17 @@ class TypesTests(unittest.TestCase): self.assertRaises(ValueError, format, 0.0, '#') self.assertRaises(ValueError, format, 0.0, '#20f') + # Issue 6902 + test(12345.6, "0<20", '12345.60000000000000') + test(12345.6, "1<20", '12345.61111111111111') + test(12345.6, "*<20", '12345.6*************') + test(12345.6, "0>20", '000000000000012345.6') + test(12345.6, "1>20", '111111111111112345.6') + test(12345.6, "*>20", '*************12345.6') + test(12345.6, "0=20", '000000000000012345.6') + test(12345.6, "1=20", '111111111111112345.6') + test(12345.6, "*=20", '*************12345.6') + def test_format_spec_errors(self): # int, float, and string all share the same format spec # mini-language parser. diff --git a/Misc/NEWS b/Misc/NEWS index 89af2a4..872affe 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 4? Core and Builtins ----------------- +- Issue #6902: Fix problem with built-in types format incorrectly with + 0 padding. + - Issue #2560: remove an unnecessary 'for' loop from my_fgets() in Parser/myreadline.c. diff --git a/Objects/stringlib/formatter.h b/Objects/stringlib/formatter.h index 1bd7acb..a807b97 100644 --- a/Objects/stringlib/formatter.h +++ b/Objects/stringlib/formatter.h @@ -151,10 +151,10 @@ DEBUG_PRINT_FORMAT_SPEC(InternalFormatSpec *format) printf("internal format spec: align %d\n", format->align); printf("internal format spec: alternate %d\n", format->alternate); printf("internal format spec: sign %d\n", format->sign); - printf("internal format spec: width %d\n", format->width); + printf("internal format spec: width %zd\n", format->width); printf("internal format spec: thousands_separators %d\n", format->thousands_separators); - printf("internal format spec: precision %d\n", format->precision); + printf("internal format spec: precision %zd\n", format->precision); printf("internal format spec: type %c\n", format->type); printf("\n"); } @@ -181,6 +181,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec, the input string */ Py_ssize_t consumed; + int align_specified = 0; format->fill_char = '\0'; format->align = default_align; @@ -196,10 +197,12 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec, if (end-ptr >= 2 && is_alignment_token(ptr[1])) { format->align = ptr[1]; format->fill_char = ptr[0]; + align_specified = 1; ptr += 2; } else if (end-ptr >= 1 && is_alignment_token(ptr[0])) { format->align = ptr[0]; + align_specified = 1; ++ptr; } @@ -219,7 +222,7 @@ parse_internal_render_format_spec(STRINGLIB_CHAR *format_spec, /* The special case for 0-padding (backwards compat) */ if (format->fill_char == '\0' && end-ptr >= 1 && ptr[0] == '0') { format->fill_char = '0'; - if (format->align == '\0') { + if (!align_specified) { format->align = '='; } ++ptr; @@ -495,7 +498,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, /* min_width can go negative, that's okay. format->width == -1 means we don't care. */ - if (format->fill_char == '0') + if (format->fill_char == '0' && format->align == '=') spec->n_min_width = format->width - n_non_digit_non_padding; else spec->n_min_width = 0; -- cgit v0.12