https://github.com/python/cpython/commit/39ee468e092eed659bfc2a4e0ce02572e0d81de0
commit: 39ee468e092eed659bfc2a4e0ce02572e0d81de0
branch: main
author: Jelle Zijlstra <jelle.zijls...@gmail.com>
committer: JelleZijlstra <jelle.zijls...@gmail.com>
date: 2025-04-17T03:46:36Z
summary:

gh-118761: Add helper to ensure that lazy imports are actually lazy (#132614)

This ensures that if we jump through some hoops to make sure something is 
imported
lazily, we don't regress on importing it.

I recently already accidentally made typing import warnings and annotationlib 
eagerly.

Co-authored-by: Adam Turner <9087854+aa-tur...@users.noreply.github.com>

files:
M Lib/test/support/import_helper.py
M Lib/test/test_annotationlib.py
M Lib/test/test_typing.py

diff --git a/Lib/test/support/import_helper.py 
b/Lib/test/support/import_helper.py
index 2b91bdcf9cd859..42cfe9cfa8cb72 100644
--- a/Lib/test/support/import_helper.py
+++ b/Lib/test/support/import_helper.py
@@ -5,6 +5,7 @@
 import os
 import shutil
 import sys
+import textwrap
 import unittest
 import warnings
 
@@ -309,3 +310,25 @@ def ready_to_import(name=None, source=""):
                 sys.modules[name] = old_module
             else:
                 sys.modules.pop(name, None)
+
+
+def ensure_lazy_imports(imported_module, modules_to_block):
+    """Test that when imported_module is imported, none of the modules in
+    modules_to_block are imported as a side effect."""
+    modules_to_block = frozenset(modules_to_block)
+    script = textwrap.dedent(
+        f"""
+        import sys
+        modules_to_block = {modules_to_block}
+        if unexpected := modules_to_block & sys.modules.keys():
+            startup = ", ".join(unexpected)
+            raise AssertionError(f'unexpectedly imported at startup: 
{{startup}}')
+
+        import {imported_module}
+        if unexpected := modules_to_block & sys.modules.keys():
+            after = ", ".join(unexpected)
+            raise AssertionError(f'unexpectedly imported after importing 
{imported_module}: {{after}}')
+        """
+    )
+    from .script_helper import assert_python_ok
+    assert_python_ok("-S", "-c", script)
diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py
index 6f097c07295f3b..0890be529a7e52 100644
--- a/Lib/test/test_annotationlib.py
+++ b/Lib/test/test_annotationlib.py
@@ -24,6 +24,7 @@
 )
 
 from test import support
+from test.support import import_helper
 from test.test_inspect import inspect_stock_annotations
 from test.test_inspect import inspect_stringized_annotations
 from test.test_inspect import inspect_stringized_annotations_2
@@ -1367,3 +1368,9 @@ def test_multiple_ways_to_create(self):
 class TestAnnotationLib(unittest.TestCase):
     def test__all__(self):
         support.check__all__(self, annotationlib)
+
+    def test_lazy_imports(self):
+        import_helper.ensure_lazy_imports("annotationlib", {
+            "typing",
+            "warnings",
+        })
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 32f12a3f8b22f1..81474a81be645d 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -6317,6 +6317,15 @@ def test_collect_parameters(self):
             typing._collect_parameters
         self.assertEqual(cm.filename, __file__)
 
+    def test_lazy_import(self):
+        import_helper.ensure_lazy_imports("typing", {
+            "warnings",
+            "inspect",
+            "re",
+            "contextlib",
+            # "annotationlib",  # TODO
+        })
+
 
 @lru_cache()
 def cached_func(x, y):

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to