8000 bpo-10379: add 'monetary' to format_string, deprecate format · python/cpython@1cf93a7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1cf93a7

Browse files
Garvit Khatribitdancer
Garvit Khatri
authored andcommitted
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.
1 parent c8fa45b commit 1cf93a7

File tree

6 files changed

+82
-53
lines changed

6 files changed

+82
-53
lines changed

Doc/library/locale.rst

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ The :mod:`locale` module defines the following exception and functions:
352352
sequence of strings.
353353

354354

355-
.. function:: format(format, val, grouping=False, monetary=False)
355+
.. function:: format_string(format, val, grouping=False, monetary=False)
356356

357357
Formats a number *val* according to the current :const:`LC_NUMERIC` setting.
358358
The format follows the conventions of the ``%`` operator. For floating point
@@ -362,14 +362,22 @@ The :mod:`locale` module defines the following exception and functions:
362362
If *monetary* is true, the conversion uses monetary thousands separator and
363363
grouping strings.
364364

365-
Please note that this function will only work for exactly one %char specifier.
366-
For whole format strings, use :func:`format_string`.
365+
Processes formatting specifiers as in ``format % val``, but takes the current
366+
locale settings into account.
367367

368+
.. versionchanged:: 3.7
369+
The *monetary* keyword parameter was added.
368370

369-
.. function:: format_string(format, val, grouping=False)
370371

371-
Processes formatting specifiers as in ``format % val``, but takes the current
372-
locale settings into account.
372+
.. function:: format(format, val, grouping=False, monetary=False)
373+
374+
Please note that this function works like format_string but will only work
375+
for exactly one %char specifier.
376+
377+
For whole format strings, use :func:`format_string`.
378+
379+
.. deprecated:: 3.7
380+
Use :meth:`format_string` instead
373381

374382

375383
.. function:: currency(val, symbol=True, grouping=False, international=False)

Doc/whatsnew/3.7.rst

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,14 @@ Other Language Changes
7676
======================
7777

7878
* More than 255 arguments can now be passed to a function, and a function can
79-
now have more than 255 parameters.
80-
(Contributed by Serhiy Storchaka in :issue:`12844` and :issue:`18896`.)
79+
now have more than 255 parameters. (Contributed by Serhiy Storchaka in
80+
:issue:`12844` and :issue:`18896`.)
8181

8282
* :meth:`bytes.fromhex` and :meth:`bytearray.fromhex` now ignore all ASCII
83-
whitespace, not only spaces.
84-
(Contributed by Robert Xiao in :issue:`28927`.)
83+
whitespace, not only spaces. (Contributed by Robert Xiao in :issue:`28927`.)
8584

8685
* :exc:`ImportError` now displays module name and module ``__file__`` path when
87-
``from ... import ...`` fails.
88-
(Contributed by Matthias Bussonnier in :issue:`29546`.)
86+
``from ... import ...`` fails. (Contributed by Matthias Bussonnier in :issue:`29546`.)
8987

9088

9189
New Modules
@@ -97,25 +95,32 @@ New Modules
9795
Improved Modules
9896
================
9997

98+
locale
99+
------
100+
101+
Added another argument *monetary* in :meth:`format_string` of :mod:`locale`.
102+
If *monetary* is true, the conversion uses monetary thousands separator and
103+
grouping strings. (Contributed by Garvit in :issue:`10379`.)
104+
100105
os
101106
--
102107

103-
Added support for :class:`bytes` paths in :func:`~os.fwalk`.
104-
(Contributed by Serhiy Storchaka in :issue:`28682`.)
108+
Added support for :class:`bytes` paths in :func:`~os.fwalk`. (Contributed by
109+
Serhiy Storchaka in :issue:`28682`.)
105110

106111
unittest.mock
107112
-------------
108113

109114
The :const:`~unittest.mock.sentinel` attributes now preserve their identity
110-
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`.
111-
(Contributed by Serhiy Storchaka in :issue:`20804`.)
115+
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`. (Contributed by
116+
Serhiy Storchaka in :issue:`20804`.)
112117

113118
xmlrpc.server
114119
-------------
115120

116121
:meth:`register_function` of :class:`xmlrpc.server.SimpleXMLRPCDispatcher` and
117-
its subclasses can be used as a decorator.
118-
(Contributed by Xiang Zhang in :issue:`7769`.)
122+
its subclasses can be used as a decorator. (Contributed by Xiang Zhang in
123+
:issue:`7769`.)
119124

120125
urllib.parse
121126
------------
@@ -130,13 +135,13 @@ Optimizations
130135

131136
* Added two new opcodes: ``LOAD_METHOD`` and ``CALL_METHOD`` to avoid
132137
instantiation of bound method objects for method calls, which results
133-
in method calls being faster up to 20%.
134-
(Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.)
138+
in method calls being faster up to 20%. (Contributed by Yury Selivanov and
139+
INADA Naoki in :issue:`26110`.)
135140

136141
* Fast implementation from standard C library is now used for functions
137142
:func:`~math.tgamma`, :func:`~math.lgamma`, :func:`~math.erf` and
138-
:func:`~math.erfc` in the :mod:`math` module.
139-
(Contributed by Serhiy Storchaka in :issue:`26121`.)
143+
:func:`~math.erfc` in the :mod:`math` module. (Contributed by Serhiy
144+
Storchaka in :issue:`26121`.)
140145

141146

142147
Build and C API Changes
@@ -154,8 +159,8 @@ Build and C API Changes
154159
``char *``. (Contributed by Serhiy Storchaka in :issue:`28761`.)
155160

156161
* The result of :c:func:`PyUnicode_AsUTF8AndSize` and :c:func:`PyUnicode_AsUTF8`
157-
is now of type ``const char *`` rather of ``char *``.
158-
(Contributed by Serhiy Storchaka in :issue:`28769`.)
162+
is now of type ``const char *`` rather of ``char *``. (Contributed by Serhiy
163+
Storchaka in :issue:`28769`.)
159164

160165
* Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`.
161166
(Contributed by Serhiy Storchaka in :issue:`27867`.)
@@ -169,6 +174,9 @@ Deprecated
169174
``0x03050400`` and ``0x03060000`` (not including) or ``0x03060100`` or
170175
higher. (Contributed by Serhiy Storchaka in :issue:`27867`.)
171176

177+
- Deprecated :meth:`format` from :mod:`locale`, use the :meth:`format_string`
178+
instead. (Contributed by Garvit in :issue:`10379`.)
179+
172180
- Methods
173181
:meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>`
174182
(replaced by
@@ -181,8 +189,8 @@ Deprecated
181189
by Matthias Bussonnier in :issue:`29576`)
182190

183191
- Using non-integer value for selecting a plural form in :mod:`gettext` is
184-
now deprecated. It never correctly worked.
185-
(Contributed by Serhiy Storchaka in :issue:`28692`.)
192+
now deprecated. It never correctly worked. (Contributed by Serhiy Storchaka
193+
in :issue:`28692`.)
186194

187195

188196
Changes in the C API
@@ -229,8 +237,8 @@ Changes in the Python API
229237

230238
* A format string argument for :meth:`string.Formatter.format`
231239
is now :ref:`positional-only <positional-only_parameter>`.
232-
Passing it as a keyword argument was deprecated in Python 3.5.
233-
(Contributed by Serhiy Storchaka in :issue:`29193`.)
240+
Passing it as a keyword argument was deprecated in Python 3.5. (Contributed
241+
by Serhiy Storchaka in :issue:`29193`.)
234242

235243
* Attributes :attr:`~http.cookies.Morsel.key`,
236244
:attr:`~http.cookies.Morsel.value` and
@@ -244,8 +252,8 @@ Changes in the Python API
244252
``ClassDef`` AST nodes now have a new ``docstring`` field.
245253
The first statement in their body is not considered as a docstring
246254
anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class
247-
and module are affected by this change.
248-
(Contributed by INADA Naoki and Eugene Toder in :issue:`29463`.)
255+
and module are affected by this change. (Contributed by INADA Naoki and
256+
Eugene Toder in :issue:`29463`.)
249257

250258
* The *mode* argument of :func:`os.makedirs` no longer affects the file
251259
permission bits of newly-created intermediate-level directories.

Lib/locale.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import collections
1818
from builtins import str as _builtin_str
1919
import functools
20+
import warnings
2021

2122
# Try importing the _locale module.
2223
#
@@ -180,19 +181,6 @@ def _strip_padding(s, amount):
180181
_percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?'
181182
r'(?P<modifiers>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]')
182< 1241 /code>183

183-
def format(percent, value, grouping=False, monetary=False, *additional):
184-
&qu F438 ot;""Returns the locale-aware substitution of a %? specifier
185-
(percent).
186-
187-
additional is for format strings which contain one or more
188-
'*' modifiers."""
189-
# this is only for one-percent-specifier strings and this should be checked
190-
match = _percent_re.match(percent)
191-
if not match or len(match.group())!= len(percent):
192-
raise ValueError(("format() must be given exactly one %%char "
193-
"format specifier, %s not valid") % repr(percent))
194-
return _format(percent, value, grouping, monetary, *additional)
195-
196184
def _format(percent, value, grouping=False, monetary=False, *additional):
197185
if additional:
198186
formatted = percent % ((value,) + additional)
@@ -217,10 +205,13 @@ def _format(percent, value, grouping=False, monetary=False, *additional):
217205
formatted = _strip_padding(formatted, seps)
218206
return formatted
219207

220-
def format_string(f, val, grouping=False):
208+
def format_string(f, val, grouping=False, monetary=False):
221209
"""Formats a string in the same way that the % formatting would use,
222210
but takes the current locale into account.
223-
Grouping is applied if the third parameter is true."""
211+
212+
Grouping is applied if the third parameter is true.
213+
Conversion uses monetary thousands separator and grouping strings if
214+
forth parameter monetary is true."""
224215
percents = list(_percent_re.finditer(f))
225216
new_f = _percent_re.sub('%s', f)
226217

@@ -230,7 +221,7 @@ def format_string(f, val, grouping=False):
230221
if perc.group()[-1]=='%':
231222
new_val.append('%')
232223
else:
233-
new_val.append(format(perc.group(), val, grouping))
224+
new_val.append(_format(perc.group(), val, grouping, monetary))
234225
else:
235226
if not isinstance(val, tuple):
236227
val = (val,)
@@ -244,13 +235,27 @@ def format_string(f, val, grouping=False):
244235
new_val.append(_format(perc.group(),
245236
val[i],
246237
grouping,
247-
False,
238+
monetary,
248239
*val[i+1:i+1+starcount]))
249240
i += (1 + starcount)
250241
val = tuple(new_val)
251242

252243
return new_f % val
253244

245+
def format(percent, value, grouping=False, monetary=False, *additional):
246+
"""Deprecated, use format_string instead."""
247+
warnings.warn(
248+
"This method will be removed in a future version of Python."
249+
"Use 'locale.format_string()' instead.",
250+
DeprecationWarning, stacklevel=2
251+
)
252+
253+
match = _percent_re.match(percent)
254+
if not match or len(match.group())!= len(percent):
255+
raise ValueError(("format() must be given exactly one %%char "
256+
"format specifier, %s not valid") % repr(percent))
257+
return _format(percent, value, grouping, monetary, *additional)
258+
254259
def currency(val, symbol=True, grouping=False, international=False):
255260
"""Formats val according to the currency settings
256261
in the current locale."""
@@ -262,7 +267,7 @@ def currency(val, symbol=True, grouping=False, international=False):
262267
raise ValueError("Currency formatting is not possible using "
263268
"the 'C' locale.")
264269

265-
s = format('%%.%if' % digits, abs(val), grouping, monetary=True)
270+
s = _format('%%.%if' % digits, abs(val), grouping, monetary=True)
266271
# '<' and '>' are markers if the sign must be inserted between symbol and value
267272
s = '<' + s + '>'
268273

@@ -298,7 +303,7 @@ def currency(val, symbol=True, grouping=False, international=False):
298303

299304
def str(val):
300305
"""Convert float to string, taking the locale into account."""
301-
return format("%.12g", val)
306+
return _format("%.12g", val)
302307

303308
def delocalize(string):
304309
"Parses a string as a normalized number according to the locale settings."
@@ -327,7 +332,7 @@ def atoi(string):
327332
def _test():
328333
setlocale(LC_ALL, "")
329334
#do grouping
330-
s1 = format("%d", 123456789,1)
335+
s1 = format_string("%d", 123456789,1)
331336
print(s1, "is", atoi(s1))
332337
#standard formatting
333338
s1 = str(3.14)

Lib/test/test_locale.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import locale
44
import sys
55
import codecs
6+
import warnings
67

78
class BaseLocalizedTest(unittest.TestCase):
89
#
@@ -197,6 +198,10 @@ def test_padding(self):
197198
self._test_format("%+10.f", -4200, grouping=0, out='-4200'.rjust( 10000 10))
198199
self._test_format("%-10.f", 4200, grouping=0, out='4200'.ljust(10))
199200

201+
def test_format_deprecation(self):
202+
with self.assertWarns(DeprecationWarning):
203+
locale.format("%-10.f", 4200, grouping=True)
204+
200205
def test_complex_formatting(self):
201206
# Spaces in formatting string
202207
self._test_format_string("One million is %i", 1000000, grouping=1,

Lib/test/test_types.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,16 @@ def test_float__format__locale(self):
381381

382382
for i in range(-10, 10):
383383
x = 1234567890.0 * (10.0 ** i)
384-
self.assertEqual(locale.format('%g', x, grouping=True), format(x, 'n'))
385-
self.assertEqual(locale.format('%.10g', x, grouping=True), format(x, '.10n'))
384+
self.assertEqual(locale.format_string('%g', x, grouping=True), format(x, 'n'))
385+
self.assertEqual(locale.format_string('%.10g', x, grouping=True), format(x, '.10n'))
386386

387387
@run_with_locale('LC_NUMERIC', 'en_US.UTF8')
388388
def test_int__format__locale(self):
389389
# test locale support for __format__ code 'n' for integers
390390

391391
x = 123456789012345678901234567890
392392
for i in range(0, 30):
393-
self.assertEqual(locale.format('%d', x, grouping=True), format(x, 'n'))
393+
self.assertEqual(locale.format_string('%d', x, grouping=True), format(x, 'n'))
394394

395395
# move to the next integer to test
396396
x = x // 10

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ Library
397397
- bpo-29534: Fixed different behaviour of Decimal.from_float()
398398
for _decimal and _pydecimal. Thanks Andrew Nester.
399399

400+
- bpo-10379: locale.format_string now supports the 'monetary' keyword argument,
401+
and locale.format is deprecated.
402+
400403
- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
401404
improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
402405
Manuel Krebber, and Łukasz Langa.

0 commit comments

Comments
 (0)
0