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..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,7 +2,7 @@ Pending removal in Python 3.15 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The bundled copy of ``libmpdecimal``. -* The :c:func:`PyImport_ImportModuleNoBlock`: +* 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 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.15.rst b/Doc/whatsnew/3.15.rst index 5e9922069aa42c..29fb492e530b29 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`: deprecated alias + of :c:func:`PyImport_ImportModule`. 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/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..57e0316fda8a52 100644 --- a/Lib/test/test_capi/test_import.py +++ b/Lib/test/test_capi/test_import.py @@ -134,7 +134,7 @@ def test_importmodule(self): # CRASHES importmodule(NULL) def test_importmodulenoblock(self): - # Test deprecated PyImport_ImportModuleNoBlock() + # Test deprecated (stable ABI only) PyImport_ImportModuleNoBlock() importmodulenoblock = _testlimitedcapi.PyImport_ImportModuleNoBlock with check_warnings(('', DeprecationWarning)): self.check_import_func(importmodulenoblock) 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. 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..9569456eb760c2 --- /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 alias :c:func:`!PyImport_ImportModuleNoBlock` of +:c:func:`PyImport_ImportModule`. Patch by Bénédikt Tran. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index d3e1f0db057023..886979139ee8a6 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -888,6 +888,7 @@ 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 3707dbedeea0d9..f85daee57d712e 100644 --- a/Modules/_testlimitedcapi/import.c +++ b/Modules/_testlimitedcapi/import.c @@ -108,20 +108,19 @@ 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) { + // Get the function from the stable ABI. + PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *name); + 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 } diff --git a/Python/import.c b/Python/import.c index afdc28eda31b9b..9dec0f488a3b90 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3434,8 +3434,10 @@ PyImport_ImportModule(const char *name) * ImportError instead of blocking. * * Returns the module object with incremented ref count. + * + * Removed in 3.15, but kept for stable ABI compatibility. */ -PyObject * +PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *name) { if (PyErr_WarnEx(PyExc_DeprecationWarning,