From e59482ec9a44a9cf8c5e066c340dc9ed78399712 Mon Sep 17 00:00:00 2001 From: "R. David Murray" Date: Wed, 1 Apr 2009 03:42:00 +0000 Subject: [PATCH] Merged revisions 70936 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r70936 | r.david.murray | 2009-03-31 23:21:43 -0400 (Tue, 31 Mar 2009) | 4 lines Fix issue 2522. locale.format now checks that it is passed exactly one pattern, which avoids mysterious errors where it had seemed to fail to do localization. ........ --- Lib/locale.py | 23 +++++++++++++++-------- Lib/test/test_locale.py | 14 ++++++++++++++ Misc/ACKS | 2 ++ Misc/NEWS | 4 ++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/Lib/locale.py b/Lib/locale.py index 17056b9df21..372c955d0ef 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -11,7 +11,11 @@ """ -import sys, encodings, encodings.aliases +import sys +import encodings +import encodings.aliases +import re +import collections from builtins import str as _builtin_str import functools @@ -173,6 +177,9 @@ def _strip_padding(s, amount): amount -= 1 return s[lpos:rpos+1] +_percent_re = re.compile(r'%(?:\((?P.*?)\))?' + r'(?P[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]') + def format(percent, value, grouping=False, monetary=False, *additional): """Returns the locale-aware substitution of a %? specifier (percent). @@ -180,9 +187,13 @@ def format(percent, value, grouping=False, monetary=False, *additional): additional is for format strings which contain one or more '*' modifiers.""" # this is only for one-percent-specifier strings and this should be checked - if percent[0] != '%': - raise ValueError("format() must be given exactly one %char " - "format specifier") + match = _percent_re.match(percent) + if not match or len(match.group())!= len(percent): + raise ValueError(("format() must be given exactly one %%char " + "format specifier, %s not valid") % repr(percent)) + return _format(percent, value, grouping, monetary, *additional) + +def _format(percent, value, grouping=False, monetary=False, *additional): if additional: formatted = percent % ((value,) + additional) else: @@ -206,10 +217,6 @@ def format(percent, value, grouping=False, monetary=False, *additional): formatted = _strip_padding(formatted, seps) return formatted -import re, collections -_percent_re = re.compile(r'%(?:\((?P.*?)\))?' - r'(?P[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]') - def format_string(f, val, grouping=False): """Formats a string in the same way that the % formatting would use, but takes the current locale into account. diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index c77dc5522a4..65639ad014e 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -219,6 +219,19 @@ class EnUSNumberFormatting(BaseFormattingTest): (self.sep, self.sep)) +class TestFormatPatternArg(unittest.TestCase): + # Test handling of pattern argument of format + + def test_onlyOnePattern(self): + # Issue 2522: accept exactly one % pattern, and no extra chars. + self.assertRaises(ValueError, locale.format, "%f\n", 'foo') + self.assertRaises(ValueError, locale.format, "%f\r", 'foo') + self.assertRaises(ValueError, locale.format, "%f\r\n", 'foo') + self.assertRaises(ValueError, locale.format, " %f", 'foo') + self.assertRaises(ValueError, locale.format, "%fg", 'foo') + self.assertRaises(ValueError, locale.format, "%^g", 'foo') + + class TestNumberFormatting(BaseLocalizedTest, EnUSNumberFormatting): # Test number formatting with a real English locale. @@ -314,6 +327,7 @@ class TestMiscellaneous(unittest.TestCase): def test_main(): tests = [ TestMiscellaneous, + TestFormatPatternArg, TestEnUSNumberFormatting, TestCNumberFormatting, TestFrFRNumberFormatting, diff --git a/Misc/ACKS b/Misc/ACKS index 8ca5b7ff96e..acde8152234 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -482,6 +482,7 @@ Damien Miller Chad Miller Jay T. Miller Roman Milner +Andrii V. Mishkovskyi Dustin J. Mitchell Dom Mitchell Doug Moen @@ -492,6 +493,7 @@ James A Morrison Sjoerd Mullender Sape Mullender Michael Muller +R. David Murray Piotr Meyer John Nagle Takahiro Nakayama diff --git a/Misc/NEWS b/Misc/NEWS index ee96d22d837..7f0808d3514 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -284,6 +284,10 @@ Core and Builtins Library ------- +- Issue #2522: locale.format now checks its first argument to ensure it has + been passed only one pattern, avoiding mysterious errors where it appeared + that it was failing to do localization. + - Issue #5583: Added optional Extensions in Distutils. Initial patch by Georg Brandl.