Skip to content

Commit cd7dc2c

Browse files
authored
Merge branch 'main' into getpass-doc
2 parents fffc644 + 7d435cf commit cd7dc2c

File tree

16 files changed

+219
-23
lines changed

16 files changed

+219
-23
lines changed

Doc/c-api/init.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,12 @@ code, or when embedding the Python interpreter:
10201020
interpreter lock is also shared by all threads, regardless of to which
10211021
interpreter they belong.
10221022
1023+
.. versionchanged:: 3.12
1024+
1025+
:pep:`684` introduced the possibility
1026+
of a :ref:`per-interpreter GIL <per-interpreter-gil>`.
1027+
See :c:func:`Py_NewInterpreterFromConfig`.
1028+
10231029
10241030
.. c:type:: PyThreadState
10251031
@@ -1711,6 +1717,8 @@ function. You can create and destroy them using the following functions:
17111717
haven't been explicitly destroyed at that point.
17121718
17131719
1720+
.. _per-interpreter-gil:
1721+
17141722
A Per-Interpreter GIL
17151723
---------------------
17161724
@@ -1722,7 +1730,7 @@ being blocked by other interpreters or blocking any others. Thus a
17221730
single Python process can truly take advantage of multiple CPU cores
17231731
when running Python code. The isolation also encourages a different
17241732
approach to concurrency than that of just using threads.
1725-
(See :pep:`554`.)
1733+
(See :pep:`554` and :pep:`684`.)
17261734
17271735
Using an isolated interpreter requires vigilance in preserving that
17281736
isolation. That especially means not sharing any objects or mutable

Doc/library/platform.rst

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ Cross platform
187187
.. versionchanged:: 3.9
188188
:attr:`processor` is resolved late instead of immediately.
189189

190+
.. function:: invalidate_caches()
191+
192+
Clear out the internal cache of information, such as the :func:`uname`.
193+
This is typically useful when the platform's :func:`node` is changed
194+
by an external process and one needs to retrieve the updated value.
195+
196+
.. versionadded:: 3.14
197+
190198

191199
Windows platform
192200
----------------
@@ -370,14 +378,3 @@ The following options are accepted:
370378
You can also pass one or more positional arguments (``terse``, ``nonaliased``)
371379
to explicitly control the output format. These behave similarly to their
372380
corresponding options.
373-
374-
Miscellaneous
375-
-------------
376-
377-
.. function:: invalidate_caches()
378-
379-
Clear out the internal cache of information, such as the :func:`uname`.
380-
This is typically useful when the platform's :func:`node` is changed
381-
by an external process and one needs to retrieve the updated value.
382-
383-
.. versionadded:: 3.14

Doc/library/ssl.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,11 +1195,11 @@ SSL sockets also have the following additional methods and attributes:
11951195

11961196
Perform the SSL setup handshake.
11971197

1198-
If *block* is true and the timeout obtained by :meth:`~socket.gettimeout`
1198+
If *block* is true and the timeout obtained by :meth:`~socket.socket.gettimeout`
11991199
is zero, the socket is set in blocking mode until the handshake is performed.
12001200

12011201
.. versionchanged:: 3.4
1202-
The handshake method also performs :func:`match_hostname` when the
1202+
The handshake method also performs :func:`!match_hostname` when the
12031203
:attr:`~SSLContext.check_hostname` attribute of the socket's
12041204
:attr:`~SSLSocket.context` is true.
12051205

@@ -1209,7 +1209,7 @@ SSL sockets also have the following additional methods and attributes:
12091209

12101210
.. versionchanged:: 3.7
12111211
Hostname or IP address is matched by OpenSSL during handshake. The
1212-
function :func:`match_hostname` is no longer used. In case OpenSSL
1212+
function :func:`!match_hostname` is no longer used. In case OpenSSL
12131213
refuses a hostname or IP address, the handshake is aborted early and
12141214
a TLS alert message is sent to the peer.
12151215

@@ -2863,7 +2863,7 @@ This common check is automatically performed when
28632863

28642864
.. versionchanged:: 3.7
28652865
Hostname matchings is now performed by OpenSSL. Python no longer uses
2866-
:func:`match_hostname`.
2866+
:func:`!match_hostname`.
28672867

28682868
In server mode, if you want to authenticate your clients using the SSL layer
28692869
(rather than using a higher-level authentication mechanism), you'll also have

Doc/library/sys.rst

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,51 @@ interpreter and to functions that interact strongly with the interpreter. It is
1111
always available. Unless explicitly noted otherwise, all variables are read-only.
1212

1313

14+
.. data:: abi_info
15+
16+
.. versionadded:: next
17+
18+
An object containing information about the ABI of the currently running
19+
Python interpreter.
20+
It should include information that affect the CPython ABI in ways that
21+
require a specific build of the interpreter chosen from variants that can
22+
co-exist on a single machine.
23+
For example, it does not encode the base OS (Linux or Windows), but does
24+
include pointer size since some systems support both 32- and 64-bit builds.
25+
The available entries are the same on all platforms;
26+
e.g. *pointer_size* is available even on 64-bit-only architectures.
27+
28+
The following attributes are available:
29+
30+
.. attribute:: abi_info.pointer_bits
31+
32+
The width of pointers in bits, as an integer,
33+
equivalent to ``8 * sizeof(void *)``.
34+
Usually, this is ``32`` or ``64``.
35+
36+
.. attribute:: abi_info.free_threaded
37+
38+
A Boolean indicating whether the interpreter was built with
39+
:term:`free threading` support.
40+
This reflects either the presence of the :option:`--disable-gil`
41+
:file:`configure` option (on Unix)
42+
or setting the ``DisableGil`` property (on Windows).
43+
44+
.. attribute:: abi_info.debug
45+
46+
A Boolean indicating whether the interpreter was built in
47+
:ref:`debug mode <debug-build>`.
48+
This reflects either the presence of the :option:`--with-pydebug`
49+
:file:`configure` option (on Unix)
50+
or the ``Debug`` configuration (on Windows).
51+
52+
.. attribute:: abi_info.byteorder
53+
54+
A string indicating the native byte order,
55+
either ``'big'`` or ``'little'``.
56+
This is the same as the :data:`byteorder` attribute.
57+
58+
1459
.. data:: abiflags
1560

1661
On POSIX systems where Python was built with the standard ``configure``
@@ -523,8 +568,9 @@ always available. Unless explicitly noted otherwise, all variables are read-only
523568

524569
Since :func:`exit` ultimately "only" raises an exception, it will only exit
525570
the process when called from the main thread, and the exception is not
526-
intercepted. Cleanup actions specified by finally clauses of :keyword:`try` statements
527-
are honored, and it is possible to intercept the exit attempt at an outer level.
571+
intercepted. Cleanup actions specified by :keyword:`finally` clauses of
572+
:keyword:`try` statements are honored, and it is possible to intercept the
573+
exit attempt at an outer level.
528574

529575
.. versionchanged:: 3.6
530576
If an error occurs in the cleanup after the Python interpreter

Doc/whatsnew/3.15.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,13 @@ ssl
460460
(Contributed by Ron Frederick in :gh:`138252`.)
461461

462462

463+
sys
464+
---
465+
466+
* Add :data:`sys.abi_info` namespace to improve access to ABI information.
467+
(Contributed by Klaus Zimmermann in :gh:`137476`.)
468+
469+
463470
tarfile
464471
-------
465472

Lib/_pyrepl/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@ def gen_colors_from_token_stream(
208208
):
209209
span = Span.from_token(token, line_lengths)
210210
yield ColorSpan(span, "soft_keyword")
211-
elif token.string in BUILTINS:
211+
elif (
212+
token.string in BUILTINS
213+
and not (prev_token and prev_token.exact_type == T.DOT)
214+
):
212215
span = Span.from_token(token, line_lengths)
213216
yield ColorSpan(span, "builtin")
214217

Lib/asyncio/selector_events.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,13 @@ def writelines(self, list_of_data):
11741174
raise RuntimeError('unable to writelines; sendfile is in progress')
11751175
if not list_of_data:
11761176
return
1177+
1178+
if self._conn_lost:
1179+
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
1180+
logger.warning('socket.send() raised exception.')
1181+
self._conn_lost += 1
1182+
return
1183+
11771184
self._buffer.extend([memoryview(data) for data in list_of_data])
11781185
self._write_ready()
11791186
# If the entire buffer couldn't be written, register a write handler

Lib/test/test_asyncio/test_selector_events.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,22 @@ def test_writelines_pauses_protocol(self):
854854
self.assertTrue(self.sock.send.called)
855855
self.assertTrue(self.loop.writers)
856856

857+
def test_writelines_after_connection_lost(self):
858+
# GH-136234
859+
transport = self.socket_transport()
860+
self.sock.send = mock.Mock()
861+
self.sock.send.side_effect = ConnectionResetError
862+
transport.write(b'data1') # Will fail immediately, causing connection lost
863+
864+
transport.writelines([b'data2'])
865+
self.assertFalse(transport._buffer)
866+
self.assertFalse(self.loop.writers)
867+
868+
test_utils.run_briefly(self.loop) # Allow _call_connection_lost to run
869+
transport.writelines([b'data2'])
870+
self.assertFalse(transport._buffer)
871+
self.assertFalse(self.loop.writers)
872+
857873
@unittest.skipUnless(selector_events._HAS_SENDMSG, 'no sendmsg')
858874
def test_write_sendmsg_full(self):
859875
data = memoryview(b'data')

Lib/test/test_pyrepl/test_utils.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from unittest import TestCase
22

3-
from _pyrepl.utils import str_width, wlen, prev_next_window
3+
from _pyrepl.utils import str_width, wlen, prev_next_window, gen_colors
44

55

66
class TestUtils(TestCase):
@@ -60,3 +60,25 @@ def gen_raise():
6060
self.assertEqual(next(pnw), (3, 4, None))
6161
with self.assertRaises(ZeroDivisionError):
6262
next(pnw)
63+
64+
def test_gen_colors_keyword_highlighting(self):
65+
cases = [
66+
# no highlights
67+
("a.set", [(".", "op")]),
68+
("obj.list", [(".", "op")]),
69+
("obj.match", [(".", "op")]),
70+
("b. \\\n format", [(".", "op")]),
71+
# highlights
72+
("set", [("set", "builtin")]),
73+
("list", [("list", "builtin")]),
74+
(" \n dict", [("dict", "builtin")]),
75+
]
76+
for code, expected_highlights in cases:
77+
with self.subTest(code=code):
78+
colors = list(gen_colors(code))
79+
# Extract (text, tag) pairs for comparison
80+
actual_highlights = []
81+
for color in colors:
82+
span_text = code[color.span.start:color.span.end + 1]
83+
actual_highlights.append((span_text, color.tag))
84+
self.assertEqual(actual_highlights, expected_highlights)

Lib/test/test_sys.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,20 @@ def test_thread_info(self):
739739
elif sys.platform == "wasi":
740740
self.assertEqual(info.name, "pthread-stubs")
741741

742+
def test_abi_info(self):
743+
info = sys.abi_info
744+
self.assertEqual(len(info.__dict__), 4)
745+
pointer_bits = 64 if sys.maxsize > 2**32 else 32
746+
self.assertEqual(info.pointer_bits, pointer_bits)
747+
self.assertEqual(info.byteorder, sys.byteorder)
748+
for attr, flag in [
749+
("free_threaded", "Py_GIL_DISABLED"),
750+
("debug", "Py_DEBUG"),
751+
]:
752+
self.assertEqual(getattr(info, attr, None),
753+
bool(sysconfig.get_config_var(flag)),
754+
f"for {attr}")
755+
742756
@unittest.skipUnless(support.is_emscripten, "only available on Emscripten")
743757
def test_emscripten_info(self):
744758
self.assertEqual(len(sys._emscripten_info), 4)

0 commit comments

Comments
 (0)