[Python-checkins] bpo-34311: Add locale.localize (GH-15275)

matrixise webhook-mailer at python.org
Mon Apr 12 08:17:49 EDT 2021


https://github.com/python/cpython/commit/e126547c070fbc080562abb08e16a2c93a8a805d
commit: e126547c070fbc080562abb08e16a2c93a8a805d
branch: master
author: Cédric Krier <cedk at users.noreply.github.com>
committer: matrixise <stephane at wirtel.be>
date: 2021-04-12T14:17:40+02:00
summary:

bpo-34311: Add locale.localize (GH-15275)

* Add method localize to the locale module
* Update the documentation of the locale module

files:
A Misc/NEWS.d/next/Library/2019-08-14-13-19-50.bpo-33731.9esS0d.rst
M Doc/library/locale.rst
M Lib/locale.py
M Lib/test/test_locale.py

diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst
index 0a77be47fb899..60d0c59d017c7 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 ee841e8b8655e..6d4f51929923f 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 4bb4c5541d077..2c788f2dfa65e 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 @@ def test_atoi(self):
         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 0000000000000..2fedb0696c326
--- /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.



More information about the Python-checkins mailing list