summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCédric Krier <cedk@users.noreply.github.com>2021-04-12 14:17:40 +0200
committerGitHub <noreply@github.com>2021-04-12 14:17:40 +0200
commite126547c070fbc080562abb08e16a2c93a8a805d (patch)
treeec2d7f22999855aa870d69891fb476106f2b9fe0
parent95bbb331ecb3ef5d05859d90b287cc3d27613c86 (diff)
downloadcpython-git-e126547c070fbc080562abb08e16a2c93a8a805d.tar.gz
bpo-34311: Add locale.localize (GH-15275)
* Add method localize to the locale module * Update the documentation of the locale module
-rw-r--r--Doc/library/locale.rst8
-rw-r--r--Lib/locale.py16
-rw-r--r--Lib/test/test_locale.py28
-rw-r--r--Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst2
4 files changed, 51 insertions, 3 deletions
diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst
index 0a77be47fb..60d0c59d01 100644
--- a/Doc/library/locale.rst
+++ b/Doc/library/locale.rst
@@ -427,6 +427,14 @@ The :mod:`locale` module defines the following exception and functions:
.. versionadded:: 3.5
+.. function:: localize(string, grouping=False, monetary=False)
+
+ Converts a normalized number string into a formatted string following the
+ :const:`LC_NUMERIC` settings.
+
+ .. versionadded:: 3.10
+
+
.. function:: atof(string)
Converts a string to a floating point number, following the :const:`LC_NUMERIC`
diff --git a/Lib/locale.py b/Lib/locale.py
index ee841e8b86..6d4f519299 100644
--- a/Lib/locale.py
+++ b/Lib/locale.py
@@ -185,8 +185,14 @@ def _format(percent, value, grouping=False, monetary=False, *additional):
formatted = percent % ((value,) + additional)
else:
formatted = percent % value
+ if percent[-1] in 'eEfFgGdiu':
+ formatted = _localize(formatted, grouping, monetary)
+ return formatted
+
+# Transform formatted as locale number according to the locale settings
+def _localize(formatted, grouping=False, monetary=False):
# floats and decimal ints need special action!
- if percent[-1] in 'eEfFgG':
+ if '.' in formatted:
seps = 0
parts = formatted.split('.')
if grouping:
@@ -196,7 +202,7 @@ def _format(percent, value, grouping=False, monetary=False, *additional):
formatted = decimal_point.join(parts)
if seps:
formatted = _strip_padding(formatted, seps)
- elif percent[-1] in 'diu':
+ else:
seps = 0
if grouping:
formatted, seps = _group(formatted, monetary=monetary)
@@ -267,7 +273,7 @@ def currency(val, symbol=True, grouping=False, international=False):
raise ValueError("Currency formatting is not possible using "
"the 'C' locale.")
- s = _format('%%.%if' % digits, abs(val), grouping, monetary=True)
+ s = _localize(f'{abs(val):.{digits}f}', grouping, monetary=True)
# '<' and '>' are markers if the sign must be inserted between symbol and value
s = '<' + s + '>'
@@ -323,6 +329,10 @@ def delocalize(string):
string = string.replace(dd, '.')
return string
+def localize(string, grouping=False, monetary=False):
+ """Parses a string as locale number according to the locale settings."""
+ return _localize(string, grouping, monetary)
+
def atof(string, func=float):
"Parses a string as a float according to the locale settings."
return func(delocalize(string))
diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py
index 4bb4c5541d..2c788f2dfa 100644
--- a/Lib/test/test_locale.py
+++ b/Lib/test/test_locale.py
@@ -1,3 +1,4 @@
+from decimal import Decimal
from test.support import verbose, is_android
from test.support.warnings_helper import check_warnings
import unittest
@@ -636,5 +637,32 @@ class TestfrFRDelocalizeTest(FrFRCookedTest, BaseDelocalizeTest):
self._test_atoi('50 000', 50000)
+class BaseLocalizeTest(BaseLocalizedTest):
+
+ def _test_localize(self, value, out, grouping=False):
+ self.assertEqual(locale.localize(value, grouping=grouping), out)
+
+
+class TestEnUSLocalize(EnUSCookedTest, BaseLocalizeTest):
+
+ def test_localize(self):
+ self._test_localize('50000.00', '50000.00')
+ self._test_localize(
+ '{0:.16f}'.format(Decimal('1.15')), '1.1500000000000000')
+
+
+class TestCLocalize(CCookedTest, BaseLocalizeTest):
+
+ def test_localize(self):
+ self._test_localize('50000.00', '50000.00')
+
+
+class TestfrFRLocalize(FrFRCookedTest, BaseLocalizeTest):
+
+ def test_localize(self):
+ self._test_localize('50000.00', '50000,00')
+ self._test_localize('50000.00', '50 000,00', grouping=True)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst b/Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst
new file mode 100644
index 0000000000..2fedb0696c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst
@@ -0,0 +1,2 @@
+Provide a locale.localize() function, which converts a normalized number string
+into a locale format.