Skip to content

Commit 636bbf7

Browse files
Merge branch 'main' into chore/cleanup-win95-locale
2 parents 583c63a + 6ea84b2 commit 636bbf7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+774
-334
lines changed

Doc/.ruff.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ ignore = [
3232
"E501", # Ignore line length errors (we use auto-formatting)
3333
]
3434

35+
[lint.per-file-ignores]
36+
"tools/check-html-ids.py" = ["I001"] # Unsorted imports
37+
3538
[format]
3639
preview = true
3740
quote-style = "preserve"

Doc/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,3 +336,9 @@ autobuild-stable-html:
336336
exit 1;; \
337337
esac
338338
@$(MAKE) autobuild-dev-html
339+
340+
# Collect HTML IDs to a JSON document
341+
.PHONY: html-ids
342+
html-ids:
343+
$(PYTHON) tools/check-html-ids.py collect build/html \
344+
-o build/html/html-ids.json.gz

Doc/c-api/dict.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ Dictionary objects
8282
8383
Return a new dictionary that contains the same key-value pairs as *p*.
8484
85+
.. versionchanged:: next
86+
If *p* is a subclass of :class:`frozendict`, the result will be a
87+
:class:`frozendict` instance instead of a :class:`dict` instance.
8588
8689
.. c:function:: int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val)
8790

Doc/library/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ the `Python Package Index <https://pypi.org>`_.
4343
constants.rst
4444
stdtypes.rst
4545
exceptions.rst
46+
threadsafety.rst
4647

4748
text.rst
4849
binary.rst

Doc/library/shutil.rst

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -618,22 +618,23 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules.
618618

619619
Create an archive file (such as zip or tar) and return its name.
620620

621-
*base_name* is the name of the file to create, including the path, minus
622-
any format-specific extension.
621+
*base_name* is a string or :term:`path-like object` specifying the name of
622+
the file to create, including the path, minus any format-specific extension.
623623

624624
*format* is the archive format: one of
625625
"zip" (if the :mod:`zlib` module is available), "tar", "gztar" (if the
626626
:mod:`zlib` module is available), "bztar" (if the :mod:`bz2` module is
627627
available), "xztar" (if the :mod:`lzma` module is available), or "zstdtar"
628628
(if the :mod:`compression.zstd` module is available).
629629

630-
*root_dir* is a directory that will be the root directory of the
631-
archive, all paths in the archive will be relative to it; for example,
632-
we typically chdir into *root_dir* before creating the archive.
630+
*root_dir* is a string or :term:`path-like object` specifying a directory
631+
that will be the root directory of the archive, all paths in the archive
632+
will be relative to it; for example, we typically chdir into *root_dir*
633+
before creating the archive.
633634

634-
*base_dir* is the directory where we start archiving from;
635-
i.e. *base_dir* will be the common prefix of all files and
636-
directories in the archive. *base_dir* must be given relative
635+
*base_dir* is a string or :term:`path-like object` specifying a directory
636+
where we start archiving from; i.e. *base_dir* will be the common prefix of
637+
all files and directories in the archive. *base_dir* must be given relative
637638
to *root_dir*. See :ref:`shutil-archiving-example-with-basedir` for how to
638639
use *base_dir* and *root_dir* together.
639640

@@ -668,6 +669,10 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules.
668669
This function is now made thread-safe during creation of standard
669670
``.zip`` and tar archives.
670671

672+
.. versionchanged:: next
673+
Accepts a :term:`path-like object` for *base_name*, *root_dir* and
674+
*base_dir*.
675+
671676
.. function:: get_archive_formats()
672677

673678
Return a list of supported formats for archiving.

Doc/library/stdtypes.rst

Lines changed: 24 additions & 242 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,111 +1449,10 @@ application).
14491449
list appear empty for the duration, and raises :exc:`ValueError` if it can
14501450
detect that the list has been mutated during a sort.
14511451

1452-
.. _thread-safety-list:
1453-
1454-
.. rubric:: Thread safety for list objects
1455-
1456-
Reading a single element from a :class:`list` is
1457-
:term:`atomic <atomic operation>`:
1458-
1459-
.. code-block::
1460-
:class: green
1461-
1462-
lst[i] # list.__getitem__
1463-
1464-
The following methods traverse the list and use :term:`atomic <atomic operation>`
1465-
reads of each item to perform their function. That means that they may
1466-
return results affected by concurrent modifications:
1467-
1468-
.. code-block::
1469-
:class: maybe
1470-
1471-
item in lst
1472-
lst.index(item)
1473-
lst.count(item)
1474-
1475-
All of the above operations avoid acquiring :term:`per-object locks
1476-
<per-object lock>`. They do not block concurrent modifications. Other
1477-
operations that hold a lock will not block these from observing intermediate
1478-
states.
1479-
1480-
All other operations from here on block using the :term:`per-object lock`.
1481-
1482-
Writing a single item via ``lst[i] = x`` is safe to call from multiple
1483-
threads and will not corrupt the list.
1484-
1485-
The following operations return new objects and appear
1486-
:term:`atomic <atomic operation>` to other threads:
1487-
1488-
.. code-block::
1489-
:class: good
1490-
1491-
lst1 + lst2 # concatenates two lists into a new list
1492-
x * lst # repeats lst x times into a new list
1493-
lst.copy() # returns a shallow copy of the list
1494-
1495-
The following methods that only operate on a single element with no shifting
1496-
required are :term:`atomic <atomic operation>`:
1497-
1498-
.. code-block::
1499-
:class: good
1500-
1501-
lst.append(x) # append to the end of the list, no shifting required
1502-
lst.pop() # pop element from the end of the list, no shifting required
1503-
1504-
The :meth:`~list.clear` method is also :term:`atomic <atomic operation>`.
1505-
Other threads cannot observe elements being removed.
1506-
1507-
The :meth:`~list.sort` method is not :term:`atomic <atomic operation>`.
1508-
Other threads cannot observe intermediate states during sorting, but the
1509-
list appears empty for the duration of the sort.
1510-
1511-
The following operations may allow :term:`lock-free` operations to observe
1512-
intermediate states since they modify multiple elements in place:
1513-
1514-
.. code-block::
1515-
:class: maybe
1516-
1517-
lst.insert(idx, item) # shifts elements
1518-
lst.pop(idx) # idx not at the end of the list, shifts elements
1519-
lst *= x # copies elements in place
1520-
1521-
The :meth:`~list.remove` method may allow concurrent modifications since
1522-
element comparison may execute arbitrary Python code (via
1523-
:meth:`~object.__eq__`).
1524-
1525-
:meth:`~list.extend` is safe to call from multiple threads. However, its
1526-
guarantees depend on the iterable passed to it. If it is a :class:`list`, a
1527-
:class:`tuple`, a :class:`set`, a :class:`frozenset`, a :class:`dict` or a
1528-
:ref:`dictionary view object <dict-views>` (but not their subclasses), the
1529-
``extend`` operation is safe from concurrent modifications to the iterable.
1530-
Otherwise, an iterator is created which can be concurrently modified by
1531-
another thread. The same applies to inplace concatenation of a list with
1532-
other iterables when using ``lst += iterable``.
1533-
1534-
Similarly, assigning to a list slice with ``lst[i:j] = iterable`` is safe
1535-
to call from multiple threads, but ``iterable`` is only locked when it is
1536-
also a :class:`list` (but not its subclasses).
1537-
1538-
Operations that involve multiple accesses, as well as iteration, are never
1539-
atomic. For example:
1540-
1541-
.. code-block::
1542-
:class: bad
1543-
1544-
# NOT atomic: read-modify-write
1545-
lst[i] = lst[i] + 1
1546-
1547-
# NOT atomic: check-then-act
1548-
if lst:
1549-
item = lst.pop()
1550-
1551-
# NOT thread-safe: iteration while modifying
1552-
for item in lst:
1553-
process(item) # another thread may modify lst
1452+
.. seealso::
15541453

1555-
Consider external synchronization when sharing :class:`list` instances
1556-
across threads. See :ref:`freethreading-python-howto` for more information.
1454+
For detailed information on thread-safety guarantees for :class:`list`
1455+
objects, see :ref:`thread-safety-list`.
15571456

15581457

15591458
.. _typesseq-tuple:
@@ -2605,6 +2504,19 @@ expression support in the :mod:`re` module).
26052504
done using the specified *fillchar* (default is an ASCII space). The
26062505
original string is returned if *width* is less than or equal to ``len(s)``.
26072506

2507+
For example:
2508+
2509+
.. doctest::
2510+
2511+
>>> 'Python'.rjust(10)
2512+
' Python'
2513+
>>> 'Python'.rjust(10, '.')
2514+
'....Python'
2515+
>>> 'Monty Python'.rjust(10, '.')
2516+
'Monty Python'
2517+
2518+
See also :meth:`ljust` and :meth:`zfill`.
2519+
26082520

26092521
.. method:: str.rpartition(sep, /)
26102522

@@ -2929,13 +2841,17 @@ expression support in the :mod:`re` module).
29292841
than before. The original string is returned if *width* is less than
29302842
or equal to ``len(s)``.
29312843

2932-
For example::
2844+
For example:
2845+
2846+
.. doctest::
29332847

29342848
>>> "42".zfill(5)
29352849
'00042'
29362850
>>> "-42".zfill(5)
29372851
'-0042'
29382852

2853+
See also :meth:`rjust`.
2854+
29392855

29402856
.. index::
29412857
single: ! formatted string literal
@@ -5601,144 +5517,10 @@ can be used interchangeably to index the same dictionary entry.
56015517
:class:`frozendict` and :class:`types.MappingProxyType` can be used to
56025518
create a read-only view of a :class:`dict`.
56035519

5604-
.. _thread-safety-dict:
5605-
5606-
.. rubric:: Thread safety for dict objects
5607-
5608-
Creating a dictionary with the :class:`dict` constructor is atomic when the
5609-
argument to it is a :class:`dict` or a :class:`tuple`. When using the
5610-
:meth:`dict.fromkeys` method, dictionary creation is atomic when the
5611-
argument is a :class:`dict`, :class:`tuple`, :class:`set` or
5612-
:class:`frozenset`.
5613-
5614-
The following operations and functions are :term:`lock-free` and
5615-
:term:`atomic <atomic operation>`.
5616-
5617-
.. code-block::
5618-
:class: good
5619-
5620-
d[key] # dict.__getitem__
5621-
d.get(key) # dict.get
5622-
key in d # dict.__contains__
5623-
len(d) # dict.__len__
5624-
5625-
All other operations from here on hold the :term:`per-object lock`.
5626-
5627-
Writing or removing a single item is safe to call from multiple threads
5628-
and will not corrupt the dictionary:
5629-
5630-
.. code-block::
5631-
:class: good
5632-
5633-
d[key] = value # write
5634-
del d[key] # delete
5635-
d.pop(key) # remove and return
5636-
d.popitem() # remove and return last item
5637-
d.setdefault(key, v) # insert if missing
5638-
5639-
These operations may compare keys using :meth:`~object.__eq__`, which can
5640-
execute arbitrary Python code. During such comparisons, the dictionary may
5641-
be modified by another thread. For built-in types like :class:`str`,
5642-
:class:`int`, and :class:`float`, that implement :meth:`~object.__eq__` in C,
5643-
the underlying lock is not released during comparisons and this is not a
5644-
concern.
5645-
5646-
The following operations return new objects and hold the :term:`per-object lock`
5647-
for the duration of the operation:
5648-
5649-
.. code-block::
5650-
:class: good
5651-
5652-
d.copy() # returns a shallow copy of the dictionary
5653-
d | other # merges two dicts into a new dict
5654-
d.keys() # returns a new dict_keys view object
5655-
d.values() # returns a new dict_values view object
5656-
d.items() # returns a new dict_items view object
5657-
5658-
The :meth:`~dict.clear` method holds the lock for its duration. Other
5659-
threads cannot observe elements being removed.
5660-
5661-
The following operations lock both dictionaries. For :meth:`~dict.update`
5662-
and ``|=``, this applies only when the other operand is a :class:`dict`
5663-
that uses the standard dict iterator (but not subclasses that override
5664-
iteration). For equality comparison, this applies to :class:`dict` and
5665-
its subclasses:
5666-
5667-
.. code-block::
5668-
:class: good
5669-
5670-
d.update(other_dict) # both locked when other_dict is a dict
5671-
d |= other_dict # both locked when other_dict is a dict
5672-
d == other_dict # both locked for dict and subclasses
5673-
5674-
All comparison operations also compare values using :meth:`~object.__eq__`,
5675-
so for non-built-in types the lock may be released during comparison.
5676-
5677-
:meth:`~dict.fromkeys` locks both the new dictionary and the iterable
5678-
when the iterable is exactly a :class:`dict`, :class:`set`, or
5679-
:class:`frozenset` (not subclasses):
5680-
5681-
.. code-block::
5682-
:class: good
5683-
5684-
dict.fromkeys(a_dict) # locks both
5685-
dict.fromkeys(a_set) # locks both
5686-
dict.fromkeys(a_frozenset) # locks both
5687-
5688-
When updating from a non-dict iterable, only the target dictionary is
5689-
locked. The iterable may be concurrently modified by another thread:
5690-
5691-
.. code-block::
5692-
:class: maybe
5693-
5694-
d.update(iterable) # iterable is not a dict: only d locked
5695-
d |= iterable # iterable is not a dict: only d locked
5696-
dict.fromkeys(iterable) # iterable is not a dict/set/frozenset: only result locked
5697-
5698-
Operations that involve multiple accesses, as well as iteration, are never
5699-
atomic:
5700-
5701-
.. code-block::
5702-
:class: bad
5703-
5704-
# NOT atomic: read-modify-write
5705-
d[key] = d[key] + 1
5706-
5707-
# NOT atomic: check-then-act (TOCTOU)
5708-
if key in d:
5709-
del d[key]
5710-
5711-
# NOT thread-safe: iteration while modifying
5712-
for key, value in d.items():
5713-
process(key) # another thread may modify d
5714-
5715-
To avoid time-of-check to time-of-use (TOCTOU) issues, use atomic
5716-
operations or handle exceptions:
5717-
5718-
.. code-block::
5719-
:class: good
5720-
5721-
# Use pop() with default instead of check-then-delete
5722-
d.pop(key, None)
5723-
5724-
# Or handle the exception
5725-
try:
5726-
del d[key]
5727-
except KeyError:
5728-
pass
5729-
5730-
To safely iterate over a dictionary that may be modified by another
5731-
thread, iterate over a copy:
5732-
5733-
.. code-block::
5734-
:class: good
5735-
5736-
# Make a copy to iterate safely
5737-
for key, value in d.copy().items():
5738-
process(key)
5520+
.. seealso::
57395521

5740-
Consider external synchronization when sharing :class:`dict` instances
5741-
across threads. See :ref:`freethreading-python-howto` for more information.
5522+
For detailed information on thread-safety guarantees for :class:`dict`
5523+
objects, see :ref:`thread-safety-dict`.
57425524

57435525

57445526
.. _dict-views:

0 commit comments

Comments
 (0)