summaryrefslogtreecommitdiffstats
path: root/Lib/locale.py
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2009-03-14 00:07:21 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2009-03-14 00:07:21 (GMT)
commitfeeafff0529c8fa0b5ab6a3086464cce8fd1b3fc (patch)
tree3e8a15f3146cbcb89abae264afa3c73002dcb004 /Lib/locale.py
parente83a4adba77d1055c564fbcc87695e259e672f5b (diff)
downloadcpython-feeafff0529c8fa0b5ab6a3086464cce8fd1b3fc.zip
cpython-feeafff0529c8fa0b5ab6a3086464cce8fd1b3fc.tar.gz
cpython-feeafff0529c8fa0b5ab6a3086464cce8fd1b3fc.tar.bz2
Issue #1222: locale.format() bug when the thousands separator is a space character.
Diffstat (limited to 'Lib/locale.py')
-rw-r--r--Lib/locale.py83
1 files changed, 51 insertions, 32 deletions
diff --git a/Lib/locale.py b/Lib/locale.py
index fd948a7..f853867 100644
--- a/Lib/locale.py
+++ b/Lib/locale.py
@@ -108,6 +108,19 @@ def localeconv():
# Author: Martin von Loewis
# improved by Georg Brandl
+# Iterate over grouping intervals
+def _grouping_intervals(grouping):
+ for interval in grouping:
+ # if grouping is -1, we are done
+ if interval == CHAR_MAX:
+ return
+ # 0: re-use last group ad infinitum
+ if interval == 0:
+ while True:
+ yield last_interval
+ yield interval
+ last_interval = interval
+
#perform the grouping from right to left
def _group(s, monetary=False):
conv = localeconv()
@@ -117,35 +130,41 @@ def _group(s, monetary=False):
return (s, 0)
result = ""
seps = 0
- spaces = ""
if s[-1] == ' ':
- sp = s.find(' ')
- spaces = s[sp:]
- s = s[:sp]
- while s and grouping:
- # if grouping is -1, we are done
- if grouping[0] == CHAR_MAX:
+ stripped = s.rstrip()
+ right_spaces = s[len(stripped):]
+ s = stripped
+ else:
+ right_spaces = ''
+ left_spaces = ''
+ groups = []
+ for interval in _grouping_intervals(grouping):
+ if not s or s[-1] not in "0123456789":
+ # only non-digit characters remain (sign, spaces)
+ left_spaces = s
+ s = ''
break
- # 0: re-use last group ad infinitum
- elif grouping[0] != 0:
- #process last group
- group = grouping[0]
- grouping = grouping[1:]
- if result:
- result = s[-group:] + thousands_sep + result
- seps += 1
- else:
- result = 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:
- return s + spaces, seps
+ groups.append(s[-interval:])
+ s = s[:-interval]
if s:
- result = s + thousands_sep + result
- seps += 1
- return result + spaces, seps
+ groups.append(s)
+ groups.reverse()
+ return (
+ left_spaces + thousands_sep.join(groups) + right_spaces,
+ len(groups) - 1
+ )
+
+# Strip a given amount of excess padding from the given string
+def _strip_padding(s, amount):
+ lpos = 0
+ while amount and s[lpos] == ' ':
+ lpos += 1
+ amount -= 1
+ rpos = len(s) - 1
+ while amount and s[rpos] == ' ':
+ rpos -= 1
+ amount -= 1
+ return s[lpos:rpos+1]
def format(percent, value, grouping=False, monetary=False, *additional):
"""Returns the locale-aware substitution of a %? specifier
@@ -170,14 +189,14 @@ def format(percent, value, grouping=False, monetary=False, *additional):
decimal_point = localeconv()[monetary and 'mon_decimal_point'
or 'decimal_point']
formatted = decimal_point.join(parts)
- while seps:
- sp = formatted.find(' ')
- if sp == -1: break
- formatted = formatted[:sp] + formatted[sp+1:]
- seps -= 1
+ if seps:
+ formatted = _strip_padding(formatted, seps)
elif percent[-1] in 'diu':
+ seps = 0
if grouping:
- formatted = _group(formatted, monetary=monetary)[0]
+ formatted, seps = _group(formatted, monetary=monetary)
+ if seps:
+ formatted = _strip_padding(formatted, seps)
return formatted
import re, operator