Skip to content

Commit 1afc2ec

Browse files
authored
Merge branch 'main' into claude/elegant-faraday-p69m3r
2 parents 48e893e + 4e3d5ec commit 1afc2ec

18 files changed

Lines changed: 266 additions & 57 deletions

‎Doc/c-api/extension-modules.rst‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,16 +313,32 @@ This is typically done using :c:func:`PyModule_Create` and functions like
313313
Single-phase initialization differs from the :ref:`default <multi-phase-initialization>`
314314
in the following ways:
315315
316-
* Single-phase modules are, or rather *contain*, “singletons”.
316+
* Single-phase modules with :c:member:`PyModuleDef.m_size` set to -1 are,
317+
or rather *contain*, “singletons”.
317318
318-
When the module is first initialized, Python saves the contents of
319+
When such a module is first initialized, Python saves the contents of
319320
the module's ``__dict__`` (that is, typically, the module's functions and
320321
types).
321322
322323
For subsequent imports, Python does not call the initialization function
323324
again.
324325
Instead, it creates a new module object with a new ``__dict__``, and copies
325326
the saved contents to it.
327+
Modules are matched to the saved contents by a (*module_name*, *file_name*)
328+
tuple where:
329+
330+
- *module_name* is the module's full dotted name, taken from
331+
:py:attr:`ModuleSpec.name <importlib.machinery.ModuleSpec.name>`
332+
(or the equivalent argument of the importing function).
333+
Note that names that the initialization function uses to create the module
334+
(for example, :c:member:`PyModuleDef.m_name`) are not taken into account.
335+
- *file_name* is the extension's file name.
336+
It is unset for modules not loaded from a file, such as built-ins and
337+
modules added with :c:func:`PyImport_CreateModuleFromInitfunc` or
338+
:c:func:`PyImport_AppendInittab`.
339+
340+
As part of the first initialization, Python also adds the module to
341+
:data:`sys.modules` under its name.
326342
For example, given a single-phase module ``_testsinglephase``
327343
[#testsinglephase]_ that defines a function ``sum`` and an exception class
328344
``error``:
@@ -344,6 +360,16 @@ in the following ways:
344360
345361
The exact behavior should be considered a CPython implementation detail.
346362

363+
* For single-phase modules with non-negative :c:member:`PyModuleDef.m_size`,
364+
Python may cache a pointer to the initialization function under the
365+
(*module_name*, *file_name*) key as for ``m_size == -1``.
366+
367+
Subsequent imports that specify a different initialization function
368+
(for example, using :c:func:`PyImport_CreateModuleFromInitfunc`)
369+
may call either the cached function or the provided "new" one.
370+
371+
The exact behavior should again be considered a CPython implementation detail.
372+
347373
* To work around the fact that ``PyInit_modulename`` does not take a *spec*
348374
argument, some state of the import machinery is saved and applied to the
349375
first suitable module created during the ``PyInit_modulename`` call.

‎Doc/c-api/file.rst‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,29 @@ the :mod:`io` APIs instead.
6060
raised if the end of the file is reached immediately.
6161
6262
63+
.. c:function:: char* Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
64+
65+
Read a line from the C stream *stream* into the buffer *buf*, like the
66+
C standard library function :c:func:`!fgets`, but treating all of ``\n``,
67+
``\r`` and ``\r\n`` as line endings (see :term:`universal newlines`).
68+
Any ``\r`` or ``\r\n`` read from the stream is stored in *buf* as a
69+
single ``\n``.
70+
71+
At most ``n - 1`` characters are stored in *buf*; reading stops after a
72+
newline has been stored or when the end of the file is reached.
73+
The result is always null-terminated.
74+
*stream* should be opened in binary mode, so that the C library does not
75+
perform its own newline translation.
76+
77+
Return *buf* on success.
78+
Return ``NULL`` if no characters could be read, because *stream* is at
79+
end of file, a read error occurred, or *n* is less than 2.
80+
Like :c:func:`!fgets`, this function does not distinguish between end of
81+
file and a read error, and it does not set an exception.
82+
83+
*fobj* exists only for backward compatibility and must be ``NULL``.
84+
85+
6386
.. c:function:: int PyFile_SetOpenCodeHook(Py_OpenCodeHookFunction handler)
6487
6588
Overrides the normal behavior of :func:`io.open_code` to pass its parameter

‎Doc/c-api/float.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ Pack functions
214214
The pack routines write 2, 4 or 8 bytes, starting at *p*. *le* is an
215215
:c:expr:`int` argument, non-zero if you want the bytes string in little-endian
216216
format (exponent last, at ``p+1``, ``p+3``, or ``p+6`` and ``p+7``), zero if you
217-
want big-endian format (exponent first, at *p*). Use the :c:macro:`!PY_LITTLE_ENDIAN`
217+
want big-endian format (exponent first, at *p*). Use the :c:macro:`PY_LITTLE_ENDIAN`
218218
constant to select the native endian: it is equal to ``0`` on big
219219
endian processor, or ``1`` on little endian processor.
220220
@@ -240,7 +240,7 @@ Unpack functions
240240
The unpack routines read 2, 4 or 8 bytes, starting at *p*. *le* is an
241241
:c:expr:`int` argument, non-zero if the bytes string is in little-endian format
242242
(exponent last, at ``p+1``, ``p+3`` or ``p+6`` and ``p+7``), zero if big-endian
243-
(exponent first, at *p*). Use the :c:macro:`!PY_LITTLE_ENDIAN` constant to
243+
(exponent first, at *p*). Use the :c:macro:`PY_LITTLE_ENDIAN` constant to
244244
select the native endian: it is equal to ``0`` on big endian processor, or ``1``
245245
on little endian processor.
246246

‎Doc/c-api/import.rst‎

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ Importing Modules
408408
409409
*spec* must be a :class:`~importlib.machinery.ModuleSpec` object.
410410
411-
*initfunc* must be an :ref:`initialization function <extension-export-hook>`,
411+
*initfunc* must be an :ref:`initialization function <extension-pyinit>`,
412412
the same as for :c:func:`PyImport_AppendInittab`.
413413
414414
On success, create and return a module object.
@@ -417,10 +417,27 @@ Importing Modules
417417
(Custom importers should do this in their
418418
:py:meth:`~importlib.abc.Loader.exec_module` method.)
419419
420-
If the spec's name is dotted and *initfunc* creates the module using only
421-
the last component of the name, the module's :attr:`~module.__name__`
422-
is set to the full name from the spec.
423-
424420
On error, return NULL with an exception set.
425421
422+
For modules using :ref:`legacy single-phase initialization <single-phase-initialization>`,
423+
most of the import process is done in this function, rather than in
424+
extra steps that importers typically take after
425+
:py:meth:`~importlib.abc.Loader.create_module`.
426+
Specifically:
427+
428+
- The module is added to :data:`sys.modules` under the *spec*'s
429+
:py:attr:`~importlib.machinery.ModuleSpec.name` as part of initialization.
430+
- If a single-phase module was previously imported under the
431+
same :py:attr:`~importlib.machinery.ModuleSpec.name` by this function
432+
or as a built-in module (for example, one registered with
433+
:c:func:`PyImport_AppendInittab`), Python may reuse the previous module's
434+
contents instead of calling *initfunc* again.
435+
- The module will be fully initialized by *initfunc*.
436+
Calling :c:func:`PyModule_Exec` on it will have no effect, though it is
437+
still recommended, in case the module later switches to
438+
:ref:`multi-phase initialization <multi-phase-initialization>`.
439+
- Also, if the *spec*'s :py:attr:`!name` contains dots, this name is used
440+
for prepending a parent package to the new module's
441+
:attr:`~module.__name__`.
442+
426443
.. versionadded:: 3.15

‎Doc/c-api/intro.rst‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,12 @@ Numeric utilities
299299
Argument must be a character or an integer in the range [-128, 127] or [0,
300300
255]. This macro returns ``c`` cast to an ``unsigned char``.
301301

302+
.. c:macro:: PY_BIG_ENDIAN
303+
PY_LITTLE_ENDIAN
304+
305+
Constants describing the byte order of the platform that Python was built
306+
for. Exactly one of them is ``1`` and the other is ``0``.
307+
302308

303309
Assertion utilities
304310
^^^^^^^^^^^^^^^^^^^
@@ -916,8 +922,13 @@ use them.
916922
917923
A signed integral type such that ``sizeof(Py_ssize_t) == sizeof(size_t)``.
918924
C99 doesn't define such a thing directly (size_t is an unsigned integral type).
919-
See :pep:`353` for details. ``PY_SSIZE_T_MAX`` is the largest positive value
920-
of type :c:type:`Py_ssize_t`.
925+
See :pep:`353` for details.
926+
927+
.. c:macro:: PY_SSIZE_T_MAX
928+
PY_SSIZE_T_MIN
929+
930+
The limit values (largest positive one and smallest negative one,
931+
respecitvely) of type :c:type:`Py_ssize_t`.
921932

922933

923934
.. _api-exceptions:

‎Doc/library/ctypes.rst‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3675,6 +3675,12 @@ fields, or any other data types containing pointer type fields.
36753675
36763676
point = Point(1, 2)
36773677
3678+
.. note::
3679+
3680+
Calling :func:`super` without arguments in methods of the decorated
3681+
class raises a :exc:`TypeError`. Use the two-argument form instead, for example
3682+
``super(Point, self).__init__(x, y)``.
3683+
36783684
*align*, *layout*, and *pack* supply the value for the :attr:`~ctypes.Structure._align_`,
36793685
:attr:`~ctypes.Structure._layout_`, and :attr:`~ctypes.Structure._pack_`
36803686
attributes, respectively.

‎Lib/bdb.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ def clear_all_file_breaks(self, filename):
747747
return 'There are no breakpoints in %s' % filename
748748
for line in self.breaks[filename]:
749749
blist = Breakpoint.bplist[filename, line]
750-
for bp in blist:
750+
for bp in blist[:]:
751751
bp.deleteMe()
752752
del self.breaks[filename]
753753
return None

‎Lib/test/test_bdb.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,17 @@ def main():
965965
with TracerRun(self) as tracer:
966966
tracer.runcall(tfunc_import)
967967

968+
def test_clear_all_file_breaks_same_line(self):
969+
reset_Breakpoint()
970+
self.addCleanup(reset_Breakpoint)
971+
debugger = Bdb()
972+
for _ in range(3):
973+
self.assertIsNone(debugger.set_break(__file__, 1))
974+
self.assertIsNone(debugger.clear_all_file_breaks(__file__))
975+
self.assertEqual(debugger.get_all_breaks(), {})
976+
self.assertEqual(_bdb.Breakpoint.bplist, {})
977+
self.assertTrue(all(bp is None for bp in _bdb.Breakpoint.bpbynumber))
978+
968979
def test_clear_at_no_bp(self):
969980
self.expect_set = [
970981
('line', 2, 'tfunc_import'), ('clear', (__file__, 1))

‎Lib/test/test_ctypes/test_simplesubclasses.py‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import unittest
2-
from ctypes import Structure, CFUNCTYPE, c_int, _SimpleCData
2+
from collections.abc import Hashable
3+
from ctypes import Structure, CFUNCTYPE, c_int, _SimpleCData, POINTER
34
from ._support import (_CData, PyCSimpleType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
45
Py_TPFLAGS_IMMUTABLETYPE)
56

@@ -26,6 +27,28 @@ def test_type_flags(self):
2627
self.assertTrue(_SimpleCData.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
2728
self.assertFalse(_SimpleCData.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
2829

30+
def test_unhashable(self):
31+
# gh-78327: CData objects are mutable and must not be hashable.
32+
class S(Structure):
33+
_fields_ = [("a", c_int)]
34+
35+
for cls in c_int, S, c_int * 2, POINTER(c_int), CFUNCTYPE(None):
36+
with self.subTest(cls=cls):
37+
self.assertIsNone(cls.__hash__)
38+
obj = cls()
39+
self.assertNotIsInstance(obj, Hashable)
40+
with self.assertRaisesRegex(TypeError,
41+
f"unhashable type: '{cls.__name__}'"):
42+
hash(obj)
43+
44+
# Subclasses can still opt in to hashing.
45+
class H(S):
46+
def __hash__(self):
47+
return 42
48+
49+
self.assertEqual(hash(H()), 42)
50+
self.assertIsInstance(H(), Hashable)
51+
2952
def test_metaclass_details(self):
3053
# Abstract classes (whose metaclass __init__ was not called) can't be
3154
# instantiated directly

‎Lib/test/test_embed.py‎

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -273,16 +273,27 @@ def test_create_module_from_initfunc(self):
273273
out, err = self.run_embedded_interpreter("test_create_module_from_initfunc")
274274
self.assertEqual(self._nogil_filtered_err(err, "embedded_ext"), "")
275275
self.assertEqual(out,
276-
"<module 'my_test_extension' (static-extension)>\n"
277-
"my_test_extension.executed='yes'\n"
278-
"my_test_extension.exec_slot_ran='yes'\n"
279-
"<module 'embedded_ext' (static-extension)>\n"
280-
"embedded_ext.executed='yes'\n"
281-
"<module 'sp_pkg.sp_submod' (static-extension)>\n"
282-
"sp_pkg.sp_submod.__name__='sp_pkg.sp_submod'\n"
283-
"sys.modules[\"sp_pkg.sp_submod\"] is sp_pkg.sp_submod=True\n"
284-
"\"sp_submod\" in sys.modules=False\n"
285-
)
276+
# multi-phase init: not in sys.modules until importlib adds it
277+
"created my_test_extension: in sys.modules=False\n"
278+
"<module 'my_test_extension' (static-extension)>\n"
279+
"my_test_extension.executed='yes'\n"
280+
"my_test_extension.exec_slot_ran='yes'\n"
281+
# single-phase init: added to sys.modules by the init function
282+
"created embedded_ext: in sys.modules=True\n"
283+
"<module 'embedded_ext' (static-extension)>\n"
284+
"embedded_ext.executed='yes'\n"
285+
# same name, different initfuncs: the cached module is
286+
# returned and the second initfunc is never called
287+
"a.which='A' b.which='A' a is b=True\n"
288+
"create_static_module.initfunc_calls()=(1, 0)\n"
289+
# Static extension
290+
"created sp_pkg: in sys.modules=False\n"
291+
"created sp_pkg.sp_submod: in sys.modules=True\n"
292+
"<module 'sp_pkg.sp_submod' (static-extension)>\n"
293+
"sp_pkg.sp_submod.__name__='sp_pkg.sp_submod'\n"
294+
"sys.modules[\"sp_pkg.sp_submod\"] is sp_pkg.sp_submod=True\n"
295+
"\"sp_submod\" in sys.modules=False\n"
296+
)
286297

287298
def test_inittab_submodule_multiphase(self):
288299
out, err = self.run_embedded_interpreter("test_inittab_submodule_multiphase")

0 commit comments

Comments
 (0)