summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorR. David Murray <rdmurray@bitdance.com>2009-04-01 03:21:43 (GMT)
committerR. David Murray <rdmurray@bitdance.com>2009-04-01 03:21:43 (GMT)
commita83da3507f6f6075cce143cb118d3ddb23df981c (patch)
tree75e643486900e3c7547e16c70b92dd98fbf346e9 /Lib
parentbb94d43dcdbfddff40f23944f0e4079f41a30421 (diff)
downloadcpython-a83da3507f6f6075cce143cb118d3ddb23df981c.zip
cpython-a83da3507f6f6075cce143cb118d3ddb23df981c.tar.gz
cpython-a83da3507f6f6075cce143cb118d3ddb23df981c.tar.bz2
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.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/locale.py23
-rw-r--r--Lib/test/test_locale.py14
2 files changed, 29 insertions, 8 deletions
diff --git a/Lib/locale.py b/Lib/locale.py
index 163b044..777bb03 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 operator
import functools
# Try importing the _locale module.
@@ -166,6 +170,9 @@ def _strip_padding(s, amount):
amount -= 1
return s[lpos:rpos+1]
+_percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?'
+ r'(?P<modifiers>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]')
+
def format(percent, value, grouping=False, monetary=False, *additional):
"""Returns the locale-aware substitution of a %? specifier
(percent).
@@ -173,9 +180,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:
@@ -199,10 +210,6 @@ def format(percent, value, grouping=False, monetary=False, *additional):
formatted = _strip_padding(formatted, seps)
return formatted
-import re, operator
-_percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?'
- r'(?P<modifiers>[-#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 180f403..d9d3cd9 100644
--- a/Lib/test/test_locale.py
+++ b/Lib/test/test_locale.py
@@ -221,6 +221,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.
@@ -351,6 +364,7 @@ class TestMiscellaneous(unittest.TestCase):
def test_main():
tests = [
TestMiscellaneous,
+ TestFormatPatternArg,
TestEnUSNumberFormatting,
TestCNumberFormatting,
TestFrFRNumberFormatting,