From 91fd216cd12c3e8a45d70a768de0f949fd5fa38e Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Tue, 5 May 2026 01:36:15 +0100 Subject: [PATCH 1/2] gh-149321: Remove lazy_imports=none startup mode --- Doc/c-api/import.rst | 5 - Doc/library/sys.rst | 4 - Doc/reference/simple_stmts.rst | 4 - Doc/using/cmdline.rst | 14 +- Doc/whatsnew/3.15.rst | 9 +- Include/import.h | 3 +- Lib/test/test_lazy_import/__init__.py | 152 +++--------------- Lib/test/test_lazy_import/data/global_off.py | 5 - Misc/NEWS.d/3.15.0a8.rst | 10 -- ...-issue-149321.remove-lazy-imports-none.rst | 1 + ...-05-03-12-00-00.gh-issue-149321.fUaxrz.rst | 3 +- Modules/_testcapi/import.c | 4 - Python/ceval.c | 5 +- Python/clinic/sysmodule.c.h | 4 +- Python/initconfig.c | 15 +- Python/pylifecycle.c | 14 +- Python/sysmodule.c | 15 +- 17 files changed, 53 insertions(+), 214 deletions(-) delete mode 100644 Lib/test/test_lazy_import/data/global_off.py create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-05-05-12-00-00.gh-issue-149321.remove-lazy-imports-none.rst diff --git a/Doc/c-api/import.rst b/Doc/c-api/import.rst index e2d363b911a87c..ec9462931d56c2 100644 --- a/Doc/c-api/import.rst +++ b/Doc/c-api/import.rst @@ -393,11 +393,6 @@ Importing Modules Make all imports lazy by default. - .. c:enumerator:: PyImport_LAZY_NONE - - Disable lazy imports entirely. Even explicit ``lazy`` statements become - eager imports. - .. versionadded:: 3.15 .. c:function:: PyObject* PyImport_CreateModuleFromInitfunc(PyObject *spec, PyObject* (*initfunc)(void)) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 6946eb6eeaa5fa..c47fe8898e53dd 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -919,8 +919,6 @@ always available. Unless explicitly noted otherwise, all variables are read-only * ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword are lazy * ``"all"``: All top-level imports are potentially lazy - * ``"none"``: All lazy imports are suppressed (even explicitly marked - ones) See also :func:`set_lazy_imports` and :pep:`810`. @@ -1757,8 +1755,6 @@ always available. Unless explicitly noted otherwise, all variables are read-only * ``"normal"``: Only imports explicitly marked with the ``lazy`` keyword are lazy * ``"all"``: All top-level imports become potentially lazy - * ``"none"``: All lazy imports are suppressed (even explicitly marked - ones) This function is intended for advanced users who need to control lazy imports across their entire application. Library developers should diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index f8e54aa0a108c8..0f134604b5d922 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -965,10 +965,6 @@ Imports inside functions, class bodies, or :keyword:`try`/:keyword:`except`/:keyword:`finally` blocks are always eager, regardless of :attr:`!__lazy_modules__`. -Setting ``-X lazy_imports=none`` (or the :envvar:`PYTHON_LAZY_IMPORTS` -environment variable to ``none``) overrides :attr:`!__lazy_modules__` and -forces all imports to be eager. - .. versionadded:: 3.15 .. _future: diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 7cbc03f5f1281e..794f0b7b4f72ab 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -705,10 +705,9 @@ Miscellaneous options .. versionadded:: 3.14 - * :samp:`-X lazy_imports={all,none,normal}` controls lazy import behavior. - ``all`` makes all imports lazy by default, ``none`` disables lazy imports - entirely (even explicit ``lazy`` statements become eager), and ``normal`` - (the default) respects the ``lazy`` keyword in source code. + * :samp:`-X lazy_imports={all,normal}` controls lazy import behavior. + ``all`` makes all imports lazy by default, and ``normal`` (the default) + respects the ``lazy`` keyword in source code. See also :envvar:`PYTHON_LAZY_IMPORTS`. .. versionadded:: 3.15 @@ -1416,10 +1415,9 @@ conflict. .. envvar:: PYTHON_LAZY_IMPORTS - Controls lazy import behavior. Accepts three values: ``all`` makes all - imports lazy by default, ``none`` disables lazy imports entirely (even - explicit ``lazy`` statements become eager), and ``normal`` (the default) - respects the ``lazy`` keyword in source code. + Controls lazy import behavior. Accepts two values: ``all`` makes all + imports lazy by default, and ``normal`` (the default) respects the + ``lazy`` keyword in source code. See also the :option:`-X lazy_imports <-X>` command-line option. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 7f12cc04a460d4..4cf89f9d477f02 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -151,11 +151,10 @@ making it straightforward to diagnose and debug the failure. For cases where you want to enable lazy loading globally without modifying source code, Python provides the :option:`-X lazy_imports <-X>` command-line option and the :envvar:`PYTHON_LAZY_IMPORTS` environment variable. Both -accept three values: ``all`` makes all imports lazy by default, ``none`` -disables lazy imports entirely (even explicit ``lazy`` statements become -eager), and ``normal`` (the default) respects the ``lazy`` keyword in source -code. The :func:`sys.set_lazy_imports` and :func:`sys.get_lazy_imports` -functions allow changing and querying this mode at runtime. +accept two values: ``all`` makes all imports lazy by default, and ``normal`` +(the default) respects the ``lazy`` keyword in source code. The +:func:`sys.set_lazy_imports` and :func:`sys.get_lazy_imports` functions allow +changing and querying this mode at runtime. For more selective control, :func:`sys.set_lazy_imports_filter` accepts a callable that determines whether a specific module should be loaded lazily. diff --git a/Include/import.h b/Include/import.h index 6f1c13787b8569..c062e46bff46bf 100644 --- a/Include/import.h +++ b/Include/import.h @@ -90,8 +90,7 @@ PyAPI_FUNC(int) PyImport_AppendInittab( typedef enum { PyImport_LAZY_NORMAL, - PyImport_LAZY_ALL, - PyImport_LAZY_NONE + PyImport_LAZY_ALL } PyImport_LazyImportsMode; #ifndef Py_LIMITED_API diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 1d1d2e00bd733f..b697db7be64a96 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -100,10 +100,10 @@ def tearDown(self): sys.set_lazy_imports_filter(None) sys.set_lazy_imports("normal") - def test_global_off(self): - """Mode 'none' should disable lazy imports entirely.""" - import test.test_lazy_import.data.global_off - self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + def test_global_off_rejected(self): + """Mode 'none' is not supported.""" + with self.assertRaises(ValueError): + sys.set_lazy_imports("none") def test_global_on(self): """Mode 'all' should make regular imports lazy.""" @@ -468,9 +468,6 @@ def test_get_lazy_imports_returns_string(self): sys.set_lazy_imports("all") self.assertEqual(sys.get_lazy_imports(), "all") - sys.set_lazy_imports("none") - self.assertEqual(sys.get_lazy_imports(), "none") - def test_get_lazy_imports_filter_default(self): """get_lazy_imports_filter should return None by default.""" sys.set_lazy_imports_filter(None) @@ -1015,68 +1012,16 @@ def test_cli_lazy_imports_all_makes_regular_imports_lazy(self): self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") self.assertIn("LAZY", result.stdout) - def test_cli_lazy_imports_none_forces_all_imports_eager(self): - """-X lazy_imports=none should force all imports to be eager.""" - code = textwrap.dedent(""" - import sys - # Even explicit lazy imports should be eager in 'none' mode - lazy import json - if 'json' in sys.modules: - print("EAGER") - else: - print("LAZY") - """) + def test_cli_lazy_imports_none_is_rejected(self): + """-X lazy_imports=none should be rejected.""" result = subprocess.run( - [sys.executable, "-X", "lazy_imports=none", "-c", code], + [sys.executable, "-X", "lazy_imports=none", "-c", "pass"], capture_output=True, text=True ) - self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") - self.assertIn("EAGER", result.stdout) - - @support.requires_resource("cpu") - def test_cli_lazy_imports_modes_import_stdlib_modules(self): - """-X lazy_imports modes should import available stdlib modules.""" - # Do not smoke-test modules with intentional import-time effects. - import_side_effect_modules = {"antigravity", "this"} - importable = [] - - for module in sorted(sys.stdlib_module_names): - if module in import_side_effect_modules: - continue - - with self.subTest(module=module): - code = f"import {module}; print({module})" - baseline = subprocess.run( - [sys.executable, "-I", "-c", code], - capture_output=True, - text=True, - timeout=60, - ) - if baseline.returncode: - # sys.stdlib_module_names includes modules for other - # platforms and optional extension modules not built here. - continue - importable.append(module) - - for mode in ("normal", "none"): - with self.subTest(module=module, mode=mode): - result = subprocess.run( - [ - sys.executable, - "-I", - "-X", - f"lazy_imports={mode}", - "-c", - code, - ], - capture_output=True, - text=True, - timeout=60, - ) - self.assertEqual(result.returncode, 0, result.stderr) - - self.assertGreater(len(importable), 100) + self.assertNotEqual(result.returncode, 0) + self.assertIn("-X lazy_imports: invalid value", result.stderr) + self.assertIn("expected 'all' or 'normal'", result.stderr) def test_cli_lazy_imports_normal_respects_lazy_keyword_only(self): """-X lazy_imports=normal should respect lazy keyword only.""" @@ -1125,77 +1070,27 @@ def test_env_var_lazy_imports_all_enables_global_lazy(self): self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") self.assertIn("LAZY", result.stdout) - def test_env_var_lazy_imports_none_disables_all_lazy(self): - """PYTHON_LAZY_IMPORTS=none should disable all lazy imports.""" - code = textwrap.dedent(""" - import sys - lazy import json - if 'json' in sys.modules: - print("EAGER") - else: - print("LAZY") - """) + def test_env_var_lazy_imports_none_is_rejected(self): + """PYTHON_LAZY_IMPORTS=none should be rejected.""" import os env = os.environ.copy() env["PYTHON_LAZY_IMPORTS"] = "none" result = subprocess.run( - [sys.executable, "-c", code], + [sys.executable, "-c", "pass"], capture_output=True, text=True, env=env ) - self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") - self.assertIn("EAGER", result.stdout) - - def test_cli_lazy_imports_none_disables_dunder_lazy_modules(self): - """-X lazy_imports=none should override __lazy_modules__.""" - code = textwrap.dedent(""" - import sys - __lazy_modules__ = ["json"] - import json - if 'json' in sys.modules: - print("EAGER") - else: - print("LAZY") - """) - result = subprocess.run( - [sys.executable, "-X", "lazy_imports=none", "-c", code], - capture_output=True, - text=True, - ) - self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") - self.assertIn("EAGER", result.stdout) - - def test_env_var_lazy_imports_none_disables_dunder_lazy_modules(self): - """PYTHON_LAZY_IMPORTS=none should override __lazy_modules__.""" - code = textwrap.dedent(""" - import sys - __lazy_modules__ = ["json"] - import json - if 'json' in sys.modules: - print("EAGER") - else: - print("LAZY") - """) - import os - - env = os.environ.copy() - env["PYTHON_LAZY_IMPORTS"] = "none" - result = subprocess.run( - [sys.executable, "-c", code], - capture_output=True, - text=True, - env=env, - ) - self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") - self.assertIn("EAGER", result.stdout) + self.assertNotEqual(result.returncode, 0) + self.assertIn("PYTHON_LAZY_IMPORTS: invalid value", result.stderr) + self.assertIn("expected 'all' or 'normal'", result.stderr) def test_cli_overrides_env_var(self): """Command-line option should take precedence over environment variable.""" # PEP 810: -X lazy_imports takes precedence over PYTHON_LAZY_IMPORTS code = textwrap.dedent(""" import sys - lazy import json + import json if 'json' in sys.modules: print("EAGER") else: @@ -1203,23 +1098,23 @@ def test_cli_overrides_env_var(self): """) import os env = os.environ.copy() - env["PYTHON_LAZY_IMPORTS"] = "all" # env says all + env["PYTHON_LAZY_IMPORTS"] = "all" # env says all imports are lazy result = subprocess.run( - [sys.executable, "-X", "lazy_imports=none", "-c", code], # CLI says none + [sys.executable, "-X", "lazy_imports=normal", "-c", code], capture_output=True, text=True, env=env ) self.assertEqual(result.returncode, 0, f"stderr: {result.stderr}") - # CLI should win - imports should be eager + # CLI should win, so a regular import should stay eager. self.assertIn("EAGER", result.stdout) def test_sys_set_lazy_imports_overrides_cli(self): """sys.set_lazy_imports() should take precedence over CLI option.""" code = textwrap.dedent(""" import sys - sys.set_lazy_imports("none") # Override CLI - lazy import json + sys.set_lazy_imports("normal") # Override CLI + import json if 'json' in sys.modules: print("EAGER") else: @@ -2001,9 +1896,10 @@ def tearDown(self): def test_set_matches_sys(self): self.assertEqual(_testcapi.PyImport_GetLazyImportsMode(), sys.get_lazy_imports()) - for mode in ("normal", "all", "none"): + for mode in ("normal", "all"): _testcapi.PyImport_SetLazyImportsMode(mode) self.assertEqual(_testcapi.PyImport_GetLazyImportsMode(), sys.get_lazy_imports()) + self.assertRaises(ValueError, _testcapi.PyImport_SetLazyImportsMode, "none") def test_filter_matches_sys(self): self.assertEqual(_testcapi.PyImport_GetLazyImportsFilter(), sys.get_lazy_imports_filter()) diff --git a/Lib/test/test_lazy_import/data/global_off.py b/Lib/test/test_lazy_import/data/global_off.py deleted file mode 100644 index 95d1511dd93223..00000000000000 --- a/Lib/test/test_lazy_import/data/global_off.py +++ /dev/null @@ -1,5 +0,0 @@ -import sys - -sys.set_lazy_imports("none") - -lazy import test.test_lazy_import.data.basic2 as basic2 diff --git a/Misc/NEWS.d/3.15.0a8.rst b/Misc/NEWS.d/3.15.0a8.rst index ff7930aeb292d6..eceb9257672c15 100644 --- a/Misc/NEWS.d/3.15.0a8.rst +++ b/Misc/NEWS.d/3.15.0a8.rst @@ -180,16 +180,6 @@ dealing with contradictions in ``make_bottom``. .. -.. date: 2026-03-24-13-06-52 -.. gh-issue: 146369 -.. nonce: 6wDI6S -.. section: Core and Builtins - -Ensure ``-X lazy_imports=none`` and ``PYTHON_LAZY_IMPORTS=none`` override -:attr:`~module.__lazy_modules__`. Patch by Hugo van Kemenade. - -.. - .. date: 2026-03-22-19-30-00 .. gh-issue: 146308 .. nonce: AxnRVA diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-05-12-00-00.gh-issue-149321.remove-lazy-imports-none.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-05-12-00-00.gh-issue-149321.remove-lazy-imports-none.rst new file mode 100644 index 00000000000000..44e96ce7be0bfb --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-05-12-00-00.gh-issue-149321.remove-lazy-imports-none.rst @@ -0,0 +1 @@ +Do not support ``none`` as a lazy imports mode. diff --git a/Misc/NEWS.d/next/Library/2026-05-03-12-00-00.gh-issue-149321.fUaxrz.rst b/Misc/NEWS.d/next/Library/2026-05-03-12-00-00.gh-issue-149321.fUaxrz.rst index 8fd4bf60cf32a7..22e8157327cb19 100644 --- a/Misc/NEWS.d/next/Library/2026-05-03-12-00-00.gh-issue-149321.fUaxrz.rst +++ b/Misc/NEWS.d/next/Library/2026-05-03-12-00-00.gh-issue-149321.fUaxrz.rst @@ -1,2 +1 @@ -Fix import cycles exposed by running standard library modules with -``-X lazy_imports=none``. +Fix import cycles exposed when lazy imports are globally disabled. diff --git a/Modules/_testcapi/import.c b/Modules/_testcapi/import.c index ebb1032fdd1c32..384a8f52da4b98 100644 --- a/Modules/_testcapi/import.c +++ b/Modules/_testcapi/import.c @@ -41,8 +41,6 @@ pyimport_setlazyimportsmode(PyObject *self, PyObject *args) PyImport_SetLazyImportsMode(PyImport_LAZY_NORMAL); } else if (strcmp(PyUnicode_AsUTF8(mode), "all") == 0) { PyImport_SetLazyImportsMode(PyImport_LAZY_ALL); - } else if (strcmp(PyUnicode_AsUTF8(mode), "none") == 0) { - PyImport_SetLazyImportsMode(PyImport_LAZY_NONE); } else { PyErr_SetString(PyExc_ValueError, "invalid mode"); return NULL; @@ -59,8 +57,6 @@ pyimport_getlazyimportsmode(PyObject *self, PyObject *args) return PyUnicode_FromString("normal"); case PyImport_LAZY_ALL: return PyUnicode_FromString("all"); - case PyImport_LAZY_NONE: - return PyUnicode_FromString("none"); default: PyErr_SetString(PyExc_ValueError, "unknown mode"); return NULL; diff --git a/Python/ceval.c b/Python/ceval.c index 28087ba58d4855..e7c1e50dc740fa 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3035,9 +3035,6 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, PyObject *res = NULL; // Check if global policy overrides the local syntax switch (PyImport_GetLazyImportsMode()) { - case PyImport_LAZY_NONE: - lazy = 0; - break; case PyImport_LAZY_ALL: lazy = 1; break; @@ -3045,7 +3042,7 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, break; } - if (!lazy && PyImport_GetLazyImportsMode() != PyImport_LAZY_NONE) { + if (!lazy) { // See if __lazy_modules__ forces this to be lazy. lazy = check_lazy_import_compatibility(tstate, globals, name, level); if (lazy < 0) { diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 86e942ec2b8afb..a639ebb24f0517 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -1914,7 +1914,6 @@ PyDoc_STRVAR(sys_set_lazy_imports__doc__, "\n" "The mode parameter must be one of the following strings:\n" "- \"all\": All top-level imports become potentially lazy\n" -"- \"none\": All lazy imports are suppressed (even explicitly marked ones)\n" "- \"normal\": Only explicitly marked imports (with \'lazy\' keyword) are lazy\n" "\n" "In addition to the mode, lazy imports can be controlled via the filter\n" @@ -1979,7 +1978,6 @@ PyDoc_STRVAR(sys_get_lazy_imports__doc__, "Gets the global lazy imports mode.\n" "\n" "Returns \"all\" if all top level imports are potentially lazy.\n" -"Returns \"none\" if all explicitly marked lazy imports are suppressed.\n" "Returns \"normal\" if only explicitly marked imports are lazy."); #define SYS_GET_LAZY_IMPORTS_METHODDEF \ @@ -2121,4 +2119,4 @@ _jit_is_active(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=e8333fe10c01ae66 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f0412644325e58c6 input=a9049054013a1b77]*/ diff --git a/Python/initconfig.c b/Python/initconfig.c index 8dc9602ff13df7..97243fff0339e2 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -327,7 +327,7 @@ The following implementation-specific options are available:\n\ log imports of already-loaded modules; also PYTHONPROFILEIMPORTTIME\n\ -X int_max_str_digits=N: limit the size of int<->str conversions;\n\ 0 disables the limit; also PYTHONINTMAXSTRDIGITS\n\ --X lazy_imports=[all|none|normal]: control global lazy imports;\n\ +-X lazy_imports=[all|normal]: control global lazy imports;\n\ default is normal; also PYTHON_LAZY_IMPORTS\n\ -X no_debug_ranges: don't include extra location information in code objects;\n\ also PYTHONNODEBUGRANGES\n\ @@ -949,7 +949,8 @@ config_check_consistency(const PyConfig *config) assert(config->int_max_str_digits >= 0); // cpu_count can be -1 if the user doesn't override it. assert(config->cpu_count != 0); - // lazy_imports can be -1 (default), 0 (off), or 1 (on). + // lazy_imports can be -1 (default) or 1 (on). 0 is rejected later + // for embedders with an error message. assert(config->lazy_imports >= -1 && config->lazy_imports <= 1); // config->use_frozen_modules is initialized later // by _PyConfig_InitImportConfig(). @@ -2321,15 +2322,12 @@ config_init_lazy_imports(PyConfig *config) if (strcmp(env, "all") == 0) { lazy_imports = 1; } - else if (strcmp(env, "none") == 0) { - lazy_imports = 0; - } else if (strcmp(env, "normal") == 0) { lazy_imports = -1; } else { return _PyStatus_ERR("PYTHON_LAZY_IMPORTS: invalid value; " - "expected 'all', 'none', or 'normal'"); + "expected 'all' or 'normal'"); } config->lazy_imports = lazy_imports; } @@ -2339,15 +2337,12 @@ config_init_lazy_imports(PyConfig *config) if (wcscmp(x_value, L"all") == 0) { lazy_imports = 1; } - else if (wcscmp(x_value, L"none") == 0) { - lazy_imports = 0; - } else if (wcscmp(x_value, L"normal") == 0) { lazy_imports = -1; } else { return _PyStatus_ERR("-X lazy_imports: invalid value; " - "expected 'all', 'none', or 'normal'"); + "expected 'all' or 'normal'"); } config->lazy_imports = lazy_imports; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 728c0acdd4df67..d460df49edc7da 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1485,15 +1485,11 @@ init_interp_main(PyThreadState *tstate) // Initialize lazy imports based on configuration. Do this after site // module is imported to avoid circular imports during startup. - if (config->lazy_imports != -1) { - PyImport_LazyImportsMode lazy_mode; - if (config->lazy_imports == 1) { - lazy_mode = PyImport_LAZY_ALL; - } - else { - lazy_mode = PyImport_LAZY_NONE; - } - if (PyImport_SetLazyImportsMode(lazy_mode) < 0) { + if (config->lazy_imports == 0) { + return _PyStatus_ERR("PyConfig.lazy_imports=0 is not supported"); + } + if (config->lazy_imports == 1) { + if (PyImport_SetLazyImportsMode(PyImport_LAZY_ALL) < 0) { return _PyStatus_ERR("failed to set lazy imports mode"); } } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index c6447d03369a94..9a8e8fa2dcef5a 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2842,7 +2842,6 @@ Sets the global lazy imports mode. The mode parameter must be one of the following strings: - "all": All top-level imports become potentially lazy -- "none": All lazy imports are suppressed (even explicitly marked ones) - "normal": Only explicitly marked imports (with 'lazy' keyword) are lazy In addition to the mode, lazy imports can be controlled via the filter @@ -2852,12 +2851,12 @@ provided to sys.set_lazy_imports_filter static PyObject * sys_set_lazy_imports_impl(PyObject *module, PyObject *mode) -/*[clinic end generated code: output=1ff34ba6c4feaf73 input=f04e70d8bf9fe4f6]*/ +/*[clinic end generated code: output=1ff34ba6c4feaf73 input=036c75a65f42cbc2]*/ { PyImport_LazyImportsMode lazy_mode; if (!PyUnicode_Check(mode)) { PyErr_SetString(PyExc_TypeError, - "mode must be a string: 'normal', 'all', or 'none'"); + "mode must be a string: 'normal' or 'all'"); return NULL; } if (PyUnicode_CompareWithASCIIString(mode, "normal") == 0) { @@ -2866,12 +2865,9 @@ sys_set_lazy_imports_impl(PyObject *module, PyObject *mode) else if (PyUnicode_CompareWithASCIIString(mode, "all") == 0) { lazy_mode = PyImport_LAZY_ALL; } - else if (PyUnicode_CompareWithASCIIString(mode, "none") == 0) { - lazy_mode = PyImport_LAZY_NONE; - } else { PyErr_SetString(PyExc_ValueError, - "mode must be 'normal', 'all', or 'none'"); + "mode must be 'normal' or 'all'"); return NULL; } @@ -2887,22 +2883,19 @@ sys.get_lazy_imports Gets the global lazy imports mode. Returns "all" if all top level imports are potentially lazy. -Returns "none" if all explicitly marked lazy imports are suppressed. Returns "normal" if only explicitly marked imports are lazy. [clinic start generated code]*/ static PyObject * sys_get_lazy_imports_impl(PyObject *module) -/*[clinic end generated code: output=4147dec48c51ae99 input=8cb574f1e4e3003c]*/ +/*[clinic end generated code: output=4147dec48c51ae99 input=6f8dd4f2c82893f2]*/ { switch (PyImport_GetLazyImportsMode()) { case PyImport_LAZY_NORMAL: return PyUnicode_FromString("normal"); case PyImport_LAZY_ALL: return PyUnicode_FromString("all"); - case PyImport_LAZY_NONE: - return PyUnicode_FromString("none"); default: PyErr_SetString(PyExc_RuntimeError, "unknown lazy imports mode"); return NULL; From 5afe58c203c57ea8217137a118fed860f77aa11d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 5 May 2026 10:56:06 +0200 Subject: [PATCH 2/2] Add entry for removed API --- Doc/tools/removed-ids.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt index 5e3ef2efe271fd..a2bd1ae5f22422 100644 --- a/Doc/tools/removed-ids.txt +++ b/Doc/tools/removed-ids.txt @@ -5,3 +5,5 @@ c-api/allocation.html: deprecated-aliases c-api/file.html: deprecated-api library/asyncio-task.html: terminating-a-task-group + +c-api/import.html: c.PyImport_LazyImportsMode.PyImport_LAZY_NONE