mirror of https://github.com/python/cpython
bpo-10379: add 'monetary' to format_string, deprecate format
Add the 'monetary' parameter to format_string so that all uses of format can be converted to format_string. Adjust the documentation accordingly, and add a deprecation warning when format is used.
This commit is contained in:
parent
c8fa45bac2
commit
1cf93a76c2
|
@ -352,7 +352,7 @@ The :mod:`locale` module defines the following exception and functions:
|
|||
sequence of strings.
|
||||
|
||||
|
||||
.. function:: format(format, val, grouping=False, monetary=False)
|
||||
.. function:: format_string(format, val, grouping=False, monetary=False)
|
||||
|
||||
Formats a number *val* according to the current :const:`LC_NUMERIC` setting.
|
||||
The format follows the conventions of the ``%`` operator. For floating point
|
||||
|
@ -362,15 +362,23 @@ The :mod:`locale` module defines the following exception and functions:
|
|||
If *monetary* is true, the conversion uses monetary thousands separator and
|
||||
grouping strings.
|
||||
|
||||
Please note that this function will only work for exactly one %char specifier.
|
||||
For whole format strings, use :func:`format_string`.
|
||||
|
||||
|
||||
.. function:: format_string(format, val, grouping=False)
|
||||
|
||||
Processes formatting specifiers as in ``format % val``, but takes the current
|
||||
locale settings into account.
|
||||
|
||||
.. versionchanged:: 3.7
|
||||
The *monetary* keyword parameter was added.
|
||||
|
||||
|
||||
.. function:: format(format, val, grouping=False, monetary=False)
|
||||
|
||||
Please note that this function works like format_string but will only work
|
||||
for exactly one %char specifier.
|
||||
|
||||
For whole format strings, use :func:`format_string`.
|
||||
|
||||
.. deprecated:: 3.7
|
||||
Use :meth:`format_string` instead
|
||||
|
||||
|
||||
.. function:: currency(val, symbol=True, grouping=False, international=False)
|
||||
|
||||
|
|
|
@ -76,16 +76,14 @@ Other Language Changes
|
|||
======================
|
||||
|
||||
* More than 255 arguments can now be passed to a function, and a function can
|
||||
now have more than 255 parameters.
|
||||
(Contributed by Serhiy Storchaka in :issue:`12844` and :issue:`18896`.)
|
||||
now have more than 255 parameters. (Contributed by Serhiy Storchaka in
|
||||
:issue:`12844` and :issue:`18896`.)
|
||||
|
||||
* :meth:`bytes.fromhex` and :meth:`bytearray.fromhex` now ignore all ASCII
|
||||
whitespace, not only spaces.
|
||||
(Contributed by Robert Xiao in :issue:`28927`.)
|
||||
whitespace, not only spaces. (Contributed by Robert Xiao in :issue:`28927`.)
|
||||
|
||||
* :exc:`ImportError` now displays module name and module ``__file__`` path when
|
||||
``from ... import ...`` fails.
|
||||
(Contributed by Matthias Bussonnier in :issue:`29546`.)
|
||||
``from ... import ...`` fails. (Contributed by Matthias Bussonnier in :issue:`29546`.)
|
||||
|
||||
|
||||
New Modules
|
||||
|
@ -97,25 +95,32 @@ New Modules
|
|||
Improved Modules
|
||||
================
|
||||
|
||||
locale
|
||||
------
|
||||
|
||||
Added another argument *monetary* in :meth:`format_string` of :mod:`locale`.
|
||||
If *monetary* is true, the conversion uses monetary thousands separator and
|
||||
grouping strings. (Contributed by Garvit in :issue:`10379`.)
|
||||
|
||||
os
|
||||
--
|
||||
|
||||
Added support for :class:`bytes` paths in :func:`~os.fwalk`.
|
||||
(Contributed by Serhiy Storchaka in :issue:`28682`.)
|
||||
Added support for :class:`bytes` paths in :func:`~os.fwalk`. (Contributed by
|
||||
Serhiy Storchaka in :issue:`28682`.)
|
||||
|
||||
unittest.mock
|
||||
-------------
|
||||
|
||||
The :const:`~unittest.mock.sentinel` attributes now preserve their identity
|
||||
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`.
|
||||
(Contributed by Serhiy Storchaka in :issue:`20804`.)
|
||||
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`. (Contributed by
|
||||
Serhiy Storchaka in :issue:`20804`.)
|
||||
|
||||
xmlrpc.server
|
||||
-------------
|
||||
|
||||
:meth:`register_function` of :class:`xmlrpc.server.SimpleXMLRPCDispatcher` and
|
||||
its subclasses can be used as a decorator.
|
||||
(Contributed by Xiang Zhang in :issue:`7769`.)
|
||||
its subclasses can be used as a decorator. (Contributed by Xiang Zhang in
|
||||
:issue:`7769`.)
|
||||
|
||||
urllib.parse
|
||||
------------
|
||||
|
@ -130,13 +135,13 @@ Optimizations
|
|||
|
||||
* Added two new opcodes: ``LOAD_METHOD`` and ``CALL_METHOD`` to avoid
|
||||
instantiation of bound method objects for method calls, which results
|
||||
in method calls being faster up to 20%.
|
||||
(Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.)
|
||||
in method calls being faster up to 20%. (Contributed by Yury Selivanov and
|
||||
INADA Naoki in :issue:`26110`.)
|
||||
|
||||
* Fast implementation from standard C library is now used for functions
|
||||
:func:`~math.tgamma`, :func:`~math.lgamma`, :func:`~math.erf` and
|
||||
:func:`~math.erfc` in the :mod:`math` module.
|
||||
(Contributed by Serhiy Storchaka in :issue:`26121`.)
|
||||
:func:`~math.erfc` in the :mod:`math` module. (Contributed by Serhiy
|
||||
Storchaka in :issue:`26121`.)
|
||||
|
||||
|
||||
Build and C API Changes
|
||||
|
@ -154,8 +159,8 @@ Build and C API Changes
|
|||
``char *``. (Contributed by Serhiy Storchaka in :issue:`28761`.)
|
||||
|
||||
* The result of :c:func:`PyUnicode_AsUTF8AndSize` and :c:func:`PyUnicode_AsUTF8`
|
||||
is now of type ``const char *`` rather of ``char *``.
|
||||
(Contributed by Serhiy Storchaka in :issue:`28769`.)
|
||||
is now of type ``const char *`` rather of ``char *``. (Contributed by Serhiy
|
||||
Storchaka in :issue:`28769`.)
|
||||
|
||||
* Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`.
|
||||
(Contributed by Serhiy Storchaka in :issue:`27867`.)
|
||||
|
@ -169,6 +174,9 @@ Deprecated
|
|||
``0x03050400`` and ``0x03060000`` (not including) or ``0x03060100`` or
|
||||
higher. (Contributed by Serhiy Storchaka in :issue:`27867`.)
|
||||
|
||||
- Deprecated :meth:`format` from :mod:`locale`, use the :meth:`format_string`
|
||||
instead. (Contributed by Garvit in :issue:`10379`.)
|
||||
|
||||
- Methods
|
||||
:meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>`
|
||||
(replaced by
|
||||
|
@ -181,8 +189,8 @@ Deprecated
|
|||
by Matthias Bussonnier in :issue:`29576`)
|
||||
|
||||
- Using non-integer value for selecting a plural form in :mod:`gettext` is
|
||||
now deprecated. It never correctly worked.
|
||||
(Contributed by Serhiy Storchaka in :issue:`28692`.)
|
||||
now deprecated. It never correctly worked. (Contributed by Serhiy Storchaka
|
||||
in :issue:`28692`.)
|
||||
|
||||
|
||||
Changes in the C API
|
||||
|
@ -229,8 +237,8 @@ Changes in the Python API
|
|||
|
||||
* A format string argument for :meth:`string.Formatter.format`
|
||||
is now :ref:`positional-only <positional-only_parameter>`.
|
||||
Passing it as a keyword argument was deprecated in Python 3.5.
|
||||
(Contributed by Serhiy Storchaka in :issue:`29193`.)
|
||||
Passing it as a keyword argument was deprecated in Python 3.5. (Contributed
|
||||
by Serhiy Storchaka in :issue:`29193`.)
|
||||
|
||||
* Attributes :attr:`~http.cookies.Morsel.key`,
|
||||
:attr:`~http.cookies.Morsel.value` and
|
||||
|
@ -244,8 +252,8 @@ Changes in the Python API
|
|||
``ClassDef`` AST nodes now have a new ``docstring`` field.
|
||||
The first statement in their body is not considered as a docstring
|
||||
anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class
|
||||
and module are affected by this change.
|
||||
(Contributed by INADA Naoki and Eugene Toder in :issue:`29463`.)
|
||||
and module are affected by this change. (Contributed by INADA Naoki and
|
||||
Eugene Toder in :issue:`29463`.)
|
||||
|
||||
* The *mode* argument of :func:`os.makedirs` no longer affects the file
|
||||
permission bits of newly-created intermediate-level directories.
|
||||
|
|
|
@ -17,6 +17,7 @@ import re
|
|||
import collections
|
||||
from builtins import str as _builtin_str
|
||||
import functools
|
||||
import warnings
|
||||
|
||||
# Try importing the _locale module.
|
||||
#
|
||||
|
@ -180,19 +181,6 @@ def _strip_padding(s, amount):
|
|||
_percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?'
|
||||
r'(?P<modifiers>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]')
|
||||
|
||||
def format(percent, value, grouping=False, monetary=False, *additional):
|
||||
"""Returns the locale-aware substitution of a %? specifier
|
||||
(percent).
|
||||
|
||||
additional is for format strings which contain one or more
|
||||
'*' modifiers."""
|
||||
# this is only for one-percent-specifier strings and this should be checked
|
||||
match = _percent_re.match(percent)
|
||||
if not match or len(match.group())!= len(percent):
|
||||
raise ValueError(("format() must be given exactly one %%char "
|
||||
"format specifier, %s not valid") % repr(percent))
|
||||
return _format(percent, value, grouping, monetary, *additional)
|
||||
|
||||
def _format(percent, value, grouping=False, monetary=False, *additional):
|
||||
if additional:
|
||||
formatted = percent % ((value,) + additional)
|
||||
|
@ -217,10 +205,13 @@ def _format(percent, value, grouping=False, monetary=False, *additional):
|
|||
formatted = _strip_padding(formatted, seps)
|
||||
return formatted
|
||||
|
||||
def format_string(f, val, grouping=False):
|
||||
def format_string(f, val, grouping=False, monetary=False):
|
||||
"""Formats a string in the same way that the % formatting would use,
|
||||
but takes the current locale into account.
|
||||
Grouping is applied if the third parameter is true."""
|
||||
|
||||
Grouping is applied if the third parameter is true.
|
||||
Conversion uses monetary thousands separator and grouping strings if
|
||||
forth parameter monetary is true."""
|
||||
percents = list(_percent_re.finditer(f))
|
||||
new_f = _percent_re.sub('%s', f)
|
||||
|
||||
|
@ -230,7 +221,7 @@ def format_string(f, val, grouping=False):
|
|||
if perc.group()[-1]=='%':
|
||||
new_val.append('%')
|
||||
else:
|
||||
new_val.append(format(perc.group(), val, grouping))
|
||||
new_val.append(_format(perc.group(), val, grouping, monetary))
|
||||
else:
|
||||
if not isinstance(val, tuple):
|
||||
val = (val,)
|
||||
|
@ -244,13 +235,27 @@ def format_string(f, val, grouping=False):
|
|||
new_val.append(_format(perc.group(),
|
||||
val[i],
|
||||
grouping,
|
||||
False,
|
||||
monetary,
|
||||
*val[i+1:i+1+starcount]))
|
||||
i += (1 + starcount)
|
||||
val = tuple(new_val)
|
||||
|
||||
return new_f % val
|
||||
|
||||
def format(percent, value, grouping=False, monetary=False, *additional):
|
||||
"""Deprecated, use format_string instead."""
|
||||
warnings.warn(
|
||||
"This method will be removed in a future version of Python."
|
||||
"Use 'locale.format_string()' instead.",
|
||||
DeprecationWarning, stacklevel=2
|
||||
)
|
||||
|
||||
match = _percent_re.match(percent)
|
||||
if not match or len(match.group())!= len(percent):
|
||||
raise ValueError(("format() must be given exactly one %%char "
|
||||
"format specifier, %s not valid") % repr(percent))
|
||||
return _format(percent, value, grouping, monetary, *additional)
|
||||
|
||||
def currency(val, symbol=True, grouping=False, international=False):
|
||||
"""Formats val according to the currency settings
|
||||
in the current locale."""
|
||||
|
@ -262,7 +267,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 = _format('%%.%if' % digits, abs(val), grouping, monetary=True)
|
||||
# '<' and '>' are markers if the sign must be inserted between symbol and value
|
||||
s = '<' + s + '>'
|
||||
|
||||
|
@ -298,7 +303,7 @@ def currency(val, symbol=True, grouping=False, international=False):
|
|||
|
||||
def str(val):
|
||||
"""Convert float to string, taking the locale into account."""
|
||||
return format("%.12g", val)
|
||||
return _format("%.12g", val)
|
||||
|
||||
def delocalize(string):
|
||||
"Parses a string as a normalized number according to the locale settings."
|
||||
|
@ -327,7 +332,7 @@ def atoi(string):
|
|||
def _test():
|
||||
setlocale(LC_ALL, "")
|
||||
#do grouping
|
||||
s1 = format("%d", 123456789,1)
|
||||
s1 = format_string("%d", 123456789,1)
|
||||
print(s1, "is", atoi(s1))
|
||||
#standard formatting
|
||||
s1 = str(3.14)
|
||||
|
|
|
@ -3,6 +3,7 @@ import unittest
|
|||
import locale
|
||||
import sys
|
||||
import codecs
|
||||
import warnings
|
||||
|
||||
class BaseLocalizedTest(unittest.TestCase):
|
||||
#
|
||||
|
@ -197,6 +198,10 @@ class EnUSNumberFormatting(BaseFormattingTest):
|
|||
self._test_format("%+10.f", -4200, grouping=0, out='-4200'.rjust(10))
|
||||
self._test_format("%-10.f", 4200, grouping=0, out='4200'.ljust(10))
|
||||
|
||||
def test_format_deprecation(self):
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
locale.format("%-10.f", 4200, grouping=True)
|
||||
|
||||
def test_complex_formatting(self):
|
||||
# Spaces in formatting string
|
||||
self._test_format_string("One million is %i", 1000000, grouping=1,
|
||||
|
|
|
@ -381,8 +381,8 @@ class TypesTests(unittest.TestCase):
|
|||
|
||||
for i in range(-10, 10):
|
||||
x = 1234567890.0 * (10.0 ** i)
|
||||
self.assertEqual(locale.format('%g', x, grouping=True), format(x, 'n'))
|
||||
self.assertEqual(locale.format('%.10g', x, grouping=True), format(x, '.10n'))
|
||||
self.assertEqual(locale.format_string('%g', x, grouping=True), format(x, 'n'))
|
||||
self.assertEqual(locale.format_string('%.10g', x, grouping=True), format(x, '.10n'))
|
||||
|
||||
@run_with_locale('LC_NUMERIC', 'en_US.UTF8')
|
||||
def test_int__format__locale(self):
|
||||
|
@ -390,7 +390,7 @@ class TypesTests(unittest.TestCase):
|
|||
|
||||
x = 123456789012345678901234567890
|
||||
for i in range(0, 30):
|
||||
self.assertEqual(locale.format('%d', x, grouping=True), format(x, 'n'))
|
||||
self.assertEqual(locale.format_string('%d', x, grouping=True), format(x, 'n'))
|
||||
|
||||
# move to the next integer to test
|
||||
x = x // 10
|
||||
|
|
|
@ -397,6 +397,9 @@ Library
|
|||
- bpo-29534: Fixed different behaviour of Decimal.from_float()
|
||||
for _decimal and _pydecimal. Thanks Andrew Nester.
|
||||
|
||||
- bpo-10379: locale.format_string now supports the 'monetary' keyword argument,
|
||||
and locale.format is deprecated.
|
||||
|
||||
- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
|
||||
improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
|
||||
Manuel Krebber, and Łukasz Langa.
|
||||
|
|
Loading…
Reference in New Issue