Skip to content

Commit 4a50dcd

Browse files
Merge branch 'main' into capi-PySys_GetAttr3
2 parents ff9c317 + c5f925c commit 4a50dcd

27 files changed

+589
-300
lines changed

Doc/glossary.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ Glossary
719719
iterables include all sequence types (such as :class:`list`, :class:`str`,
720720
and :class:`tuple`) and some non-sequence types like :class:`dict`,
721721
:term:`file objects <file object>`, and objects of any classes you define
722-
with an :meth:`~iterator.__iter__` method or with a
722+
with an :meth:`~object.__iter__` method or with a
723723
:meth:`~object.__getitem__` method
724724
that implements :term:`sequence` semantics.
725725

Doc/library/abc.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,18 +141,18 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance:
141141
MyIterable.register(Foo)
142142

143143
The ABC ``MyIterable`` defines the standard iterable method,
144-
:meth:`~iterator.__iter__`, as an abstract method. The implementation given
144+
:meth:`~object.__iter__`, as an abstract method. The implementation given
145145
here can still be called from subclasses. The :meth:`!get_iterator` method
146146
is also part of the ``MyIterable`` abstract base class, but it does not have
147147
to be overridden in non-abstract derived classes.
148148

149149
The :meth:`__subclasshook__` class method defined here says that any class
150-
that has an :meth:`~iterator.__iter__` method in its
150+
that has an :meth:`~object.__iter__` method in its
151151
:attr:`~object.__dict__` (or in that of one of its base classes, accessed
152152
via the :attr:`~type.__mro__` list) is considered a ``MyIterable`` too.
153153

154154
Finally, the last line makes ``Foo`` a virtual subclass of ``MyIterable``,
155-
even though it does not define an :meth:`~iterator.__iter__` method (it uses
155+
even though it does not define an :meth:`~object.__iter__` method (it uses
156156
the old-style iterable protocol, defined in terms of :meth:`~object.__len__` and
157157
:meth:`~object.__getitem__`). Note that this will not make ``get_iterator``
158158
available as a method of ``Foo``, so it is provided separately.

Doc/library/stdtypes.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -949,9 +949,9 @@ Generator Types
949949
---------------
950950

951951
Python's :term:`generator`\s provide a convenient way to implement the iterator
952-
protocol. If a container object's :meth:`~iterator.__iter__` method is implemented as a
952+
protocol. If a container object's :meth:`~object.__iter__` method is implemented as a
953953
generator, it will automatically return an iterator object (technically, a
954-
generator object) supplying the :meth:`!__iter__` and :meth:`~generator.__next__`
954+
generator object) supplying the :meth:`~iterator.__iter__` and :meth:`~generator.__next__`
955955
methods.
956956
More information about generators can be found in :ref:`the documentation for
957957
the yield expression <yieldexpr>`.

Doc/library/string.rst

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,14 +319,19 @@ non-empty format specification typically modifies the result.
319319
The general form of a *standard format specifier* is:
320320

321321
.. productionlist:: format-spec
322-
format_spec: [[`fill`]`align`][`sign`]["z"]["#"]["0"][`width`][`grouping_option`]["." `precision`][`type`]
322+
format_spec: [`options`][`width_and_precision`][`type`]
323+
options: [[`fill`]`align`][`sign`]["z"]["#"]["0"]
323324
fill: <any character>
324325
align: "<" | ">" | "=" | "^"
325326
sign: "+" | "-" | " "
327+
width_and_precision: [`width_with_grouping`][`precision_with_grouping`]
328+
width_with_grouping: [`width`][`grouping_option`]
329+
precision_with_grouping: "." [`precision`]`grouping_option`
326330
width: `~python-grammar:digit`+
327331
grouping_option: "_" | ","
328332
precision: `~python-grammar:digit`+
329-
type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
333+
type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g"
334+
: | "G" | "n" | "o" | "s" | "x" | "X" | "%"
330335

331336
If a valid *align* value is specified, it can be preceded by a *fill*
332337
character that can be any character and defaults to a space if omitted.
@@ -458,6 +463,13 @@ indicates the maximum field size - in other words, how many characters will be
458463
used from the field content. The *precision* is not allowed for integer
459464
presentation types.
460465

466+
The ``'_'`` or ``','`` option after *precision* means the use of an underscore
467+
or a comma for a thousands separator of the fractional part for floating-point
468+
presentation types.
469+
470+
.. versionchanged:: 3.14
471+
Support thousands separators for the fractional part.
472+
461473
Finally, the *type* determines how the data should be presented.
462474

463475
The available string presentation types are:
@@ -704,10 +716,18 @@ Replacing ``%x`` and ``%o`` and converting the value to different bases::
704716
>>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)
705717
'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
706718

707-
Using the comma as a thousands separator::
719+
Using the comma or the underscore as a thousands separator::
708720

709721
>>> '{:,}'.format(1234567890)
710722
'1,234,567,890'
723+
>>> '{:_}'.format(1234567890)
724+
'1_234_567_890'
725+
>>> '{:_}'.format(123456789.123456789)
726+
'123_456_789.12345679'
727+
>>> '{:._}'.format(123456789.123456789)
728+
'123456789.123_456_79'
729+
>>> '{:_._}'.format(123456789.123456789)
730+
'123_456_789.123_456_79'
711731

712732
Expressing a percentage::
713733

Doc/library/uuid.rst

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,6 @@ The :mod:`uuid` module defines the following functions:
184184
administered MAC addresses, since the former are guaranteed to be
185185
globally unique, while the latter are not.
186186

187-
.. index:: single: getnode
188-
189187

190188
.. function:: uuid1(node=None, clock_seq=None)
191189

@@ -194,33 +192,25 @@ The :mod:`uuid` module defines the following functions:
194192
*clock_seq* is given, it is used as the sequence number; otherwise a random
195193
14-bit sequence number is chosen.
196194

197-
.. index:: single: uuid1
198-
199195

200196
.. function:: uuid3(namespace, name)
201197

202198
Generate a UUID based on the MD5 hash of a namespace identifier (which is a
203199
UUID) and a name (which is a :class:`bytes` object or a string
204200
that will be encoded using UTF-8).
205201

206-
.. index:: single: uuid3
207-
208202

209203
.. function:: uuid4()
210204

211205
Generate a random UUID.
212206

213-
.. index:: single: uuid4
214-
215207

216208
.. function:: uuid5(namespace, name)
217209

218210
Generate a UUID based on the SHA-1 hash of a namespace identifier (which is a
219211
UUID) and a name (which is a :class:`bytes` object or a string
220212
that will be encoded using UTF-8).
221213

222-
.. index:: single: uuid5
223-
224214

225215
.. function:: uuid8(a=None, b=None, c=None)
226216

@@ -235,8 +225,6 @@ The :mod:`uuid` module defines the following functions:
235225

236226
.. versionadded:: 3.14
237227

238-
.. index:: single: uuid8
239-
240228

241229
The :mod:`uuid` module defines the following namespace identifiers for use with
242230
:func:`uuid3` or :func:`uuid5`.

Doc/whatsnew/3.14.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ Other language changes
336336
making it a :term:`generic type`.
337337
(Contributed by Brian Schubert in :gh:`126012`.)
338338

339+
* Support underscore and comma as thousands separators in the fractional part
340+
for floating-point presentation types of the new-style string formatting
341+
(with :func:`format` or :ref:`f-strings`).
342+
(Contrubuted by Sergey B Kirpichev in :gh:`87790`.)
343+
339344
* ``\B`` in :mod:`regular expression <re>` now matches empty input string.
340345
Now it is always the opposite of ``\b``.
341346
(Contributed by Serhiy Storchaka in :gh:`124130`.)

Include/internal/pycore_unicodeobject.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ extern Py_ssize_t _PyUnicode_InsertThousandsGrouping(
246246
Py_ssize_t min_width,
247247
const char *grouping,
248248
PyObject *thousands_sep,
249-
Py_UCS4 *maxchar);
249+
Py_UCS4 *maxchar,
250+
int forward);
250251

251252
/* --- Misc functions ----------------------------------------------------- */
252253

Lib/test/libregrtest/tsan.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
'test_capi.test_mem',
77
'test_capi.test_pyatomic',
88
'test_code',
9+
'test_concurrent_futures',
910
'test_enum',
1011
'test_functools',
1112
'test_httpservers',

Lib/test/test_concurrent_futures/util.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class ThreadPoolMixin(ExecutorMixin):
7474
executor_type = futures.ThreadPoolExecutor
7575

7676

77+
@support.skip_if_sanitizer("gh-129824: data races in InterpreterPool tests", thread=True)
7778
class InterpreterPoolMixin(ExecutorMixin):
7879
executor_type = futures.InterpreterPoolExecutor
7980

Lib/test/test_float.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,28 @@ def test_format(self):
754754
self.assertEqual(format(INF, 'f'), 'inf')
755755
self.assertEqual(format(INF, 'F'), 'INF')
756756

757+
# thousands separators
758+
x = 123_456.123_456
759+
self.assertEqual(format(x, '_f'), '123_456.123456')
760+
self.assertEqual(format(x, ',f'), '123,456.123456')
761+
self.assertEqual(format(x, '._f'), '123456.123_456')
762+
self.assertEqual(format(x, '.,f'), '123456.123,456')
763+
self.assertEqual(format(x, '_._f'), '123_456.123_456')
764+
self.assertEqual(format(x, ',.,f'), '123,456.123,456')
765+
self.assertEqual(format(x, '.10_f'), '123456.123_456_000_0')
766+
self.assertEqual(format(x, '.10,f'), '123456.123,456,000,0')
767+
self.assertEqual(format(x, '>21._f'), ' 123456.123_456')
768+
self.assertEqual(format(x, '<21._f'), '123456.123_456 ')
769+
self.assertEqual(format(x, '+.11_e'), '+1.234_561_234_56e+05')
770+
self.assertEqual(format(x, '+.11,e'), '+1.234,561,234,56e+05')
771+
772+
self.assertRaises(ValueError, format, x, '._6f')
773+
self.assertRaises(ValueError, format, x, '.,_f')
774+
self.assertRaises(ValueError, format, x, '.6,_f')
775+
self.assertRaises(ValueError, format, x, '.6_,f')
776+
self.assertRaises(ValueError, format, x, '.6_n')
777+
self.assertRaises(ValueError, format, x, '.6,n')
778+
757779
@support.requires_IEEE_754
758780
def test_format_testfile(self):
759781
with open(format_testfile, encoding="utf-8") as testfile:

Lib/test/test_format.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,15 @@ def test_with_a_commas_and_an_underscore_in_format_specifier(self):
515515
error_msg = re.escape("Cannot specify both ',' and '_'.")
516516
with self.assertRaisesRegex(ValueError, error_msg):
517517
'{:,_}'.format(1)
518+
with self.assertRaisesRegex(ValueError, error_msg):
519+
'{:.,_f}'.format(1.1)
518520

519521
def test_with_an_underscore_and_a_comma_in_format_specifier(self):
520522
error_msg = re.escape("Cannot specify both ',' and '_'.")
521523
with self.assertRaisesRegex(ValueError, error_msg):
522524
'{:_,}'.format(1)
525+
with self.assertRaisesRegex(ValueError, error_msg):
526+
'{:._,f}'.format(1.1)
523527

524528
def test_better_error_message_format(self):
525529
# https://bugs.python.org/issue20524

Lib/test/test_sys_setprofile.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,24 @@ class A:
493493
# The last c_call is the call to sys.setprofile
494494
self.assertEqual(events, ['c_call', 'c_return', 'c_call'])
495495

496+
class B:
497+
f = classmethod(max)
498+
events = []
499+
sys.setprofile(lambda frame, event, args: events.append(event))
500+
# Not important, we only want to trigger INSTRUMENTED_CALL_KW
501+
B().f(1, key=lambda x: 0)
502+
sys.setprofile(None)
503+
# The last c_call is the call to sys.setprofile
504+
self.assertEqual(
505+
events,
506+
['c_call',
507+
'call', 'return',
508+
'call', 'return',
509+
'c_return',
510+
'c_call'
511+
]
512+
)
513+
496514

497515
if __name__ == "__main__":
498516
unittest.main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Support underscore and comma as thousands separators in the fractional part for
2+
floating-point presentation types of the new-style string formatting (with
3+
:func:`format` or :ref:`f-strings`). Patch by Sergey B Kirpichev.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``INSTRUMENTED_CALL_KW`` will expand the method before monitoring to reflect the actual behavior more accurately.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Remove ``.. index::`` directives from the :mod:`uuid` module documentation. These directives
2+
previously created entries in the general index for :func:`~uuid.getnode` as well as the
3+
:func:`~uuid.uuid1`, :func:`~uuid.uuid3`, :func:`~uuid.uuid4`, :func:`~uuid.uuid5`, and
4+
:func:`~uuid.uuid8` constructor functions.

Modules/unicodedata.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,11 @@ typedef struct previous_version {
7777
Py_UCS4 (*normalization)(Py_UCS4);
7878
} PreviousDBVersion;
7979

80+
#define PreviousDBVersion_CAST(op) ((PreviousDBVersion *)(op))
81+
8082
#include "clinic/unicodedata.c.h"
8183

82-
#define get_old_record(self, v) ((((PreviousDBVersion*)self)->getrecord)(v))
84+
#define get_old_record(self, v) (PreviousDBVersion_CAST(self)->getrecord(v))
8385

8486
static PyMemberDef DB_members[] = {
8587
{"unidata_version", Py_T_STRING, offsetof(PreviousDBVersion, name), Py_READONLY},
@@ -1591,14 +1593,14 @@ static PyMethodDef unicodedata_functions[] = {
15911593
};
15921594

15931595
static int
1594-
ucd_traverse(PreviousDBVersion *self, visitproc visit, void *arg)
1596+
ucd_traverse(PyObject *self, visitproc visit, void *arg)
15951597
{
15961598
Py_VISIT(Py_TYPE(self));
15971599
return 0;
15981600
}
15991601

16001602
static void
1601-
ucd_dealloc(PreviousDBVersion *self)
1603+
ucd_dealloc(PyObject *self)
16021604
{
16031605
PyTypeObject *tp = Py_TYPE(self);
16041606
PyObject_GC_UnTrack(self);

0 commit comments

Comments
 (0)