From 1a68caa9050eca016a542f5b600d760b568cca56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
<10796600+picnixz@users.noreply.github.com>
Date: Thu, 8 May 2025 12:26:38 +0200
Subject: [PATCH 1/6] remove `PyImport_ImportModuleNoBlock`
---
Doc/c-api/import.rst | 13 -----------
Doc/data/refcounts.dat | 3 ---
Doc/data/stable_abi.dat | 1 -
.../c-api-pending-removal-in-3.15.rst | 2 --
Doc/whatsnew/3.15.rst | 2 ++
Include/import.h | 3 ---
Lib/test/test_capi/test_import.py | 9 --------
Lib/test/test_stable_abi_ctypes.py | 1 -
...-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst | 2 ++
Misc/stable_abi.toml | 2 --
Modules/_testlimitedcapi/import.c | 18 ---------------
PC/python3dll.c | 1 -
Python/import.c | 22 -------------------
13 files changed, 4 insertions(+), 75 deletions(-)
create mode 100644 Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst
diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst
index 1cab3ce3061ec9..8eabc0406b11ce 100644
--- a/Doc/c-api/import.rst
+++ b/Doc/c-api/import.rst
@@ -16,19 +16,6 @@ Importing Modules
This is a wrapper around :c:func:`PyImport_Import()` which takes a
:c:expr:`const char *` as an argument instead of a :c:expr:`PyObject *`.
-.. c:function:: PyObject* PyImport_ImportModuleNoBlock(const char *name)
-
- This function is a deprecated alias of :c:func:`PyImport_ImportModule`.
-
- .. versionchanged:: 3.3
- This function used to fail immediately when the import lock was held
- by another thread. In Python 3.3 though, the locking scheme switched
- to per-module locks for most purposes, so this function's special
- behaviour isn't needed anymore.
-
- .. deprecated-removed:: 3.13 3.15
- Use :c:func:`PyImport_ImportModule` instead.
-
.. c:function:: PyObject* PyImport_ImportModuleEx(const char *name, PyObject *globals, PyObject *locals, PyObject *fromlist)
diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat
index ca99b9e6d37141..14990bee6e4f23 100644
--- a/Doc/data/refcounts.dat
+++ b/Doc/data/refcounts.dat
@@ -1093,9 +1093,6 @@ PyImport_ImportModuleLevelObject:PyObject*:locals:0:???
PyImport_ImportModuleLevelObject:PyObject*:fromlist:0:???
PyImport_ImportModuleLevelObject:int:level::
-PyImport_ImportModuleNoBlock:PyObject*::+1:
-PyImport_ImportModuleNoBlock:const char*:name::
-
PyImport_ReloadModule:PyObject*::+1:
PyImport_ReloadModule:PyObject*:m:0:
diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat
index 3d68487d07baf2..a8658d8b80e294 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -323,7 +323,6 @@ func,PyImport_ImportFrozenModuleObject,3.7,,
func,PyImport_ImportModule,3.2,,
func,PyImport_ImportModuleLevel,3.2,,
func,PyImport_ImportModuleLevelObject,3.7,,
-func,PyImport_ImportModuleNoBlock,3.2,,
func,PyImport_ReloadModule,3.2,,
func,PyIndex_Check,3.8,,
type,PyInterpreterState,3.2,,opaque
diff --git a/Doc/deprecations/c-api-pending-removal-in-3.15.rst b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
index a5cc8f1d5b3475..50c1d42683acd7 100644
--- a/Doc/deprecations/c-api-pending-removal-in-3.15.rst
+++ b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
@@ -2,8 +2,6 @@ Pending removal in Python 3.15
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* The bundled copy of ``libmpdecimal``.
-* The :c:func:`PyImport_ImportModuleNoBlock`:
- Use :c:func:`PyImport_ImportModule` instead.
* :c:func:`PyWeakref_GetObject` and :c:func:`PyWeakref_GET_OBJECT`:
Use :c:func:`PyWeakref_GetRef` instead. The `pythoncapi-compat project
`__ can be used to get
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index 5e9922069aa42c..41c7a10b72acab 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -155,3 +155,5 @@ Deprecated C APIs
Removed C APIs
--------------
+* :c:func:`!PyImport_ImportModuleNoBlock`: use :c:func:`PyImport_ImportModule`
+ instead.
diff --git a/Include/import.h b/Include/import.h
index 24b23b9119196f..d91ebe96ca868d 100644
--- a/Include/import.h
+++ b/Include/import.h
@@ -51,9 +51,6 @@ PyAPI_FUNC(PyObject *) PyImport_AddModuleRef(
PyAPI_FUNC(PyObject *) PyImport_ImportModule(
const char *name /* UTF-8 encoded string */
);
-Py_DEPRECATED(3.13) PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(
- const char *name /* UTF-8 encoded string */
- );
PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(
const char *name, /* UTF-8 encoded string */
PyObject *globals,
diff --git a/Lib/test/test_capi/test_import.py b/Lib/test/test_capi/test_import.py
index 25136624ca4ed9..3a1595790d4415 100644
--- a/Lib/test/test_capi/test_import.py
+++ b/Lib/test/test_capi/test_import.py
@@ -133,15 +133,6 @@ def test_importmodule(self):
self.assertRaises(UnicodeDecodeError, importmodule, b'\xff')
# CRASHES importmodule(NULL)
- def test_importmodulenoblock(self):
- # Test deprecated PyImport_ImportModuleNoBlock()
- importmodulenoblock = _testlimitedcapi.PyImport_ImportModuleNoBlock
- with check_warnings(('', DeprecationWarning)):
- self.check_import_func(importmodulenoblock)
- self.assertRaises(UnicodeDecodeError, importmodulenoblock, b'\xff')
-
- # CRASHES importmodulenoblock(NULL)
-
def check_frozen_import(self, import_frozen_module):
# Importing a frozen module executes its code, so start by unloading
# the module to execute the code in a new (temporary) module.
diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py
index 1e6f69d49e9335..3ac62c46207de7 100644
--- a/Lib/test/test_stable_abi_ctypes.py
+++ b/Lib/test/test_stable_abi_ctypes.py
@@ -360,7 +360,6 @@ def test_windows_feature_macros(self):
"PyImport_ImportModule",
"PyImport_ImportModuleLevel",
"PyImport_ImportModuleLevelObject",
- "PyImport_ImportModuleNoBlock",
"PyImport_ReloadModule",
"PyIndex_Check",
"PyInterpreterState_Clear",
diff --git a/Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst b/Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst
new file mode 100644
index 00000000000000..3a4e8209cfe574
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst
@@ -0,0 +1,2 @@
+Remove deprecated :c:func:`!PyImport_ImportModuleNoBlock`. Use
+:c:func:`PyImport_ImportModule` instead. Patch by Bénédikt Tran.
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index d3e1f0db057023..e6b7f4bd074d40 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -886,8 +886,6 @@
added = '3.2'
[function.PyImport_ImportModuleLevel]
added = '3.2'
-[function.PyImport_ImportModuleNoBlock]
- added = '3.2'
[function.PyImport_ReloadModule]
added = '3.2'
[function.PyInterpreterState_Clear]
diff --git a/Modules/_testlimitedcapi/import.c b/Modules/_testlimitedcapi/import.c
index 3707dbedeea0d9..91c2de224891f2 100644
--- a/Modules/_testlimitedcapi/import.c
+++ b/Modules/_testlimitedcapi/import.c
@@ -108,23 +108,6 @@ pyimport_importmodule(PyObject *Py_UNUSED(module), PyObject *args)
}
-/* Test PyImport_ImportModuleNoBlock() */
-static PyObject *
-pyimport_importmodulenoblock(PyObject *Py_UNUSED(module), PyObject *args)
-{
- const char *name;
- Py_ssize_t size;
- if (!PyArg_ParseTuple(args, "z#", &name, &size)) {
- return NULL;
- }
-
- _Py_COMP_DIAG_PUSH
- _Py_COMP_DIAG_IGNORE_DEPR_DECLS
- return PyImport_ImportModuleNoBlock(name);
- _Py_COMP_DIAG_POP
-}
-
-
/* Test PyImport_ImportModuleEx() */
static PyObject *
pyimport_importmoduleex(PyObject *Py_UNUSED(module), PyObject *args)
@@ -285,7 +268,6 @@ static PyMethodDef test_methods[] = {
{"PyImport_AddModuleRef", pyimport_addmoduleref, METH_VARARGS},
{"PyImport_Import", pyimport_import, METH_O},
{"PyImport_ImportModule", pyimport_importmodule, METH_VARARGS},
- {"PyImport_ImportModuleNoBlock", pyimport_importmodulenoblock, METH_VARARGS},
{"PyImport_ImportModuleEx", pyimport_importmoduleex, METH_VARARGS},
{"PyImport_ImportModuleLevel", pyimport_importmodulelevel, METH_VARARGS},
{"PyImport_ImportModuleLevelObject", pyimport_importmodulelevelobject, METH_VARARGS},
diff --git a/PC/python3dll.c b/PC/python3dll.c
index f0c578e11c643b..5424ae8242836e 100755
--- a/PC/python3dll.c
+++ b/PC/python3dll.c
@@ -318,7 +318,6 @@ EXPORT_FUNC(PyImport_ImportFrozenModuleObject)
EXPORT_FUNC(PyImport_ImportModule)
EXPORT_FUNC(PyImport_ImportModuleLevel)
EXPORT_FUNC(PyImport_ImportModuleLevelObject)
-EXPORT_FUNC(PyImport_ImportModuleNoBlock)
EXPORT_FUNC(PyImport_ReloadModule)
EXPORT_FUNC(PyIndex_Check)
EXPORT_FUNC(PyInterpreterState_Clear)
diff --git a/Python/import.c b/Python/import.c
index afdc28eda31b9b..28447400522708 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -3426,28 +3426,6 @@ PyImport_ImportModule(const char *name)
}
-/* Import a module without blocking
- *
- * At first it tries to fetch the module from sys.modules. If the module was
- * never loaded before it loads it with PyImport_ImportModule() unless another
- * thread holds the import lock. In the latter case the function raises an
- * ImportError instead of blocking.
- *
- * Returns the module object with incremented ref count.
- */
-PyObject *
-PyImport_ImportModuleNoBlock(const char *name)
-{
- if (PyErr_WarnEx(PyExc_DeprecationWarning,
- "PyImport_ImportModuleNoBlock() is deprecated and scheduled for "
- "removal in Python 3.15. Use PyImport_ImportModule() instead.", 1))
- {
- return NULL;
- }
- return PyImport_ImportModule(name);
-}
-
-
/* Remove importlib frames from the traceback,
* except in Verbose mode. */
static void
From 11b6f079a7e255ccf479f63b6e2f805ec9d7e4e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
<10796600+picnixz@users.noreply.github.com>
Date: Thu, 8 May 2025 12:35:09 +0200
Subject: [PATCH 2/6] update refs
---
Doc/whatsnew/2.6.rst | 2 +-
Doc/whatsnew/3.0.rst | 2 +-
Doc/whatsnew/3.13.rst | 2 +-
Doc/whatsnew/3.3.rst | 2 +-
Misc/NEWS.d/3.11.0a4.rst | 2 +-
Misc/NEWS.d/3.13.0a1.rst | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst
index 9dbc07a34e20a1..0803eba99e6d17 100644
--- a/Doc/whatsnew/2.6.rst
+++ b/Doc/whatsnew/2.6.rst
@@ -3043,7 +3043,7 @@ Changes to Python's build process and to the C API include:
* Importing modules simultaneously in two different threads no longer
deadlocks; it will now raise an :exc:`ImportError`. A new API
- function, :c:func:`PyImport_ImportModuleNoBlock`, will look for a
+ function, :c:func:`!PyImport_ImportModuleNoBlock`, will look for a
module in ``sys.modules`` first, then try to import it after
acquiring an import lock. If the import lock is held by another
thread, an :exc:`ImportError` is raised.
diff --git a/Doc/whatsnew/3.0.rst b/Doc/whatsnew/3.0.rst
index 6e1fda22ed203a..d858586138e9ae 100644
--- a/Doc/whatsnew/3.0.rst
+++ b/Doc/whatsnew/3.0.rst
@@ -870,7 +870,7 @@ to the C API.
* :c:func:`!PyNumber_Coerce`, :c:func:`!PyNumber_CoerceEx`,
:c:func:`!PyMember_Get`, and :c:func:`!PyMember_Set` C APIs are removed.
-* New C API :c:func:`PyImport_ImportModuleNoBlock`, works like
+* New C API :c:func:`!PyImport_ImportModuleNoBlock`, works like
:c:func:`PyImport_ImportModule` but won't block on the import lock
(returning an error instead).
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index e20e49325c01d5..ff33224e272c67 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -2499,7 +2499,7 @@ Deprecated C APIs
which return a :term:`borrowed reference`.
(Soft deprecated as part of :pep:`667`.)
-* Deprecate the :c:func:`PyImport_ImportModuleNoBlock` function,
+* Deprecate the :c:func:`!PyImport_ImportModuleNoBlock` function,
which is just an alias to :c:func:`PyImport_ImportModule` since Python 3.3.
(Contributed by Victor Stinner in :gh:`105396`.)
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index 7a8eb47cbdb354..89fd68686454e2 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -829,7 +829,7 @@ Previous versions of CPython have always relied on a global import lock.
This led to unexpected annoyances, such as deadlocks when importing a module
would trigger code execution in a different thread as a side-effect.
Clumsy workarounds were sometimes employed, such as the
-:c:func:`PyImport_ImportModuleNoBlock` C API function.
+:c:func:`!PyImport_ImportModuleNoBlock` C API function.
In Python 3.3, importing a module takes a per-module lock. This correctly
serializes importation of a given module from multiple threads (preventing
diff --git a/Misc/NEWS.d/3.11.0a4.rst b/Misc/NEWS.d/3.11.0a4.rst
index a2d36202045887..47cbf33c3bb29b 100644
--- a/Misc/NEWS.d/3.11.0a4.rst
+++ b/Misc/NEWS.d/3.11.0a4.rst
@@ -1161,7 +1161,7 @@ no-op now.
.. nonce: Lq2_gR
.. section: C API
-Replaced deprecated usage of :c:func:`PyImport_ImportModuleNoBlock` with
+Replaced deprecated usage of :c:func:`!PyImport_ImportModuleNoBlock` with
:c:func:`PyImport_ImportModule` in stdlib modules. Patch by Kumar Aditya.
..
diff --git a/Misc/NEWS.d/3.13.0a1.rst b/Misc/NEWS.d/3.13.0a1.rst
index 91e9fee7e37437..6149b33b076066 100644
--- a/Misc/NEWS.d/3.13.0a1.rst
+++ b/Misc/NEWS.d/3.13.0a1.rst
@@ -6538,7 +6538,7 @@ to hide implementation details. Patch by Victor Stinner.
.. nonce: FQJG5B
.. section: C API
-Deprecate the :c:func:`PyImport_ImportModuleNoBlock` function which is just
+Deprecate the :c:func:`!PyImport_ImportModuleNoBlock` function which is just
an alias to :c:func:`PyImport_ImportModule` since Python 3.3. Patch by
Victor Stinner.
From 8b7a020dffb810e06e3d9662bab2c23109f63ccf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
<10796600+picnixz@users.noreply.github.com>
Date: Thu, 8 May 2025 13:42:41 +0200
Subject: [PATCH 3/6] restore file
---
Doc/deprecations/c-api-pending-removal-in-3.15.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Doc/deprecations/c-api-pending-removal-in-3.15.rst b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
index 50c1d42683acd7..a391566c82c2f1 100644
--- a/Doc/deprecations/c-api-pending-removal-in-3.15.rst
+++ b/Doc/deprecations/c-api-pending-removal-in-3.15.rst
@@ -2,6 +2,8 @@ Pending removal in Python 3.15
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* The bundled copy of ``libmpdecimal``.
+* The :c:func:`!PyImport_ImportModuleNoBlock`:
+ Use :c:func:`PyImport_ImportModule` instead.
* :c:func:`PyWeakref_GetObject` and :c:func:`PyWeakref_GET_OBJECT`:
Use :c:func:`PyWeakref_GetRef` instead. The `pythoncapi-compat project
`__ can be used to get
From a4c7ca39846d3e6b029b1b07cd29616c098c679c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
<10796600+picnixz@users.noreply.github.com>
Date: Thu, 8 May 2025 14:27:34 +0200
Subject: [PATCH 4/6] restore stable ABI symbols
---
Lib/test/test_capi/test_import.py | 9 +++++++++
Lib/test/test_stable_abi_ctypes.py | 1 +
Misc/stable_abi.toml | 3 +++
Modules/_testlimitedcapi/import.c | 16 ++++++++++++++++
PC/python3dll.c | 1 +
Python/import.c | 24 ++++++++++++++++++++++++
6 files changed, 54 insertions(+)
diff --git a/Lib/test/test_capi/test_import.py b/Lib/test/test_capi/test_import.py
index 3a1595790d4415..57e0316fda8a52 100644
--- a/Lib/test/test_capi/test_import.py
+++ b/Lib/test/test_capi/test_import.py
@@ -133,6 +133,15 @@ def test_importmodule(self):
self.assertRaises(UnicodeDecodeError, importmodule, b'\xff')
# CRASHES importmodule(NULL)
+ def test_importmodulenoblock(self):
+ # Test deprecated (stable ABI only) PyImport_ImportModuleNoBlock()
+ importmodulenoblock = _testlimitedcapi.PyImport_ImportModuleNoBlock
+ with check_warnings(('', DeprecationWarning)):
+ self.check_import_func(importmodulenoblock)
+ self.assertRaises(UnicodeDecodeError, importmodulenoblock, b'\xff')
+
+ # CRASHES importmodulenoblock(NULL)
+
def check_frozen_import(self, import_frozen_module):
# Importing a frozen module executes its code, so start by unloading
# the module to execute the code in a new (temporary) module.
diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py
index 3ac62c46207de7..1e6f69d49e9335 100644
--- a/Lib/test/test_stable_abi_ctypes.py
+++ b/Lib/test/test_stable_abi_ctypes.py
@@ -360,6 +360,7 @@ def test_windows_feature_macros(self):
"PyImport_ImportModule",
"PyImport_ImportModuleLevel",
"PyImport_ImportModuleLevelObject",
+ "PyImport_ImportModuleNoBlock",
"PyImport_ReloadModule",
"PyIndex_Check",
"PyInterpreterState_Clear",
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index e6b7f4bd074d40..886979139ee8a6 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -886,6 +886,9 @@
added = '3.2'
[function.PyImport_ImportModuleLevel]
added = '3.2'
+[function.PyImport_ImportModuleNoBlock]
+ added = '3.2'
+ abi_only = true
[function.PyImport_ReloadModule]
added = '3.2'
[function.PyInterpreterState_Clear]
diff --git a/Modules/_testlimitedcapi/import.c b/Modules/_testlimitedcapi/import.c
index 91c2de224891f2..ce6cbb9d4b5495 100644
--- a/Modules/_testlimitedcapi/import.c
+++ b/Modules/_testlimitedcapi/import.c
@@ -108,6 +108,21 @@ pyimport_importmodule(PyObject *Py_UNUSED(module), PyObject *args)
}
+/* Test PyImport_ImportModuleNoBlock() */
+static PyObject *
+pyimport_importmodulenoblock(PyObject *Py_UNUSED(module), PyObject *args)
+{
+ extern PyObject *PyImport_ImportModuleNoBlock(const char *name);
+
+ const char *name;
+ Py_ssize_t size;
+ if (!PyArg_ParseTuple(args, "z#", &name, &size)) {
+ return NULL;
+ }
+ return PyImport_ImportModuleNoBlock(name);
+}
+
+
/* Test PyImport_ImportModuleEx() */
static PyObject *
pyimport_importmoduleex(PyObject *Py_UNUSED(module), PyObject *args)
@@ -268,6 +283,7 @@ static PyMethodDef test_methods[] = {
{"PyImport_AddModuleRef", pyimport_addmoduleref, METH_VARARGS},
{"PyImport_Import", pyimport_import, METH_O},
{"PyImport_ImportModule", pyimport_importmodule, METH_VARARGS},
+ {"PyImport_ImportModuleNoBlock", pyimport_importmodulenoblock, METH_VARARGS},
{"PyImport_ImportModuleEx", pyimport_importmoduleex, METH_VARARGS},
{"PyImport_ImportModuleLevel", pyimport_importmodulelevel, METH_VARARGS},
{"PyImport_ImportModuleLevelObject", pyimport_importmodulelevelobject, METH_VARARGS},
diff --git a/PC/python3dll.c b/PC/python3dll.c
index 5424ae8242836e..f0c578e11c643b 100755
--- a/PC/python3dll.c
+++ b/PC/python3dll.c
@@ -318,6 +318,7 @@ EXPORT_FUNC(PyImport_ImportFrozenModuleObject)
EXPORT_FUNC(PyImport_ImportModule)
EXPORT_FUNC(PyImport_ImportModuleLevel)
EXPORT_FUNC(PyImport_ImportModuleLevelObject)
+EXPORT_FUNC(PyImport_ImportModuleNoBlock)
EXPORT_FUNC(PyImport_ReloadModule)
EXPORT_FUNC(PyIndex_Check)
EXPORT_FUNC(PyInterpreterState_Clear)
diff --git a/Python/import.c b/Python/import.c
index 28447400522708..9dec0f488a3b90 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -3426,6 +3426,30 @@ PyImport_ImportModule(const char *name)
}
+/* Import a module without blocking
+ *
+ * At first it tries to fetch the module from sys.modules. If the module was
+ * never loaded before it loads it with PyImport_ImportModule() unless another
+ * thread holds the import lock. In the latter case the function raises an
+ * ImportError instead of blocking.
+ *
+ * Returns the module object with incremented ref count.
+ *
+ * Removed in 3.15, but kept for stable ABI compatibility.
+ */
+PyAPI_FUNC(PyObject *)
+PyImport_ImportModuleNoBlock(const char *name)
+{
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "PyImport_ImportModuleNoBlock() is deprecated and scheduled for "
+ "removal in Python 3.15. Use PyImport_ImportModule() instead.", 1))
+ {
+ return NULL;
+ }
+ return PyImport_ImportModule(name);
+}
+
+
/* Remove importlib frames from the traceback,
* except in Verbose mode. */
static void
From 87697cf45bddb4ade535fc4943ad9831d39dd007 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
<10796600+picnixz@users.noreply.github.com>
Date: Thu, 8 May 2025 14:37:27 +0200
Subject: [PATCH 5/6] update ABI imports
---
Modules/_testlimitedcapi/import.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Modules/_testlimitedcapi/import.c b/Modules/_testlimitedcapi/import.c
index ce6cbb9d4b5495..f85daee57d712e 100644
--- a/Modules/_testlimitedcapi/import.c
+++ b/Modules/_testlimitedcapi/import.c
@@ -108,11 +108,12 @@ pyimport_importmodule(PyObject *Py_UNUSED(module), PyObject *args)
}
-/* Test PyImport_ImportModuleNoBlock() */
+/* Test PyImport_ImportModuleNoBlock() (removed in 3.15) */
static PyObject *
pyimport_importmodulenoblock(PyObject *Py_UNUSED(module), PyObject *args)
{
- extern PyObject *PyImport_ImportModuleNoBlock(const char *name);
+ // Get the function from the stable ABI.
+ PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *name);
const char *name;
Py_ssize_t size;
From 07a28c946adc51f27f97083de0995fc7d81a6ea9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
<10796600+picnixz@users.noreply.github.com>
Date: Thu, 8 May 2025 14:40:28 +0200
Subject: [PATCH 6/6] update docs
---
Doc/whatsnew/3.15.rst | 4 ++--
.../next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index 41c7a10b72acab..29fb492e530b29 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -155,5 +155,5 @@ Deprecated C APIs
Removed C APIs
--------------
-* :c:func:`!PyImport_ImportModuleNoBlock`: use :c:func:`PyImport_ImportModule`
- instead.
+* :c:func:`!PyImport_ImportModuleNoBlock`: deprecated alias
+ of :c:func:`PyImport_ImportModule`.
diff --git a/Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst b/Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst
index 3a4e8209cfe574..9569456eb760c2 100644
--- a/Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst
+++ b/Misc/NEWS.d/next/C_API/2025-05-08-12-25-47.gh-issue-133644.Yb86Rm.rst
@@ -1,2 +1,2 @@
-Remove deprecated :c:func:`!PyImport_ImportModuleNoBlock`. Use
-:c:func:`PyImport_ImportModule` instead. Patch by Bénédikt Tran.
+Remove deprecated alias :c:func:`!PyImport_ImportModuleNoBlock` of
+:c:func:`PyImport_ImportModule`. Patch by Bénédikt Tran.