From 51ddfe7764a0fae2e642a0bfb6e6405e5cdb7b0b Mon Sep 17 00:00:00 2001 From: johnslavik Date: Tue, 3 Mar 2026 08:09:18 +0100 Subject: [PATCH 1/9] Add failing test --- Lib/test/test_lazy_import/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 5d30ec2299789b..6fc7e38412dcd4 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -210,6 +210,20 @@ def test_lazy_value_resolve(self): import test.test_lazy_import.data.lazy_get_value self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + @support.requires_subprocess() + def test_lazy_value_resolve_method_exists_if_not_called(self): + code = textwrap.dedent(""" + lazy import json + print(globals()["json"].resolve) + """) + result = subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True + ) + self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") + self.assertIn(" Date: Tue, 3 Mar 2026 09:01:33 +0100 Subject: [PATCH 2/9] Initialize `PyLazyImport_Type` in `_PyTypes_InitTypes` --- Objects/object.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Objects/object.c b/Objects/object.c index ab73d2eb1c9c1f..b537c0d104e58c 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -17,6 +17,7 @@ #include "pycore_instruction_sequence.h" // _PyInstructionSequence_Type #include "pycore_interpframe.h" // _PyFrame_Stackbase() #include "pycore_interpolation.h" // _PyInterpolation_Type +#include "pycore_lazyimportobject.h" // PyLazyImport_Type #include "pycore_list.h" // _PyList_DebugMallocStats() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_memoryobject.h" // _PyManagedBuffer_Type @@ -2540,6 +2541,7 @@ static PyTypeObject* static_types[] = { &PyGen_Type, &PyGetSetDescr_Type, &PyInstanceMethod_Type, + &PyLazyImport_Type, &PyListIter_Type, &PyListRevIter_Type, &PyList_Type, From 37e62578aaf0bd64309056112834e9cd9e16604b Mon Sep 17 00:00:00 2001 From: johnslavik Date: Tue, 3 Mar 2026 09:26:06 +0100 Subject: [PATCH 3/9] Add explanations to the test --- Lib/test/test_lazy_import/__init__.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 6fc7e38412dcd4..f0afd325792907 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -210,8 +210,18 @@ def test_lazy_value_resolve(self): import test.test_lazy_import.data.lazy_get_value self.assertIn("test.test_lazy_import.data.basic2", sys.modules) + def test_lazy_import_type_exposed(self): + """LazyImportType should be exposed in types module.""" + self.assertHasAttr(types, 'LazyImportType') + self.assertEqual(types.LazyImportType.__name__, 'lazy_import') + + def test_lazy_import_type_cant_construct(self): + """LazyImportType should not be directly constructible.""" + self.assertRaises(TypeError, types.LazyImportType, {}, "module") + @support.requires_subprocess() - def test_lazy_value_resolve_method_exists_if_not_called(self): + def test_lazy_import_type_attributes_accessible(self): + """Regression test for GH-145453.""" code = textwrap.dedent(""" lazy import json print(globals()["json"].resolve) @@ -224,15 +234,6 @@ def test_lazy_value_resolve_method_exists_if_not_called(self): self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") self.assertIn(" Date: Tue, 3 Mar 2026 09:27:07 +0100 Subject: [PATCH 4/9] Fix issue number in test explanation --- Lib/test/test_lazy_import/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index f0afd325792907..cb605559778f88 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -221,7 +221,7 @@ def test_lazy_import_type_cant_construct(self): @support.requires_subprocess() def test_lazy_import_type_attributes_accessible(self): - """Regression test for GH-145453.""" + """Regression test for GH-145452.""" code = textwrap.dedent(""" lazy import json print(globals()["json"].resolve) From e498ab55e4dce01f04665ccf5670bdfa83b2b46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Tue, 3 Mar 2026 10:55:56 +0100 Subject: [PATCH 5/9] Use a descriptive docstring for the test Co-authored-by: Victor Stinner --- Lib/test/test_lazy_import/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index cb605559778f88..14cef8da7bd6b5 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -221,7 +221,7 @@ def test_lazy_import_type_cant_construct(self): @support.requires_subprocess() def test_lazy_import_type_attributes_accessible(self): - """Regression test for GH-145452.""" + """Check that static PyLazyImport_Type is initialized at startup.""" code = textwrap.dedent(""" lazy import json print(globals()["json"].resolve) From ec6ed07acf6e07207a347d1d4a25eed356f37edd Mon Sep 17 00:00:00 2001 From: johnslavik Date: Tue, 3 Mar 2026 11:14:06 +0100 Subject: [PATCH 6/9] Use big boy guns for the subprocess test Co-authored-by: Victor Stinner --- Lib/test/test_lazy_import/__init__.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 14cef8da7bd6b5..6f774af6d25819 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -12,6 +12,7 @@ import os from test import support +from test.support.script_helper import assert_python_ok try: import _testcapi @@ -226,14 +227,8 @@ def test_lazy_import_type_attributes_accessible(self): lazy import json print(globals()["json"].resolve) """) - result = subprocess.run( - [sys.executable, "-c", code], - capture_output=True, - text=True - ) - self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") - self.assertIn(" Date: Tue, 3 Mar 2026 11:14:28 +0100 Subject: [PATCH 7/9] Add extra space line --- Lib/test/test_lazy_import/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 6f774af6d25819..832a043d1772d2 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -230,6 +230,7 @@ def test_lazy_import_type_attributes_accessible(self): proc = assert_python_ok("-c", code) self.assertIn(b" Date: Tue, 3 Mar 2026 11:16:37 +0100 Subject: [PATCH 8/9] Fix linting issue --- Lib/test/test_lazy_import/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 832a043d1772d2..4088f063fa9a83 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -227,7 +227,7 @@ def test_lazy_import_type_attributes_accessible(self): lazy import json print(globals()["json"].resolve) """) - proc = assert_python_ok("-c", code) + proc = assert_python_ok("-c", code) self.assertIn(b" Date: Tue, 3 Mar 2026 11:18:03 +0100 Subject: [PATCH 9/9] One more problem --- Lib/test/test_lazy_import/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 4088f063fa9a83..a4180f05dbbafc 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -228,7 +228,7 @@ def test_lazy_import_type_attributes_accessible(self): print(globals()["json"].resolve) """) proc = assert_python_ok("-c", code) - self.assertIn(b"