Skip to content

Commit 66ec1a0

Browse files
Merge branch 'main' into htmlparser-tag
2 parents 955db4e + da79ac9 commit 66ec1a0

23 files changed

+239
-56
lines changed

Doc/c-api/object.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ Object Protocol
197197
in favour of using :c:func:`PyObject_DelAttr`, but there are currently no
198198
plans to remove it.
199199
200+
The function must not be called with ``NULL`` *v* and an an exception set.
201+
This case can arise from forgetting ``NULL`` checks and would delete the
202+
attribute.
203+
204+
.. versionchanged:: next
205+
Must not be called with NULL value if an exception is set.
206+
200207
201208
.. c:function:: int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v)
202209
@@ -207,6 +214,10 @@ Object Protocol
207214
If *v* is ``NULL``, the attribute is deleted, but this feature is
208215
deprecated in favour of using :c:func:`PyObject_DelAttrString`.
209216
217+
The function must not be called with ``NULL`` *v* and an an exception set.
218+
This case can arise from forgetting ``NULL`` checks and would delete the
219+
attribute.
220+
210221
The number of different attribute names passed to this function
211222
should be kept small, usually by using a statically allocated string
212223
as *attr_name*.
@@ -215,6 +226,10 @@ Object Protocol
215226
For more details, see :c:func:`PyUnicode_InternFromString`, which may be
216227
used internally to create a key object.
217228
229+
.. versionchanged:: next
230+
Must not be called with NULL value if an exception is set.
231+
232+
218233
.. c:function:: int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject *value)
219234
220235
Generic attribute setter and deleter function that is meant

Doc/howto/functional.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@ flow inside a program. The book uses Scheme for its examples, but many of the
12171217
design approaches described in these chapters are applicable to functional-style
12181218
Python code.
12191219

1220-
https://www.defmacro.org/ramblings/fp.html: A general introduction to functional
1220+
https://defmacro.org/2006/06/19/fp.html: A general introduction to functional
12211221
programming that uses Java examples and has a lengthy historical introduction.
12221222

12231223
https://en.wikipedia.org/wiki/Functional_programming: General Wikipedia entry

Doc/howto/isolating-extensions.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,8 +626,7 @@ Open Issues
626626

627627
Several issues around per-module state and heap types are still open.
628628

629-
Discussions about improving the situation are best held on the `capi-sig
630-
mailing list <https://mail.python.org/mailman3/lists/capi-sig.python.org/>`__.
629+
Discussions about improving the situation are best held on the `discuss forum under c-api tag <https://discuss.python.org/c/core-dev/c-api/30>`__.
631630

632631

633632
Per-Class Scope

Doc/installing/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ switch::
188188
Once the Development & Deployment part of PPUG is fleshed out, some of
189189
those sections should be linked from new questions here (most notably,
190190
we should have a question about avoiding depending on PyPI that links to
191-
https://packaging.python.org/en/latest/mirrors/)
191+
https://packaging.python.org/en/latest/guides/index-mirrors-and-caches/)
192192
193193
194194
Common installation issues

Doc/using/configure.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ Features and minimum versions required to build CPython:
2929

3030
* Tcl/Tk 8.5.12 for the :mod:`tkinter` module.
3131

32+
* `libmpdec <https://www.bytereef.org/mpdecimal/doc/libmpdec/>`_ 2.5.0
33+
for the :mod:`decimal` module.
34+
3235
* Autoconf 2.72 and aclocal 1.16.5 are required to regenerate the
3336
:file:`configure` script.
3437

Lib/asyncio/base_events.py

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,38 +1016,43 @@ async def _connect_sock(self, exceptions, addr_info, local_addr_infos=None):
10161016
family, type_, proto, _, address = addr_info
10171017
sock = None
10181018
try:
1019-
sock = socket.socket(family=family, type=type_, proto=proto)
1020-
sock.setblocking(False)
1021-
if local_addr_infos is not None:
1022-
for lfamily, _, _, _, laddr in local_addr_infos:
1023-
# skip local addresses of different family
1024-
if lfamily != family:
1025-
continue
1026-
try:
1027-
sock.bind(laddr)
1028-
break
1029-
except OSError as exc:
1030-
msg = (
1031-
f'error while attempting to bind on '
1032-
f'address {laddr!r}: {str(exc).lower()}'
1033-
)
1034-
exc = OSError(exc.errno, msg)
1035-
my_exceptions.append(exc)
1036-
else: # all bind attempts failed
1037-
if my_exceptions:
1038-
raise my_exceptions.pop()
1039-
else:
1040-
raise OSError(f"no matching local address with {family=} found")
1041-
await self.sock_connect(sock, address)
1042-
return sock
1043-
except OSError as exc:
1044-
my_exceptions.append(exc)
1045-
if sock is not None:
1046-
sock.close()
1047-
raise
1019+
try:
1020+
sock = socket.socket(family=family, type=type_, proto=proto)
1021+
sock.setblocking(False)
1022+
if local_addr_infos is not None:
1023+
for lfamily, _, _, _, laddr in local_addr_infos:
1024+
# skip local addresses of different family
1025+
if lfamily != family:
1026+
continue
1027+
try:
1028+
sock.bind(laddr)
1029+
break
1030+
except OSError as exc:
1031+
msg = (
1032+
f'error while attempting to bind on '
1033+
f'address {laddr!r}: {str(exc).lower()}'
1034+
)
1035+
exc = OSError(exc.errno, msg)
1036+
my_exceptions.append(exc)
1037+
else: # all bind attempts failed
1038+
if my_exceptions:
1039+
raise my_exceptions.pop()
1040+
else:
1041+
raise OSError(f"no matching local address with {family=} found")
1042+
await self.sock_connect(sock, address)
1043+
return sock
1044+
except OSError as exc:
1045+
my_exceptions.append(exc)
1046+
raise
10481047
except:
10491048
if sock is not None:
1050-
sock.close()
1049+
try:
1050+
sock.close()
1051+
except OSError:
1052+
# An error when closing a newly created socket is
1053+
# not important, but it can overwrite more important
1054+
# non-OSError error. So ignore it.
1055+
pass
10511056
raise
10521057
finally:
10531058
exceptions = my_exceptions = None

Lib/encodings/idna.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ def _buffer_encode(self, input, errors, final):
316316
class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
317317
def _buffer_decode(self, input, errors, final):
318318
if errors != 'strict':
319-
raise UnicodeError("Unsupported error handling: {errors}")
319+
raise UnicodeError(f"Unsupported error handling: {errors}")
320320

321321
if not input:
322322
return ("", 0)

Lib/fractions.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ def _format_float_style(self, match):
504504
trim_point = not alternate_form
505505
exponent_indicator = "E" if presentation_type in "EFG" else "e"
506506

507+
if align == '=' and fill == '0':
508+
zeropad = True
509+
507510
# Round to get the digits we need, figure out where to place the point,
508511
# and decide whether to use scientific notation. 'point_pos' is the
509512
# relative to the _end_ of the digit string: that is, it's the number

Lib/test/test_asyncio/test_base_events.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
MOCK_ANY = mock.ANY
2525

2626

27+
class CustomError(Exception):
28+
pass
29+
30+
2731
def tearDownModule():
2832
asyncio._set_event_loop_policy(None)
2933

@@ -1326,6 +1330,31 @@ def getaddrinfo_task(*args, **kwds):
13261330
self.assertEqual(len(cm.exception.exceptions), 1)
13271331
self.assertIsInstance(cm.exception.exceptions[0], OSError)
13281332

1333+
@patch_socket
1334+
def test_create_connection_connect_non_os_err_close_err(self, m_socket):
1335+
# Test the case when sock_connect() raises non-OSError exception
1336+
# and sock.close() raises OSError.
1337+
async def getaddrinfo(*args, **kw):
1338+
return [(2, 1, 6, '', ('107.6.106.82', 80))]
1339+
1340+
def getaddrinfo_task(*args, **kwds):
1341+
return self.loop.create_task(getaddrinfo(*args, **kwds))
1342+
1343+
self.loop.getaddrinfo = getaddrinfo_task
1344+
self.loop.sock_connect = mock.Mock()
1345+
self.loop.sock_connect.side_effect = CustomError
1346+
sock = mock.Mock()
1347+
m_socket.socket.return_value = sock
1348+
sock.close.side_effect = OSError
1349+
1350+
coro = self.loop.create_connection(MyProto, 'example.com', 80)
1351+
self.assertRaises(
1352+
CustomError, self.loop.run_until_complete, coro)
1353+
1354+
coro = self.loop.create_connection(MyProto, 'example.com', 80, all_errors=True)
1355+
self.assertRaises(
1356+
CustomError, self.loop.run_until_complete, coro)
1357+
13291358
def test_create_connection_multiple(self):
13301359
async def getaddrinfo(*args, **kw):
13311360
return [(2, 1, 6, '', ('0.0.0.1', 80)),

Lib/test/test_capi/test_abstract.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,31 @@ def test_iter_nextitem(self):
10771077
with self.assertRaisesRegex(TypeError, regex):
10781078
PyIter_NextItem(10)
10791079

1080+
def test_object_setattr_null_exc(self):
1081+
class Obj:
1082+
pass
1083+
obj = Obj()
1084+
obj.attr = 123
1085+
1086+
exc = ValueError("error")
1087+
with self.assertRaises(SystemError) as cm:
1088+
_testcapi.object_setattr_null_exc(obj, 'attr', exc)
1089+
self.assertIs(cm.exception.__context__, exc)
1090+
self.assertIsNone(cm.exception.__cause__)
1091+
self.assertHasAttr(obj, 'attr')
1092+
1093+
with self.assertRaises(SystemError) as cm:
1094+
_testcapi.object_setattrstring_null_exc(obj, 'attr', exc)
1095+
self.assertIs(cm.exception.__context__, exc)
1096+
self.assertIsNone(cm.exception.__cause__)
1097+
self.assertHasAttr(obj, 'attr')
1098+
1099+
with self.assertRaises(SystemError) as cm:
1100+
# undecodable name
1101+
_testcapi.object_setattrstring_null_exc(obj, b'\xff', exc)
1102+
self.assertIs(cm.exception.__context__, exc)
1103+
self.assertIsNone(cm.exception.__cause__)
1104+
10801105

10811106
if __name__ == "__main__":
10821107
unittest.main()

0 commit comments

Comments
 (0)