Skip to content

Commit 92d347c

Browse files
authored
Merge branch 'main' into fix-proactor-close-flush
2 parents 55706b8 + d9565e5 commit 92d347c

42 files changed

Lines changed: 391 additions & 73 deletions

Some content is hidden

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

Doc/c-api/complex.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,6 @@ the :ref:`Number Protocol <number>` API or use native complex types, like
197197
Set :c:data:`errno` to :c:macro:`!ERANGE` on overflows.
198198
199199
.. deprecated:: 3.15
200+
201+
.. versionchanged:: next
202+
This function leaves :c:data:`errno` unchanged on success.

Doc/library/socket.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@ Socket Objects
14971497
of :meth:`socket.getpeername` but not the actual OS resource. Unlike
14981498
:func:`socket.fromfd`, *fileno* will return the same socket and not a
14991499
duplicate. This may help close a detached socket using
1500-
:meth:`socket.close`.
1500+
:meth:`~socket.socket.close`.
15011501

15021502
The newly created socket is :ref:`non-inheritable <fd_inheritance>`.
15031503

@@ -1544,7 +1544,7 @@ Socket Objects
15441544

15451545
.. versionchanged:: 3.2
15461546
Support for the :term:`context manager` protocol was added. Exiting the
1547-
context manager is equivalent to calling :meth:`~socket.close`.
1547+
context manager is equivalent to calling :meth:`~socket.socket.close`.
15481548

15491549

15501550
.. method:: accept()
@@ -1769,7 +1769,7 @@ Socket Objects
17691769

17701770
Closing the file object returned by :meth:`makefile` won't close the
17711771
original socket unless all other file objects have been closed and
1772-
:meth:`socket.close` has been called on the socket object.
1772+
:meth:`~socket.socket.close` has been called on the socket object.
17731773

17741774
.. note::
17751775

Doc/library/warnings.rst

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,45 +68,48 @@ The following warnings category classes are currently defined:
6868
+----------------------------------+-----------------------------------------------+
6969
| Class | Description |
7070
+==================================+===============================================+
71-
| :exc:`Warning` | This is the base class of all warning |
72-
| | category classes. It is a subclass of |
73-
| | :exc:`Exception`. |
71+
| :exc:`Warning` | Base class for warning categories. It is a |
72+
| | subclass of :exc:`Exception`. |
7473
+----------------------------------+-----------------------------------------------+
75-
| :exc:`UserWarning` | The default category for :func:`warn`. |
74+
| :exc:`UserWarning` | Base class for warnings generated by user |
75+
| | code. The default category for :func:`warn`. |
7676
+----------------------------------+-----------------------------------------------+
77-
| :exc:`DeprecationWarning` | Base category for warnings about deprecated |
77+
| :exc:`DeprecationWarning` | Base class for warnings about deprecated |
7878
| | features when those warnings are intended for |
7979
| | other Python developers (ignored by default, |
8080
| | unless triggered by code in ``__main__``). |
8181
+----------------------------------+-----------------------------------------------+
82-
| :exc:`SyntaxWarning` | Base category for warnings about dubious |
83-
| | syntactic features (typically emitted when |
84-
| | compiling Python source code, and hence |
85-
| | may not be suppressed by runtime filters) |
82+
| :exc:`PendingDeprecationWarning` | Base class for warnings about features |
83+
| | that will be deprecated in the future |
84+
| | (ignored by default). |
8685
+----------------------------------+-----------------------------------------------+
87-
| :exc:`RuntimeWarning` | Base category for warnings about dubious |
88-
| | runtime features. |
86+
| :exc:`SyntaxWarning` | Base class for warnings about dubious syntax |
87+
| | (typically emitted when compiling Python |
88+
| | source code, and hence may not be suppressed |
89+
| | by runtime filters). |
8990
+----------------------------------+-----------------------------------------------+
90-
| :exc:`FutureWarning` | Base category for warnings about deprecated |
91+
| :exc:`RuntimeWarning` | Base class for warnings about dubious runtime |
92+
| | behavior. |
93+
+----------------------------------+-----------------------------------------------+
94+
| :exc:`FutureWarning` | Base class for warnings about deprecated |
9195
| | features when those warnings are intended for |
9296
| | end users of applications that are written in |
9397
| | Python. |
9498
+----------------------------------+-----------------------------------------------+
95-
| :exc:`PendingDeprecationWarning` | Base category for warnings about features |
96-
| | that will be deprecated in the future |
97-
| | (ignored by default). |
98-
+----------------------------------+-----------------------------------------------+
99-
| :exc:`ImportWarning` | Base category for warnings triggered during |
99+
| :exc:`ImportWarning` | Base class for warnings triggered during |
100100
| | the process of importing a module (ignored by |
101101
| | default). |
102102
+----------------------------------+-----------------------------------------------+
103-
| :exc:`UnicodeWarning` | Base category for warnings related to |
103+
| :exc:`UnicodeWarning` | Base class for warnings related to |
104104
| | Unicode. |
105105
+----------------------------------+-----------------------------------------------+
106-
| :exc:`BytesWarning` | Base category for warnings related to |
106+
| :exc:`EncodingWarning` | Base class for warnings related to encodings. |
107+
| | See :ref:`io-encoding-warning` for details. |
108+
+----------------------------------+-----------------------------------------------+
109+
| :exc:`BytesWarning` | Base class for warnings related to |
107110
| | :class:`bytes` and :class:`bytearray`. |
108111
+----------------------------------+-----------------------------------------------+
109-
| :exc:`ResourceWarning` | Base category for warnings related to |
112+
| :exc:`ResourceWarning` | Base class for warnings related to |
110113
| | resource usage (ignored by default). |
111114
+----------------------------------+-----------------------------------------------+
112115

Doc/whatsnew/3.16.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,10 @@ Porting to Python 3.16
10181018
if the value cannot be marshalled.
10191019
(Contributed by Serhiy Storchaka in :gh:`155907`.)
10201020

1021+
* :c:func:`_Py_c_abs` no longer sets :c:data:`errno` to zero on success,
1022+
but rather leaves it unchanged.
1023+
(Contributed by Sergey B Kirpichev in :gh:`155526`.)
1024+
10211025
Deprecated C APIs
10221026
-----------------
10231027

Lib/asyncio/tasks.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,9 @@ def __step(self, exc=None):
268268
raise exceptions.InvalidStateError(
269269
f'__step(): already done: {self!r}, {exc!r}')
270270
if self._must_cancel:
271-
if not isinstance(exc, exceptions.CancelledError):
271+
# gh-108549: do not swallow SystemExit and KeyboardInterrupt.
272+
if not isinstance(exc, (exceptions.CancelledError,
273+
SystemExit, KeyboardInterrupt)):
272274
exc = self._make_cancelled_error()
273275
self._must_cancel = False
274276
self._fut_waiter = None
@@ -541,13 +543,18 @@ async def _cancel_and_wait(fut):
541543
cb = functools.partial(_release_waiter, waiter)
542544
fut.add_done_callback(cb)
543545

546+
# gh-157058: awaiting the waiter leaves no edge on fut, add it here
547+
cur_task = current_task()
548+
futures.future_add_to_awaited_by(fut, cur_task)
549+
544550
try:
545551
fut.cancel()
546552
# We cannot wait on *fut* directly to make
547553
# sure _cancel_and_wait itself is reliably cancellable.
548554
await waiter
549555
finally:
550556
fut.remove_done_callback(cb)
557+
futures.future_discard_from_awaited_by(fut, cur_task)
551558

552559

553560
class _AsCompletedIterator:
@@ -770,6 +777,11 @@ def cancel(self, msg=None):
770777
return ret
771778

772779

780+
def _discard_awaited_by(children, waiter, outer):
781+
for fut in children:
782+
futures.future_discard_from_awaited_by(fut, waiter)
783+
784+
773785
def gather(*coros_or_futures, return_exceptions=False):
774786
"""Return a future aggregating results from the given coroutines/futures.
775787
@@ -903,6 +915,10 @@ def _done_callback(fut, cur_task=cur_task):
903915
children.append(fut)
904916

905917
outer = _GatheringFuture(children, loop=loop)
918+
if cur_task is not None:
919+
# gh-157213: a child outliving gather() must lose the awaited-by edge
920+
outer.add_done_callback(
921+
functools.partial(_discard_awaited_by, children, cur_task))
906922
# Run done callbacks after GatheringFuture created so any post-processing
907923
# can be performed at this point
908924
# optimization: in the special case that *all* futures finished eagerly,

Lib/base64.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ def b16decode(s, casefold=False, *, ignorechars=b''):
304304
for b in b'abcdef':
305305
if b in s and b not in ignorechars:
306306
raise binascii.Error('Non-base16 digit found')
307-
s = s.translate(None, delete=b'abcdef')
307+
if ignorechars:
308+
s = s.translate(None, delete=b'abcdef')
308309
return binascii.unhexlify(s, ignorechars=ignorechars)
309310

310311
#

Lib/importlib/_bootstrap_external.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
_MS_WINDOWS = (sys.platform == 'win32')
3434
if _MS_WINDOWS:
3535
import nt as _os
36-
import winreg
36+
try:
37+
import winreg
38+
except ImportError:
39+
winreg = None
3740
else:
3841
import posix as _os
3942

Lib/tarfile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2841,9 +2841,11 @@ def makelink_with_filter(self, tarinfo, targetpath,
28412841
"makelink_with_filter: if filter_function is not None, "
28422842
+ "extraction_root must also not be None")
28432843
try:
2844-
filter_function(
2844+
filtered = filter_function(
28452845
unfiltered.replace(name=tarinfo.name, deep=False),
28462846
extraction_root)
2847+
if filtered is None:
2848+
return
28472849
filtered = filter_function(unfiltered, extraction_root)
28482850
except _FILTER_ERRORS as cause:
28492851
raise LinkFallbackError(tarinfo, unfiltered.name) from cause

Lib/test/test_asyncio/test_graph.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,33 @@ class FakeCoro:
173173

174174
self.assertEqual(len(result.call_stack), 2)
175175

176+
async def test_stack_wait_for_non_positive_timeout(self):
177+
# gh-157058: wait_for(fut, 0) must still record the waiter
178+
cleanup = asyncio.Future()
179+
180+
async def worker():
181+
try:
182+
await asyncio.Future()
183+
finally:
184+
await cleanup
185+
186+
async def probe(t):
187+
await asyncio.wait_for(t, 0)
188+
189+
t = asyncio.ensure_future(worker())
190+
p = asyncio.create_task(probe(t), name='probe')
191+
for _ in range(5):
192+
await asyncio.sleep(0)
193+
194+
stack = capture_test_stack(fut=t)
195+
196+
cleanup.set_result(None)
197+
await asyncio.gather(p, t, return_exceptions=True)
198+
199+
self.assertEqual(stack[0][2], [
200+
['T<probe>', ['a _cancel_and_wait', 'a wait_for', 'a probe'], []],
201+
])
202+
176203
async def test_stack_gather(self):
177204

178205
stack_for_deep = None
@@ -202,6 +229,29 @@ async def main():
202229
]
203230
])
204231

232+
async def test_stack_gather_survivor(self):
233+
# gh-157213: a child that outlives gather() must not be shown as awaited
234+
235+
async def fail():
236+
raise ValueError
237+
238+
async def survivor():
239+
await asyncio.Future()
240+
241+
t = asyncio.create_task(survivor(), name='survivor')
242+
with self.assertRaises(ValueError):
243+
await asyncio.gather(t, fail())
244+
245+
self.assertEqual(capture_test_stack(fut=t)[0], [
246+
'T<survivor>',
247+
['a survivor'],
248+
[]
249+
])
250+
251+
t.cancel()
252+
with self.assertRaises(asyncio.CancelledError):
253+
await t
254+
205255
async def test_stack_shield(self):
206256

207257
stack_for_shield = None

Lib/test/test_asyncio/test_taskgroups.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,11 +1200,17 @@ async def child(tg):
12001200

12011201
async def test_taskgroup_cancel_keeps_outer_cancellation(self):
12021202
# gh-155433: any cancellation from outside the group must propagate.
1203+
cancelling = asyncio.Event()
1204+
release = asyncio.Event()
1205+
12031206
async def child():
12041207
try:
12051208
await asyncio.sleep(10)
12061209
finally:
1207-
await asyncio.sleep(0.1)
1210+
# The group is cancelling: it has cancelled its parent task
1211+
# and is waiting for this task to finish.
1212+
cancelling.set()
1213+
await release.wait()
12081214

12091215
async def body():
12101216
async with asyncio.TaskGroup() as tg:
@@ -1213,8 +1219,9 @@ async def body():
12131219
tg.cancel()
12141220

12151221
task = asyncio.create_task(body())
1216-
await asyncio.sleep(0.01)
1222+
await cancelling.wait()
12171223
task.cancel('message')
1224+
release.set()
12181225
with self.assertRaises(asyncio.CancelledError) as cm:
12191226
await task
12201227
self.assertEqual('message', cm.exception.args[0])

0 commit comments

Comments
 (0)