New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
locale.format() and locale.format_string() cast Decimals to float #78492
Comments
We use locale.format('%.2f', x, True) to convert Decimal values to strings for display. Unfortunately, the locale module is using %-formatting to generate the initial string before applying locale specific formatting. As a result, any value which cannot be accurately represented as a float will produce incorrect results. I've built some formatting that uses new-style string formatting (and some internal locale functions) which corrects the problem. Unfortunately, making this change in the locale module would require converting the input format string to the new syntax, so '%.2f' would become '{:.2f}'. See also bpo-33731 |
Would my suggestion in bpo-33731 of adding another letter in the format spec for float and decimal.Decimal solve your problem? I guess if you're using monetary=True you'd need two additional letters: like 'f' but locale aware, and like 'f' but locale aware and monetary=True. Maybe 'l' and 'L' for these? In this case, there would be no changes to the locale module. I don't see any good way of using new-style formatting without changing float.__format__ and decimal.Decimal.__format__. |
Certainly adding another letter to the format spec would solve my issue and would in fact be somewhat preferable to using local.format directly. I think this could be fixed in the locale module by transforming the format spec and using new-style formatting, but I'm not familiar enough with the corner cases to know if its practical to cover all the possible cases; particularly those coming from format_string(). |
It looks like a bot got a bit excited when I mentioned this issue in the PR for bpo-33731. I unlinked the PR but this issue still got flagged for review. |
I think we can solve this issue like I solved bpo-13918 by providing a locale.localize() method which does the formatting as locale.format_string does but using the already formatted string. I created PR-15275 which implements it and also use the new format in locale.currency as it is highly probable that currency will be used with Decimal. |
Does the name "locale.localize" have some origin? I feel the name doesn't represent well about it is for formatting numeric based on LC_NUMERIC. |
For me, the name was natural as it is the reverse operation of the existing delocalize method. |
Verified. Methododology:
.. code-block:: Ran 64 tests in 0.023s FAILED (errors=4, skipped=4) Traceback (most recent call last):
File "/Users/sholden/cpython/Lib/test/test_locale.py", line 613, in test_localize_invalid_format
locale.localize('foo')
AssertionError: ValueError not raised ====================================================================== Traceback (most recent call last):
File "/Users/sholden/cpython/Lib/test/test_locale.py", line 625, in test_localize
self._test_localize('50000.00', '50000,00')
File "/Users/sholden/cpython/Lib/test/test_locale.py", line 601, in _test_localize
self.assertEqual(locale.localize(value, grouping=grouping), out)
AssertionError: '50000.00' != '50000,00'
- 50000.00
? ^
+ 50000,00
? ^ ---------------------------------------------------------------------- FAILED (failures=2, skipped=4)
Seems to me like this one should be good to go, so I've changed the stage to "commit review" and await the application of some core developer's commit bit. |
I have merged the PR, thank you to Cédric for the PR, and thank you to Steve for his review. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: