Skip to content

Commit 9535a98

Browse files
committed
Issue #13918: Provide a locale.delocalize() function which can remove
locale-specific number formatting from a string representing a number, without then converting it to a specific type. Patch by Cédric Krier.
1 parent 2a8dc41 commit 9535a98

File tree

4 files changed

+75
-6
lines changed

4 files changed

+75
-6
lines changed

Doc/library/locale.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,14 @@ The :mod:`locale` module defines the following exception and functions:
387387
``str(float)``, but takes the decimal point into account.
388388

389389

390+
.. function:: delocalize(string)
391+
392+
Converts a string into a normalized number string, following the
393+
:const:'LC_NUMERIC`settings.
394+
395+
.. versionadded:: 3.5
396+
397+
390398
.. function:: atof(string)
391399

392400
Converts a string to a floating point number, following the :const:`LC_NUMERIC`

Lib/locale.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,8 @@ def str(val):
301301
"""Convert float to integer, taking the locale into account."""
302302
return format("%.12g", val)
303303

304-
def atof(string, func=float):
305-
"Parses a string as a float according to the locale settings."
304+
def delocalize(string):
305+
"Parses a string as a normalized number according to the locale settings."
306306
#First, get rid of the grouping
307307
ts = localeconv()['thousands_sep']
308308
if ts:
@@ -311,12 +311,15 @@ def atof(string, func=float):
311311
dd = localeconv()['decimal_point']
312312
if dd:
313313
string = string.replace(dd, '.')
314-
#finally, parse the string
315-
return func(string)
314+
return string
315+
316+
def atof(string, func=float):
317+
"Parses a string as a float according to the locale settings."
318+
return func(delocalize(string))
316319

317-
def atoi(str):
320+
def atoi(string):
318321
"Converts a string to an integer according to the locale settings."
319-
return atof(str, int)
322+
return int(delocalize(string))
320323

321324
def _test():
322325
setlocale(LC_ALL, "")

Lib/test/test_locale.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,5 +524,59 @@ def test_invalid_iterable_in_localetuple(self):
524524
locale.setlocale(locale.LC_ALL, (b'not', b'valid'))
525525

526526

527+
class BaseDelocalizeTest(BaseLocalizedTest):
528+
529+
def _test_delocalize(self, value, out):
530+
self.assertEqual(locale.delocalize(value), out)
531+
532+
def _test_atof(self, value, out):
533+
self.assertEqual(locale.atof(value), out)
534+
535+
def _test_atoi(self, value, out):
536+
self.assertEqual(locale.atoi(value), out)
537+
538+
539+
class TestEnUSDelocalize(EnUSCookedTest, BaseDelocalizeTest):
540+
541+
def test_delocalize(self):
542+
self._test_delocalize('50000.00', '50000.00')
543+
self._test_delocalize('50,000.00', '50000.00')
544+
545+
def test_atof(self):
546+
self._test_atof('50000.00', 50000.)
547+
self._test_atof('50,000.00', 50000.)
548+
549+
def test_atoi(self):
550+
self._test_atoi('50000', 50000)
551+
self._test_atoi('50,000', 50000)
552+
553+
554+
class TestCDelocalizeTest(CCookedTest, BaseDelocalizeTest):
555+
556+
def test_delocalize(self):
557+
self._test_delocalize('50000.00', '50000.00')
558+
559+
def test_atof(self):
560+
self._test_atof('50000.00', 50000.)
561+
562+
def test_atoi(self):
563+
self._test_atoi('50000', 50000)
564+
565+
566+
class TestfrFRDelocalizeTest(FrFRCookedTest, BaseDelocalizeTest):
567+
568+
def test_delocalize(self):
569+
self._test_delocalize('50000,00', '50000.00')
570+
self._test_delocalize('50 000,00', '50000.00')
571+
572+
def test_atof(self):
573+
self._test_atof('50000,00', 50000.)
574+
self._test_atof('50 000,00', 50000.)
575+
576+
def test_atoi(self):
577+
self._test_atoi('50000', 50000)
578+
self._test_atoi('50 000', 50000)
579+
580+
527581
if __name__ == '__main__':
528582
unittest.main()

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ Core and Builtins
181181
Library
182182
-------
183183

184+
- Issue #13918: Provide a locale.delocalize() function which can remove
185+
locale-specific number formatting from a string representing a number,
186+
without then converting it to a specific type. Patch by Cédric Krier.
187+
184188
- Issue #22676: Make the pickling of global objects which don't have a
185189
__module__ attribute less slow.
186190

0 commit comments

Comments
 (0)