Skip to content

Commit c9a6ac9

Browse files
committed
Merge branch 'refs/heads/main' into fix-gh-136327
2 parents 35c6097 + 0240ef4 commit c9a6ac9

File tree

15 files changed

+184
-51
lines changed

15 files changed

+184
-51
lines changed

Doc/c-api/structures.rst

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,52 @@ under :ref:`reference counting <countingrefs>`.
2828
object. In a normal "release" build, it contains only the object's
2929
reference count and a pointer to the corresponding type object.
3030
Nothing is actually declared to be a :c:type:`PyObject`, but every pointer
31-
to a Python object can be cast to a :c:expr:`PyObject*`. Access to the
32-
members must be done by using the macros :c:macro:`Py_REFCNT` and
33-
:c:macro:`Py_TYPE`.
31+
to a Python object can be cast to a :c:expr:`PyObject*`.
32+
33+
The members must not be accessed directly; instead use macros such as
34+
:c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`.
35+
36+
.. c:member:: Py_ssize_t ob_refcnt
37+
38+
The object's reference count, as returned by :c:macro:`Py_REFCNT`.
39+
Do not use this field directly; instead use functions and macros such as
40+
:c:macro:`!Py_REFCNT`, :c:func:`Py_INCREF` and :c:func:`Py_DecRef`.
41+
42+
The field type may be different from ``Py_ssize_t``, depending on
43+
build configuration and platform.
44+
45+
.. c:member:: PyTypeObject* ob_type
46+
47+
The object's type.
48+
Do not use this field directly; use :c:macro:`Py_TYPE` and
49+
:c:func:`Py_SET_TYPE` instead.
3450

3551

3652
.. c:type:: PyVarObject
3753
38-
This is an extension of :c:type:`PyObject` that adds the :c:member:`~PyVarObject.ob_size`
39-
field. This is only used for objects that have some notion of *length*.
40-
This type does not often appear in the Python/C API.
41-
Access to the members must be done by using the macros
42-
:c:macro:`Py_REFCNT`, :c:macro:`Py_TYPE`, and :c:macro:`Py_SIZE`.
54+
An extension of :c:type:`PyObject` that adds the
55+
:c:member:`~PyVarObject.ob_size` field.
56+
This is intended for objects that have some notion of *length*.
57+
58+
As with :c:type:`!PyObject`, the members must not be accessed directly;
59+
instead use macros such as :c:macro:`Py_SIZE`, :c:macro:`Py_REFCNT` and
60+
:c:macro:`Py_TYPE`.
61+
62+
.. c:member:: Py_ssize_t ob_size
63+
64+
A size field, whose contents should be considered an object's internal
65+
implementation detail.
66+
67+
Do not use this field directly; use :c:macro:`Py_SIZE` instead.
68+
69+
Object creation functions such as :c:func:`PyObject_NewVar` will
70+
generally set this field to the requested size (number of items).
71+
After creation, arbitrary values can be stored in :c:member:`!ob_size`
72+
using :c:macro:`Py_SET_SIZE`.
73+
74+
To get an object's publicly exposed length, as returned by
75+
the Python function :py:func:`len`, use :c:func:`PyObject_Length`
76+
instead.
4377

4478

4579
.. c:macro:: PyObject_HEAD
@@ -103,9 +137,8 @@ under :ref:`reference counting <countingrefs>`.
103137
104138
Get the type of the Python object *o*.
105139
106-
Return a :term:`borrowed reference`.
107-
108-
Use the :c:func:`Py_SET_TYPE` function to set an object type.
140+
The returned reference is :term:`borrowed <borrowed reference>` from *o*.
141+
Do not release it with :c:func:`Py_DECREF` or similar.
109142
110143
.. versionchanged:: 3.11
111144
:c:func:`Py_TYPE()` is changed to an inline static function.
@@ -122,16 +155,26 @@ under :ref:`reference counting <countingrefs>`.
122155
123156
.. c:function:: void Py_SET_TYPE(PyObject *o, PyTypeObject *type)
124157
125-
Set the object *o* type to *type*.
158+
Set the type of object *o* to *type*, without any checking or reference
159+
counting.
160+
161+
This is a very low-level operation.
162+
Consider instead setting the Python attribute :attr:`~object.__class__`
163+
using :c:func:`PyObject_SetAttrString` or similar.
164+
165+
Note that assigning an incompatible type can lead to undefined behavior.
166+
167+
If *type* is a :ref:`heap type <heap-types>`, the caller must create a
168+
new reference to it.
169+
Similarly, if the old type of *o* is a heap type, the caller must release
170+
a reference to that type.
126171
127172
.. versionadded:: 3.9
128173
129174
130175
.. c:function:: Py_ssize_t Py_SIZE(PyVarObject *o)
131176
132-
Get the size of the Python object *o*.
133-
134-
Use the :c:func:`Py_SET_SIZE` function to set an object size.
177+
Get the :c:member:`~PyVarObject.ob_size` field of *o*.
135178
136179
.. versionchanged:: 3.11
137180
:c:func:`Py_SIZE()` is changed to an inline static function.
@@ -140,7 +183,7 @@ under :ref:`reference counting <countingrefs>`.
140183
141184
.. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)
142185
143-
Set the object *o* size to *size*.
186+
Set the :c:member:`~PyVarObject.ob_size` field of *o* to *size*.
144187
145188
.. versionadded:: 3.9
146189

Doc/c-api/typeobj.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,9 @@ metatype) initializes :c:member:`~PyTypeObject.tp_itemsize`, which means that it
492492
type objects) *must* have the :c:member:`~PyVarObject.ob_size` field.
493493

494494

495-
.. c:member:: Py_ssize_t PyObject.ob_refcnt
495+
:c:member:`PyObject.ob_refcnt`
496496

497-
This is the type object's reference count, initialized to ``1`` by the
497+
The type object's reference count is initialized to ``1`` by the
498498
``PyObject_HEAD_INIT`` macro. Note that for :ref:`statically allocated type
499499
objects <static-types>`, the type's instances (objects whose :c:member:`~PyObject.ob_type`
500500
points back to the type) do *not* count as references. But for
@@ -506,7 +506,7 @@ type objects) *must* have the :c:member:`~PyVarObject.ob_size` field.
506506
This field is not inherited by subtypes.
507507

508508

509-
.. c:member:: PyTypeObject* PyObject.ob_type
509+
:c:member:`PyObject.ob_type`
510510

511511
This is the type's type, in other words its metatype. It is initialized by the
512512
argument to the ``PyObject_HEAD_INIT`` macro, and its value should normally be
@@ -532,14 +532,13 @@ type objects) *must* have the :c:member:`~PyVarObject.ob_size` field.
532532
PyVarObject Slots
533533
-----------------
534534

535-
.. c:member:: Py_ssize_t PyVarObject.ob_size
535+
:c:member:`PyVarObject.ob_size`
536536

537537
For :ref:`statically allocated type objects <static-types>`, this should be
538538
initialized to zero. For :ref:`dynamically allocated type objects
539539
<heap-types>`, this field has a special internal meaning.
540540

541-
This field should be accessed using the :c:func:`Py_SIZE()` and
542-
:c:func:`Py_SET_SIZE()` macros.
541+
This field should be accessed using the :c:func:`Py_SIZE()` macro.
543542

544543
**Inheritance:**
545544

Doc/conf.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -635,13 +635,14 @@
635635
'image': '_static/og-image.png',
636636
'line_color': '#3776ab',
637637
}
638-
ogp_custom_meta_tags = [
639-
'<meta name="theme-color" content="#3776ab">',
640-
]
641-
if 'create-social-cards' not in tags: # noqa: F821
642-
# Define a static preview image when not creating social cards
643-
ogp_image = '_static/og-image.png'
644-
ogp_custom_meta_tags += [
645-
'<meta property="og:image:width" content="200">',
646-
'<meta property="og:image:height" content="200">',
638+
if 'builder_html' in tags: # noqa: F821
639+
ogp_custom_meta_tags = [
640+
'<meta name="theme-color" content="#3776ab">',
647641
]
642+
if 'create-social-cards' not in tags: # noqa: F821
643+
# Define a static preview image when not creating social cards
644+
ogp_image = '_static/og-image.png'
645+
ogp_custom_meta_tags += [
646+
'<meta property="og:image:width" content="200">',
647+
'<meta property="og:image:height" content="200">',
648+
]

Doc/library/email.compat32-message.rst

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ Here are the methods of the :class:`Message` class:
181181
:meth:`set_payload` instead.
182182

183183
This is a legacy method. On the
184-
:class:`~email.emailmessage.EmailMessage` class its functionality is
184+
:class:`~email.message.EmailMessage` class its functionality is
185185
replaced by :meth:`~email.message.EmailMessage.set_content` and the
186186
related ``make`` and ``add`` methods.
187187

@@ -224,7 +224,7 @@ Here are the methods of the :class:`Message` class:
224224
ASCII charset.
225225

226226
This is a legacy method. On the
227-
:class:`~email.emailmessage.EmailMessage` class its functionality is
227+
:class:`~email.message.EmailMessage` class its functionality is
228228
replaced by :meth:`~email.message.EmailMessage.get_content` and
229229
:meth:`~email.message.EmailMessage.iter_parts`.
230230

@@ -236,7 +236,7 @@ Here are the methods of the :class:`Message` class:
236236
the message's default character set; see :meth:`set_charset` for details.
237237

238238
This is a legacy method. On the
239-
:class:`~email.emailmessage.EmailMessage` class its functionality is
239+
:class:`~email.message.EmailMessage` class its functionality is
240240
replaced by :meth:`~email.message.EmailMessage.set_content`.
241241

242242

@@ -265,9 +265,9 @@ Here are the methods of the :class:`Message` class:
265265
using that :mailheader:`Content-Transfer-Encoding` and is not modified.
266266

267267
This is a legacy method. On the
268-
:class:`~email.emailmessage.EmailMessage` class its functionality is
268+
:class:`~email.message.EmailMessage` class its functionality is
269269
replaced by the *charset* parameter of the
270-
:meth:`email.emailmessage.EmailMessage.set_content` method.
270+
:meth:`email.message.EmailMessage.set_content` method.
271271

272272

273273
.. method:: get_charset()
@@ -276,7 +276,7 @@ Here are the methods of the :class:`Message` class:
276276
message's payload.
277277

278278
This is a legacy method. On the
279-
:class:`~email.emailmessage.EmailMessage` class it always returns
279+
:class:`~email.message.EmailMessage` class it always returns
280280
``None``.
281281

282282

@@ -486,7 +486,7 @@ Here are the methods of the :class:`Message` class:
486486
search instead of :mailheader:`Content-Type`.
487487

488488
This is a legacy method. On the
489-
:class:`~email.emailmessage.EmailMessage` class its functionality is
489+
:class:`~email.message.EmailMessage` class its functionality is
490490
replaced by the *params* property of the individual header objects
491491
returned by the header access methods.
492492

@@ -524,7 +524,7 @@ Here are the methods of the :class:`Message` class:
524524
to ``False``.
525525

526526
This is a legacy method. On the
527-
:class:`~email.emailmessage.EmailMessage` class its functionality is
527+
:class:`~email.message.EmailMessage` class its functionality is
528528
replaced by the *params* property of the individual header objects
529529
returned by the header access methods.
530530

@@ -579,7 +579,7 @@ Here are the methods of the :class:`Message` class:
579579
header is also added.
580580

581581
This is a legacy method. On the
582-
:class:`~email.emailmessage.EmailMessage` class its functionality is
582+
:class:`~email.message.EmailMessage` class its functionality is
583583
replaced by the ``make_`` and ``add_`` methods.
584584

585585

Doc/tools/.nitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ Doc/extending/extending.rst
1515
Doc/library/ast.rst
1616
Doc/library/asyncio-extending.rst
1717
Doc/library/email.charset.rst
18-
Doc/library/email.compat32-message.rst
1918
Doc/library/email.parser.rst
2019
Doc/library/exceptions.rst
2120
Doc/library/functools.rst

Include/internal/pycore_object.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ static inline PyObject *
614614
_Py_XGetRef(PyObject **ptr)
615615
{
616616
for (;;) {
617-
PyObject *value = _Py_atomic_load_ptr(ptr);
617+
PyObject *value = _PyObject_CAST(_Py_atomic_load_ptr(ptr));
618618
if (value == NULL) {
619619
return value;
620620
}
@@ -629,7 +629,7 @@ _Py_XGetRef(PyObject **ptr)
629629
static inline PyObject *
630630
_Py_TryXGetRef(PyObject **ptr)
631631
{
632-
PyObject *value = _Py_atomic_load_ptr(ptr);
632+
PyObject *value = _PyObject_CAST(_Py_atomic_load_ptr(ptr));
633633
if (value == NULL) {
634634
return value;
635635
}

Include/internal/pycore_stackref.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ _Py_TryIncrefCompareStackRef(PyObject **src, PyObject *op, _PyStackRef *out)
829829
static inline int
830830
_Py_TryXGetStackRef(PyObject **src, _PyStackRef *out)
831831
{
832-
PyObject *op = _Py_atomic_load_ptr_relaxed(src);
832+
PyObject *op = _PyObject_CAST(_Py_atomic_load_ptr_relaxed(src));
833833
if (op == NULL) {
834834
*out = PyStackRef_NULL;
835835
return 1;

Lib/test/test_asyncio/test_base_events.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,29 @@ def test_ipaddr_info_no_inet_pton(self, m_socket):
150150
socket.SOCK_STREAM,
151151
socket.IPPROTO_TCP))
152152

153+
def test_interleave_addrinfos(self):
154+
self.maxDiff = None
155+
SIX_A = (socket.AF_INET6, 0, 0, '', ('2001:db8::1', 1))
156+
SIX_B = (socket.AF_INET6, 0, 0, '', ('2001:db8::2', 2))
157+
SIX_C = (socket.AF_INET6, 0, 0, '', ('2001:db8::3', 3))
158+
SIX_D = (socket.AF_INET6, 0, 0, '', ('2001:db8::4', 4))
159+
FOUR_A = (socket.AF_INET, 0, 0, '', ('192.0.2.1', 5))
160+
FOUR_B = (socket.AF_INET, 0, 0, '', ('192.0.2.2', 6))
161+
FOUR_C = (socket.AF_INET, 0, 0, '', ('192.0.2.3', 7))
162+
FOUR_D = (socket.AF_INET, 0, 0, '', ('192.0.2.4', 8))
163+
164+
addrinfos = [SIX_A, SIX_B, SIX_C, FOUR_A, FOUR_B, FOUR_C, FOUR_D, SIX_D]
165+
expected = [SIX_A, FOUR_A, SIX_B, FOUR_B, SIX_C, FOUR_C, SIX_D, FOUR_D]
166+
167+
self.assertEqual(expected, base_events._interleave_addrinfos(addrinfos))
168+
169+
expected_fafc_2 = [SIX_A, SIX_B, FOUR_A, SIX_C, FOUR_B, SIX_D, FOUR_C, FOUR_D]
170+
self.assertEqual(
171+
expected_fafc_2,
172+
base_events._interleave_addrinfos(addrinfos, first_address_family_count=2),
173+
)
174+
175+
153176

154177
class BaseEventLoopTests(test_utils.TestCase):
155178

@@ -1053,6 +1076,71 @@ def test_asyncgen_finalization_by_gc_in_other_thread(self):
10531076
test_utils.run_briefly(self.loop)
10541077
self.assertTrue(status['finalized'])
10551078

1079+
@unittest.skipUnless(socket_helper.IPV6_ENABLED, 'no IPv6 support')
1080+
@patch_socket
1081+
def test_create_connection_happy_eyeballs(self, m_socket):
1082+
1083+
class MyProto(asyncio.Protocol):
1084+
pass
1085+
1086+
async def getaddrinfo(*args, **kw):
1087+
return [(socket.AF_INET6, 0, 0, '', ('2001:db8::1', 1)),
1088+
(socket.AF_INET, 0, 0, '', ('192.0.2.1', 5))]
1089+
1090+
async def sock_connect(sock, address):
1091+
if address[0] == '2001:db8::1':
1092+
await asyncio.sleep(1)
1093+
sock.connect(address)
1094+
1095+
loop = asyncio.new_event_loop()
1096+
loop._add_writer = mock.Mock()
1097+
loop._add_writer = mock.Mock()
1098+
loop._add_reader = mock.Mock()
1099+
loop.getaddrinfo = getaddrinfo
1100+
loop.sock_connect = sock_connect
1101+
1102+
coro = loop.create_connection(MyProto, 'example.com', 80, happy_eyeballs_delay=0.3)
1103+
transport, protocol = loop.run_until_complete(coro)
1104+
try:
1105+
sock = transport._sock
1106+
sock.connect.assert_called_with(('192.0.2.1', 5))
1107+
finally:
1108+
transport.close()
1109+
test_utils.run_briefly(loop) # allow transport to close
1110+
loop.close()
1111+
1112+
@patch_socket
1113+
def test_create_connection_happy_eyeballs_ipv4_only(self, m_socket):
1114+
1115+
class MyProto(asyncio.Protocol):
1116+
pass
1117+
1118+
async def getaddrinfo(*args, **kw):
1119+
return [(socket.AF_INET, 0, 0, '', ('192.0.2.1', 5)),
1120+
(socket.AF_INET, 0, 0, '', ('192.0.2.2', 6))]
1121+
1122+
async def sock_connect(sock, address):
1123+
if address[0] == '192.0.2.1':
1124+
await asyncio.sleep(1)
1125+
sock.connect(address)
1126+
1127+
loop = asyncio.new_event_loop()
1128+
loop._add_writer = mock.Mock()
1129+
loop._add_writer = mock.Mock()
1130+
loop._add_reader = mock.Mock()
1131+
loop.getaddrinfo = getaddrinfo
1132+
loop.sock_connect = sock_connect
1133+
1134+
coro = loop.create_connection(MyProto, 'example.com', 80, happy_eyeballs_delay=0.3)
1135+
transport, protocol = loop.run_until_complete(coro)
1136+
try:
1137+
sock = transport._sock
1138+
sock.connect.assert_called_with(('192.0.2.2', 6))
1139+
finally:
1140+
transport.close()
1141+
test_utils.run_briefly(loop) # allow transport to close
1142+
loop.close()
1143+
10561144

10571145
class MyProto(asyncio.Protocol):
10581146
done = None

Lib/test/test_dbm.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ def test_whichdb(self):
274274
@unittest.skipUnless(ndbm, reason='Test requires ndbm')
275275
def test_whichdb_ndbm(self):
276276
# Issue 17198: check that ndbm which is referenced in whichdb is defined
277-
with open(_fname + '.db', 'wb'): pass
277+
with open(_fname + '.db', 'wb') as f:
278+
f.write(b'spam')
278279
_bytes_fname = os.fsencode(_fname)
279280
fnames = [_fname, os_helper.FakePath(_fname),
280281
_bytes_fname, os_helper.FakePath(_bytes_fname)]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix compilation errors when compiling the internal headers with a C++ compiler.

0 commit comments

Comments
 (0)