Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions Lib/test/test_lazy_import/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2109,5 +2109,135 @@ def test_set_bad_filter(self):
self.assertRaises(ValueError, _testcapi.PyImport_SetLazyImportsFilter, 42)


class SubmoduleLazinessTests(unittest.TestCase):
"""Tests that module-level lazy imports remain lazy until accessed."""

def tearDown(self):
for key in list(sys.modules.keys()):
if key.startswith('test.test_lazy_import.data'):
del sys.modules[key]
sys.set_lazy_imports_filter(None)
sys.set_lazy_imports("normal")

def test_unaccessed_imports_stay_lazy(self):
"""Imports in 'all' mode should stay lazy until accessed."""
sys.set_lazy_imports("all")
from test.test_lazy_import.data.metasyntactic import names
self.assertIsInstance(names.__dict__["Foo"], types.LazyImportType)
self.assertNotIn(
"test.test_lazy_import.data.metasyntactic.foo", sys.modules
)
_ = names.Foo
self.assertEqual(names.Foo, "Foo")
self.assertIn(
"test.test_lazy_import.data.metasyntactic.foo", sys.modules
)
self.assertIsInstance(names.__dict__["Ack"], types.LazyImportType)
self.assertNotIn(
"test.test_lazy_import.data.metasyntactic.foo.ack", sys.modules
)


class AttributeSideEffectTests(unittest.TestCase):
"""Tests that submodule imports don't overwrite parent attributes."""

def tearDown(self):
for key in list(sys.modules.keys()):
if key.startswith('test.test_lazy_import.data'):
del sys.modules[key]
sys.set_lazy_imports_filter(None)
sys.set_lazy_imports("normal")

def test_version_submodule_does_not_overwrite(self):
"""A __version__ submodule should not overwrite the parent's
__version__ attribute imported in __init__.py."""
import test.test_lazy_import.data.versioned as versioned
self.assertEqual(versioned.__version__, "1.0")
self.assertEqual(
versioned.__copyright__,
"Copyright (c) 2001-2022 Python Software Foundation.",
)


class ModuleVariableNameCollisionTests(unittest.TestCase):
"""Tests for name collision between a submodule and a variable."""

def tearDown(self):
for key in list(sys.modules.keys()):
if key.startswith('test.test_lazy_import.data'):
del sys.modules[key]
sys.set_lazy_imports_filter(None)
sys.set_lazy_imports("normal")

def test_variable_after_import_wins(self):
"""Variable assigned after import should overwrite the submodule."""
from test.test_lazy_import.data import module_same_name_var_order1
self.assertEqual(module_same_name_var_order1.bar, "Blah")

def test_import_after_variable_wins(self):
"""Import after variable assignment should overwrite the variable."""
from test.test_lazy_import.data import module_same_name_var_order2
bar_mod = sys.modules[
"test.test_lazy_import.data.module_same_name_var_order2.bar"
]
self.assertIs(module_same_name_var_order2.bar, bar_mod)


class DeletedModuleReimportTests(unittest.TestCase):
"""Tests for reimporting after module deletion from sys.modules."""

def tearDown(self):
for key in list(sys.modules.keys()):
if key.startswith('test.test_lazy_import.data'):
del sys.modules[key]
sys.set_lazy_imports_filter(None)
sys.set_lazy_imports("normal")

def test_reimport_creates_new_module(self):
"""Deleting and reimporting should create a new module object."""
import test.test_lazy_import.data.metasyntactic.foo
import test.test_lazy_import.data.metasyntactic.foo.bar.baz

first_bar = test.test_lazy_import.data.metasyntactic.foo.bar

del sys.modules[
"test.test_lazy_import.data.metasyntactic.foo.bar"
]

import test.test_lazy_import.data.metasyntactic.foo.bar.thud

second_bar = test.test_lazy_import.data.metasyntactic.foo.bar

self.assertIsNot(first_bar, second_bar)
self.assertIn("baz", dir(first_bar))
self.assertNotIn("thud", dir(first_bar))
self.assertIn("thud", dir(second_bar))
self.assertNotIn("baz", dir(second_bar))


@support.requires_subprocess()
class CircularImportLazyTests(unittest.TestCase):
"""Tests that lazy imports can break circular import patterns."""

def test_succeeds_with_lazy(self):
"""Same-level circular imports should succeed with lazy mode."""
proc = assert_python_ok(
"-X", "lazy_imports=all", "-c",
"import test.test_lazy_import.data.circular_import_pkg.main;"
"print('OK')",
)
self.assertIn(b"OK", proc.out)

def test_fails_without_lazy(self):
"""Same-level circular imports should fail without lazy mode."""
result = subprocess.run(
[sys.executable, "-c",
"import test.test_lazy_import.data.circular_import_pkg.main"],
capture_output=True, text=True,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("ImportError", result.stderr)


if __name__ == '__main__':
unittest.main()
Empty file.
2 changes: 2 additions & 0 deletions Lib/test/test_lazy_import/data/circular_import_pkg/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .x import X2
X2()
7 changes: 7 additions & 0 deletions Lib/test/test_lazy_import/data/circular_import_pkg/x.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def X1():
return "X"

from .y import Y1

def X2():
return Y1()
7 changes: 7 additions & 0 deletions Lib/test/test_lazy_import/data/circular_import_pkg/y.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def Y1():
return "Y"

from .x import X2

def Y2():
return X2()
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Foo = "Foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ack = "Ack"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bar = "Bar"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Baz = "Baz"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Qux = "Qux"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Thud = "Thud"
9 changes: 9 additions & 0 deletions Lib/test/test_lazy_import/data/metasyntactic/names.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .foo import Foo
from .foo.ack import Ack
from .foo.bar import Bar
from .foo.bar.baz import Baz
from .foo.bar.thud import Thud
from .waldo import Waldo
from .waldo.fred import Fred
from .plugh import Plugh
Metasyntactic = "Metasyntactic"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Plugh = "Plugh"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Waldo = "Waldo"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fred = "Fred"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .bar import Bar
bar = "Blah"
Bar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bar = "Bar"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bar = "Blah"
from .bar import Bar
Bar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bar = "Bar"
2 changes: 2 additions & 0 deletions Lib/test/test_lazy_import/data/versioned/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .__version__ import __version__
from .__version__ import __copyright__
2 changes: 2 additions & 0 deletions Lib/test/test_lazy_import/data/versioned/__version__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__version__ = "1.0"
__copyright__ = "Copyright (c) 2001-2022 Python Software Foundation."
14 changes: 14 additions & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -2671,6 +2671,20 @@ TESTSUBDIRS= idlelib/idle_test \
test/test_lazy_import/data \
test/test_lazy_import/data/pkg \
test/test_lazy_import/data/badsyntax \
test/test_lazy_import/data/circular_import_pkg \
test/test_lazy_import/data/metasyntactic \
test/test_lazy_import/data/metasyntactic/foo \
test/test_lazy_import/data/metasyntactic/foo/ack \
test/test_lazy_import/data/metasyntactic/foo/bar \
test/test_lazy_import/data/metasyntactic/foo/bar/baz \
test/test_lazy_import/data/metasyntactic/foo/bar/baz/qux \
test/test_lazy_import/data/metasyntactic/foo/bar/thud \
test/test_lazy_import/data/metasyntactic/plugh \
test/test_lazy_import/data/metasyntactic/waldo \
test/test_lazy_import/data/metasyntactic/waldo/fred \
test/test_lazy_import/data/module_same_name_var_order1 \
test/test_lazy_import/data/module_same_name_var_order2 \
test/test_lazy_import/data/versioned \
test/test_module \
test/test_multiprocessing_fork \
test/test_multiprocessing_forkserver \
Expand Down
Loading