Skip to content

Commit 387232d

Browse files
committed
Merge branch 'main' into fix-issue-129069
2 parents 39bee16 + 78acd8e commit 387232d

32 files changed

+494
-183
lines changed

.pre-commit-config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ repos:
1414
name: Run Ruff (lint) on Tools/build/
1515
args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml]
1616
files: ^Tools/build/
17+
- id: ruff
18+
name: Run Ruff (lint) on Tools/i18n/
19+
args: [--exit-non-zero-on-fix, --config=Tools/i18n/.ruff.toml]
20+
files: ^Tools/i18n/
1721
- id: ruff
1822
name: Run Ruff (lint) on Argument Clinic
1923
args: [--exit-non-zero-on-fix, --config=Tools/clinic/.ruff.toml]

Doc/deprecations/pending-removal-in-3.15.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,6 @@ Pending removal in Python 3.15
107107

108108
* :mod:`zipimport`:
109109

110-
* :meth:`~zipimport.zipimporter.load_module` has been deprecated since
110+
* :meth:`!zipimport.zipimporter.load_module` has been deprecated since
111111
Python 3.10. Use :meth:`~zipimport.zipimporter.exec_module` instead.
112-
(Contributed by Jiahao Li in :gh:`125746`.)
112+
(:gh:`125746`.)

Doc/howto/descriptor.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ Here are three practical data validation utilities:
420420

421421
def validate(self, value):
422422
if not isinstance(value, str):
423-
raise TypeError(f'Expected {value!r} to be an str')
423+
raise TypeError(f'Expected {value!r} to be a str')
424424
if self.minsize is not None and len(value) < self.minsize:
425425
raise ValueError(
426426
f'Expected {value!r} to be no smaller than {self.minsize!r}'

Doc/library/ssl.rst

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,19 +1684,33 @@ to speed up repeated connections from the same clients.
16841684

16851685
.. method:: SSLContext.set_ciphers(ciphers)
16861686

1687-
Set the available ciphers for sockets created with this context.
1688-
It should be a string in the `OpenSSL cipher list format
1687+
Set the allowed ciphers for sockets created with this context when
1688+
connecting using TLS 1.2 and earlier. The *ciphers* argument should
1689+
be a string in the `OpenSSL cipher list format
16891690
<https://docs.openssl.org/master/man1/ciphers/>`_.
1691+
To set allowed TLS 1.3 ciphers, use :meth:`SSLContext.set_ciphersuites`.
1692+
16901693
If no cipher can be selected (because compile-time options or other
16911694
configuration forbids use of all the specified ciphers), an
16921695
:class:`SSLError` will be raised.
16931696

16941697
.. note::
1695-
when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will
1696-
give the currently selected cipher.
1698+
When connected, the :meth:`SSLSocket.cipher` method of SSL sockets will
1699+
return details about the negotiated cipher.
1700+
1701+
.. method:: SSLContext.set_ciphersuites(ciphersuites)
1702+
1703+
Set the allowed ciphers for sockets created with this context when
1704+
connecting using TLS 1.3. The *ciphersuites* argument should be a
1705+
colon-separate string of TLS 1.3 cipher names. If no cipher can be
1706+
selected (because compile-time options or other configuration forbids
1707+
use of all the specified ciphers), an :class:`SSLError` will be raised.
1708+
1709+
.. note::
1710+
When connected, the :meth:`SSLSocket.cipher` method of SSL sockets will
1711+
return details about the negotiated cipher.
16971712

1698-
TLS 1.3 cipher suites cannot be disabled with
1699-
:meth:`~SSLContext.set_ciphers`.
1713+
.. versionadded:: next
17001714

17011715
.. method:: SSLContext.set_groups(groups)
17021716

@@ -2845,10 +2859,15 @@ TLS 1.3
28452859
The TLS 1.3 protocol behaves slightly differently than previous version
28462860
of TLS/SSL. Some new TLS 1.3 features are not yet available.
28472861

2848-
- TLS 1.3 uses a disjunct set of cipher suites. All AES-GCM and
2849-
ChaCha20 cipher suites are enabled by default. The method
2850-
:meth:`SSLContext.set_ciphers` cannot enable or disable any TLS 1.3
2851-
ciphers yet, but :meth:`SSLContext.get_ciphers` returns them.
2862+
- TLS 1.3 uses a disjunct set of cipher suites. All AES-GCM and ChaCha20
2863+
cipher suites are enabled by default. To restrict which TLS 1.3 ciphers
2864+
are allowed, the :meth:`SSLContext.set_ciphersuites` method should be
2865+
called instead of :meth:`SSLContext.set_ciphers`, which only affects
2866+
ciphers in older TLS versions. The :meth:`SSLContext.get_ciphers` method
2867+
returns information about ciphers for both TLS 1.3 and earlier versions
2868+
and the method :meth:`SSLSocket.cipher` returns information about the
2869+
negotiated cipher for both TLS 1.3 and earlier versions once a connection
2870+
is established.
28522871
- Session tickets are no longer sent as part of the initial handshake and
28532872
are handled differently. :attr:`SSLSocket.session` and :class:`SSLSession`
28542873
are not compatible with TLS 1.3.

Doc/library/zipimport.rst

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,6 @@ zipimporter Objects
142142
:exc:`ZipImportError` if the module couldn't be found.
143143

144144

145-
.. method:: load_module(fullname)
146-
147-
Load the module specified by *fullname*. *fullname* must be the fully
148-
qualified (dotted) module name. Returns the imported module on success,
149-
raises :exc:`ZipImportError` on failure.
150-
151-
.. deprecated-removed:: 3.10 3.15
152-
153-
Use :meth:`exec_module` instead.
154-
155-
156145
.. method:: invalidate_caches()
157146

158147
Clear out the internal cache of information about files found within
@@ -188,17 +177,20 @@ Here is an example that imports a module from a ZIP archive - note that the
188177

189178
.. code-block:: shell-session
190179
191-
$ unzip -l example.zip
192-
Archive: example.zip
180+
$ unzip -l example_archive.zip
181+
Archive: example_archive.zip
193182
Length Date Time Name
194183
-------- ---- ---- ----
195-
8467 11-26-02 22:30 jwzthreading.py
184+
8467 01-01-00 12:30 example.py
196185
-------- -------
197186
8467 1 file
198-
$ ./python
199-
Python 2.3 (#1, Aug 1 2003, 19:54:32)
187+
188+
.. code-block:: pycon
189+
200190
>>> import sys
201-
>>> sys.path.insert(0, 'example.zip') # Add .zip file to front of path
202-
>>> import jwzthreading
203-
>>> jwzthreading.__file__
204-
'example.zip/jwzthreading.py'
191+
>>> # Add the archive to the front of the module search path
192+
>>> sys.path.insert(0, 'example_archive.zip')
193+
>>> import example
194+
>>> example.__file__
195+
'example_archive.zip/example.py'
196+

Doc/whatsnew/3.15.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,13 @@ ssl
426426

427427
(Contributed by Ron Frederick in :gh:`136306`)
428428

429+
* Added a new method :meth:`ssl.SSLContext.set_ciphersuites` for setting TLS 1.3
430+
ciphers. For TLS 1.2 or earlier, :meth:`ssl.SSLContext.set_ciphers` should
431+
continue to be used. Both calls can be made on the same context and the
432+
selected cipher suite will depend on the TLS version negotiated when a
433+
connection is made.
434+
(Contributed by Ron Frederick in :gh:`137197`.)
435+
429436

430437
tarfile
431438
-------
@@ -611,6 +618,14 @@ wave
611618
(Contributed by Bénédikt Tran in :gh:`133873`.)
612619

613620

621+
zipimport
622+
---------
623+
624+
* Remove deprecated :meth:`!zipimport.zipimporter.load_module`.
625+
Use :meth:`zipimport.zipimporter.exec_module` instead.
626+
(Contributed by Jiahao Li in :gh:`133656`.)
627+
628+
614629
Porting to Python 3.15
615630
======================
616631

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from threading import Barrier, Thread
2+
from test.test_json import CTest
3+
from test.support import threading_helper
4+
5+
6+
def encode_json_helper(
7+
json, worker, data, number_of_threads=12, number_of_json_encodings=100
8+
):
9+
worker_threads = []
10+
barrier = Barrier(number_of_threads)
11+
for index in range(number_of_threads):
12+
worker_threads.append(
13+
Thread(target=worker, args=[barrier, data, index])
14+
)
15+
for t in worker_threads:
16+
t.start()
17+
for ii in range(number_of_json_encodings):
18+
json.dumps(data)
19+
data.clear()
20+
for t in worker_threads:
21+
t.join()
22+
23+
24+
class MyMapping(dict):
25+
def __init__(self):
26+
self.mapping = []
27+
28+
def items(self):
29+
return self.mapping
30+
31+
32+
@threading_helper.reap_threads
33+
@threading_helper.requires_working_threading()
34+
class TestJsonEncoding(CTest):
35+
# Test encoding json with concurrent threads modifying the data cannot
36+
# corrupt the interpreter
37+
38+
def test_json_mutating_list(self):
39+
def worker(barrier, data, index):
40+
barrier.wait()
41+
while data:
42+
for d in data:
43+
if len(d) > 5:
44+
d.clear()
45+
else:
46+
d.append(index)
47+
48+
data = [[], []]
49+
encode_json_helper(self.json, worker, data)
50+
51+
def test_json_mutating_exact_dict(self):
52+
def worker(barrier, data, index):
53+
barrier.wait()
54+
while data:
55+
for d in data:
56+
if len(d) > 5:
57+
try:
58+
key = list(d)[0]
59+
d.pop()
60+
except (KeyError, IndexError):
61+
pass
62+
else:
63+
d[index] = index
64+
65+
data = [{}, {}]
66+
encode_json_helper(self.json, worker, data)
67+
68+
def test_json_mutating_mapping(self):
69+
def worker(barrier, data, index):
70+
barrier.wait()
71+
while data:
72+
for d in data:
73+
if len(d.mapping) > 3:
74+
d.mapping.clear()
75+
else:
76+
d.mapping.append((index, index))
77+
78+
data = [MyMapping(), MyMapping()]
79+
encode_json_helper(self.json, worker, data)

Lib/test/test_io/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import os
2+
from test.support import load_package_tests
3+
4+
def load_tests(*args):
5+
return load_package_tests(os.path.dirname(__file__), *args)

Lib/test/test_io/__main__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from . import load_tests
2+
import unittest
3+
4+
unittest.main()

Lib/test/test_io.py renamed to Lib/test/test_io/test_general.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# * test_memoryio - tests BytesIO and StringIO
66
# * test_fileio - tests FileIO
77
# * test_file - tests the file interface
8-
# * test_io - tests everything else in the io module
8+
# * test_io.test_general - tests everything else in the io module
99
# * test_univnewlines - tests universal newline support
1010
# * test_largefile - tests operations on a file greater than 2**32 bytes
1111
# (only enabled with -ulargefile)

0 commit comments

Comments
 (0)