Commit 8e0461f8 authored by Martin v. Löwis's avatar Martin v. Löwis

Patch #415777: new grouping strategy.

fixes bug #414940, and redoes the fix for #129417 in a different way.
It also fixes a number of other problems with locale-specific formatting:
If there is leading or trailing spaces, then no grouping should be applied
in the spaces, and the total length of the string should not be changed
due to grouping.
Also added test case which works only if the en_US locale is available.
parent 7039a158
...@@ -95,6 +95,12 @@ def _group(s): ...@@ -95,6 +95,12 @@ def _group(s):
grouping=conv['grouping'] grouping=conv['grouping']
if not grouping:return s if not grouping:return s
result="" result=""
seps = 0
spaces = ""
if s[-1] == ' ':
sp = s.find(' ')
spaces = s[sp:]
s = s[:sp]
while s and grouping: while s and grouping:
# if grouping is -1, we are done # if grouping is -1, we are done
if grouping[0]==CHAR_MAX: if grouping[0]==CHAR_MAX:
...@@ -106,34 +112,48 @@ def _group(s): ...@@ -106,34 +112,48 @@ def _group(s):
grouping=grouping[1:] grouping=grouping[1:]
if result: if result:
result=s[-group:]+conv['thousands_sep']+result result=s[-group:]+conv['thousands_sep']+result
seps += 1
else: else:
result=s[-group:] result=s[-group:]
s=s[:-group] s=s[:-group]
if s and s[-1] not in "0123456789":
# the leading string is only spaces and signs
return s+result+spaces,seps
if not result: if not result:
return s return s+spaces,seps
if s: if s:
result=s+conv['thousands_sep']+result result=s+conv['thousands_sep']+result
return result seps += 1
return result+spaces,seps
def format(f,val,grouping=0): def format(f,val,grouping=0):
"""Formats a value in the same way that the % formatting would use, """Formats a value in the same way that the % formatting would use,
but takes the current locale into account. but takes the current locale into account.
Grouping is applied if the third parameter is true.""" Grouping is applied if the third parameter is true."""
result = f % abs(val) result = f % val
fields = result.split(".") fields = result.split(".")
seps = 0
if grouping: if grouping:
fields[0]=_group(fields[0]) fields[0],seps=_group(fields[0])
if len(fields)==2: if len(fields)==2:
res = fields[0]+localeconv()['decimal_point']+fields[1] result = fields[0]+localeconv()['decimal_point']+fields[1]
elif len(fields)==1: elif len(fields)==1:
res = fields[0] result = fields[0]
else: else:
raise Error, "Too many decimal points in result string" raise Error, "Too many decimal points in result string"
if val < 0: while seps:
return '-'+res # If the number was formatted for a specific width, then it
else: # might have been filled with spaces to the left or right. If
return res # so, kill as much spaces as there where separators.
# Leading zeroes as fillers are not yet dealt with, as it is
# not clear how they should interact with grouping.
sp = result.find(" ")
if sp==-1:break
result = result[:sp]+result[sp+1:]
seps -= 1
return result
def str(val): def str(val):
"""Convert float to integer, taking the locale into account.""" """Convert float to integer, taking the locale into account."""
......
from test_support import verbose
import locale
oldlocale = locale.setlocale(locale.LC_NUMERIC)
try:
locale.setlocale(locale.LC_NUMERIC, "en_US")
except locale.Error:
raise ImportError, "test locale en_US not supported"
def testformat(formatstr, value, grouping = 0, output=None):
if verbose:
if output:
print "%s %% %s =? %s ..." %\
(repr(formatstr), repr(value), repr(output)),
else:
print "%s %% %s works? ..." % (repr(formatstr), repr(value)),
result = locale.format(formatstr, value, grouping = grouping)
if output and result != output:
if verbose:
print 'no'
print "%s %% %s == %s != %s" %\
(repr(formatstr), repr(value), repr(result), repr(output))
else:
if verbose:
print "yes"
try:
testformat("%f", 1024, grouping=1, output='1,024.000000')
testformat("%f", 102, grouping=1, output='102.000000')
testformat("%f", -42, grouping=1, output='-42.000000')
testformat("%+f", -42, grouping=1, output='-42.000000')
testformat("%20.f", -42, grouping=1, output=' -42')
testformat("%+10.f", -4200, grouping=1, output=' -4,200')
testformat("%-10.f", 4200, grouping=1, output='4,200 ')
finally:
locale.setlocale(locale.LC_NUMERIC, oldlocale)
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