Kaydet (Commit) 3939dcdb authored tarafından R. David Murray's avatar R. David Murray

Issue #6656: fix locale.format_string to handle escaped percents and mappings.

Refactors format_string.  Includes tests for the two problems noted in
the issue, but as far as I can see there are no other tests that confirm
that format_string conforms to normal % formatting rules.
üst 278d665c
...@@ -220,22 +220,30 @@ def format_string(f, val, grouping=False): ...@@ -220,22 +220,30 @@ def format_string(f, val, grouping=False):
percents = list(_percent_re.finditer(f)) percents = list(_percent_re.finditer(f))
new_f = _percent_re.sub('%s', f) new_f = _percent_re.sub('%s', f)
if isinstance(val, tuple): if operator.isMappingType(val):
new_val = list(val) new_val = []
i = 0
for perc in percents:
starcount = perc.group('modifiers').count('*')
new_val[i] = format(perc.group(), new_val[i], grouping, False, *new_val[i+1:i+1+starcount])
del new_val[i+1:i+1+starcount]
i += (1 + starcount)
val = tuple(new_val)
elif operator.isMappingType(val):
for perc in percents: for perc in percents:
key = perc.group("key") if perc.group()[-1]=='%':
val[key] = format(perc.group(), val[key], grouping) new_val.append('%')
else:
new_val.append(format(perc.group(), val, grouping))
else: else:
# val is a single value if not isinstance(val, tuple):
val = format(percents[0].group(), val, grouping) val = (val,)
new_val = []
i = 0
for perc in percents:
if perc.group()[-1]=='%':
new_val.append('%')
else:
starcount = perc.group('modifiers').count('*')
new_val.append(_format(perc.group(),
val[i],
grouping,
False,
*val[i+1:i+1+starcount]))
i += (1 + starcount)
val = tuple(new_val)
return new_f % val return new_f % val
......
...@@ -238,6 +238,25 @@ class TestFormatPatternArg(unittest.TestCase): ...@@ -238,6 +238,25 @@ class TestFormatPatternArg(unittest.TestCase):
self.assertRaises(ValueError, locale.format, " %f", 'foo') self.assertRaises(ValueError, locale.format, " %f", 'foo')
self.assertRaises(ValueError, locale.format, "%fg", 'foo') self.assertRaises(ValueError, locale.format, "%fg", 'foo')
self.assertRaises(ValueError, locale.format, "%^g", 'foo') self.assertRaises(ValueError, locale.format, "%^g", 'foo')
self.assertRaises(ValueError, locale.format, "%f%%", 'foo')
class TestLocaleFormatString(unittest.TestCase):
"""General tests on locale.format_string"""
def test_percent_escape(self):
self.assertEqual(locale.format_string('%f%%', 1.0), '%f%%' % 1.0)
self.assertEqual(locale.format_string('%d %f%%d', (1, 1.0)),
'%d %f%%d' % (1, 1.0))
self.assertEqual(locale.format_string('%(foo)s %%d', {'foo': 'bar'}),
('%(foo)s %%d' % {'foo': 'bar'}))
def test_mapping(self):
self.assertEqual(locale.format_string('%(foo)s bing.', {'foo': 'bar'}),
('%(foo)s bing.' % {'foo': 'bar'}))
self.assertEqual(locale.format_string('%(foo)s', {'foo': 'bar'}),
('%(foo)s' % {'foo': 'bar'}))
class TestNumberFormatting(BaseLocalizedTest, EnUSNumberFormatting): class TestNumberFormatting(BaseLocalizedTest, EnUSNumberFormatting):
...@@ -382,6 +401,7 @@ def test_main(): ...@@ -382,6 +401,7 @@ def test_main():
tests = [ tests = [
TestMiscellaneous, TestMiscellaneous,
TestFormatPatternArg, TestFormatPatternArg,
TestLocaleFormatString,
TestEnUSNumberFormatting, TestEnUSNumberFormatting,
TestCNumberFormatting, TestCNumberFormatting,
TestFrFRNumberFormatting, TestFrFRNumberFormatting,
......
...@@ -27,6 +27,9 @@ Core and Builtins ...@@ -27,6 +27,9 @@ Core and Builtins
Library Library
------- -------
- Issue #6656: fix locale.format_string to handle escaped percents
and mappings.
- Issue #2302: Fix a race condition in SocketServer.BaseServer.shutdown, - Issue #2302: Fix a race condition in SocketServer.BaseServer.shutdown,
where the method could block indefinitely if called just before the where the method could block indefinitely if called just before the
event loop started running. This also fixes the occasional freezes event loop started running. This also fixes the occasional freezes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment