Skip to content

Commit fa92f61

Browse files
committed
Merge remote-tracking branch 'upstream/3.15' into backport-00a1c3a-3.15
2 parents 14c59a8 + 3d9473f commit fa92f61

23 files changed

Lines changed: 189 additions & 0 deletions

File tree

‎Lib/test/test_lazy_import/__init__.py‎

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,6 +2692,135 @@ def test_dotted_as_replays_lookups_on_dotted_placeholder(self):
26922692
assert_python_ok("-c", code)
26932693

26942694

2695+
class SubmoduleLazinessTests(unittest.TestCase):
2696+
"""Tests that module-level lazy imports remain lazy until accessed."""
2697+
2698+
def tearDown(self):
2699+
for key in list(sys.modules.keys()):
2700+
if key.startswith('test.test_lazy_import.data'):
2701+
del sys.modules[key]
2702+
sys.set_lazy_imports_filter(None)
2703+
sys.set_lazy_imports("normal")
2704+
2705+
def test_unaccessed_imports_stay_lazy(self):
2706+
"""Imports in 'all' mode should stay lazy until accessed."""
2707+
sys.set_lazy_imports("all")
2708+
from test.test_lazy_import.data.metasyntactic import names
2709+
self.assertIsInstance(names.__dict__["Foo"], types.LazyImportType)
2710+
self.assertNotIn(
2711+
"test.test_lazy_import.data.metasyntactic.foo", sys.modules
2712+
)
2713+
_ = names.Foo
2714+
self.assertEqual(names.Foo, "Foo")
2715+
self.assertIn(
2716+
"test.test_lazy_import.data.metasyntactic.foo", sys.modules
2717+
)
2718+
self.assertIsInstance(names.__dict__["Ack"], types.LazyImportType)
2719+
self.assertNotIn(
2720+
"test.test_lazy_import.data.metasyntactic.foo.ack", sys.modules
2721+
)
2722+
2723+
2724+
class AttributeSideEffectTests(unittest.TestCase):
2725+
"""Tests that submodule imports don't overwrite parent attributes."""
2726+
2727+
def tearDown(self):
2728+
for key in list(sys.modules.keys()):
2729+
if key.startswith('test.test_lazy_import.data'):
2730+
del sys.modules[key]
2731+
sys.set_lazy_imports_filter(None)
2732+
sys.set_lazy_imports("normal")
2733+
2734+
def test_version_submodule_does_not_overwrite(self):
2735+
"""A __version__ submodule should not overwrite the parent's
2736+
__version__ attribute imported in __init__.py."""
2737+
import test.test_lazy_import.data.versioned as versioned
2738+
self.assertEqual(versioned.__version__, "1.0")
2739+
self.assertEqual(
2740+
versioned.__copyright__,
2741+
"Copyright (c) 2001-2022 Python Software Foundation.",
2742+
)
2743+
2744+
2745+
class ModuleVariableNameCollisionTests(unittest.TestCase):
2746+
"""Tests for name collision between a submodule and a variable."""
2747+
2748+
def tearDown(self):
2749+
for key in list(sys.modules.keys()):
2750+
if key.startswith('test.test_lazy_import.data'):
2751+
del sys.modules[key]
2752+
sys.set_lazy_imports_filter(None)
2753+
sys.set_lazy_imports("normal")
2754+
2755+
def test_variable_after_import_wins(self):
2756+
"""Variable assigned after import should overwrite the submodule."""
2757+
from test.test_lazy_import.data import module_same_name_var_order1
2758+
self.assertEqual(module_same_name_var_order1.bar, "Blah")
2759+
2760+
def test_import_after_variable_wins(self):
2761+
"""Import after variable assignment should overwrite the variable."""
2762+
from test.test_lazy_import.data import module_same_name_var_order2
2763+
bar_mod = sys.modules[
2764+
"test.test_lazy_import.data.module_same_name_var_order2.bar"
2765+
]
2766+
self.assertIs(module_same_name_var_order2.bar, bar_mod)
2767+
2768+
2769+
class DeletedModuleReimportTests(unittest.TestCase):
2770+
"""Tests for reimporting after module deletion from sys.modules."""
2771+
2772+
def tearDown(self):
2773+
for key in list(sys.modules.keys()):
2774+
if key.startswith('test.test_lazy_import.data'):
2775+
del sys.modules[key]
2776+
sys.set_lazy_imports_filter(None)
2777+
sys.set_lazy_imports("normal")
2778+
2779+
def test_reimport_creates_new_module(self):
2780+
"""Deleting and reimporting should create a new module object."""
2781+
import test.test_lazy_import.data.metasyntactic.foo
2782+
import test.test_lazy_import.data.metasyntactic.foo.bar.baz
2783+
2784+
first_bar = test.test_lazy_import.data.metasyntactic.foo.bar
2785+
2786+
del sys.modules[
2787+
"test.test_lazy_import.data.metasyntactic.foo.bar"
2788+
]
2789+
2790+
import test.test_lazy_import.data.metasyntactic.foo.bar.thud
2791+
2792+
second_bar = test.test_lazy_import.data.metasyntactic.foo.bar
2793+
2794+
self.assertIsNot(first_bar, second_bar)
2795+
self.assertIn("baz", dir(first_bar))
2796+
self.assertNotIn("thud", dir(first_bar))
2797+
self.assertIn("thud", dir(second_bar))
2798+
self.assertNotIn("baz", dir(second_bar))
2799+
2800+
2801+
@support.requires_subprocess()
2802+
class CircularImportLazyTests(unittest.TestCase):
2803+
"""Tests that lazy imports can break circular import patterns."""
2804+
2805+
def test_succeeds_with_lazy(self):
2806+
"""Same-level circular imports should succeed with lazy mode."""
2807+
proc = assert_python_ok(
2808+
"-X", "lazy_imports=all", "-c",
2809+
"import test.test_lazy_import.data.circular_import_pkg.main;"
2810+
"print('OK')",
2811+
)
2812+
self.assertIn(b"OK", proc.out)
2813+
2814+
def test_fails_without_lazy(self):
2815+
"""Same-level circular imports should fail without lazy mode."""
2816+
result = subprocess.run(
2817+
[sys.executable, "-c",
2818+
"import test.test_lazy_import.data.circular_import_pkg.main"],
2819+
capture_output=True, text=True,
2820+
)
2821+
self.assertNotEqual(result.returncode, 0)
2822+
self.assertIn("ImportError", result.stderr)
2823+
26952824

26962825
if __name__ == '__main__':
26972826
unittest.main()

‎Lib/test/test_lazy_import/data/circular_import_pkg/__init__.py‎

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .x import X2
2+
X2()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
def X1():
2+
return "X"
3+
4+
from .y import Y1
5+
6+
def X2():
7+
return Y1()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
def Y1():
2+
return "Y"
3+
4+
from .x import X2
5+
6+
def Y2():
7+
return X2()

‎Lib/test/test_lazy_import/data/metasyntactic/__init__.py‎

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Foo = "Foo"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ack = "Ack"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Bar = "Bar"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Baz = "Baz"

0 commit comments

Comments
 (0)