https://github.com/python/cpython/commit/e531dd4b7e6961aab54c19ee90bd80420e24f82d
commit: e531dd4b7e6961aab54c19ee90bd80420e24f82d
branch: 3.15
author: Brittany Reynoso <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-08-19T11:01:31+01:00
summary:
[3.15] gh-155194: Fix not raising on non-module import (GH-155189) (#155983)
files:
A Lib/test/test_lazy_import/data/lazypkg/__init__.py
A Lib/test/test_lazy_import/data/lazypkg/bar.py
M Lib/test/test_lazy_import/__init__.py
M Lib/test/test_traceback.py
M Makefile.pre.in
M Python/import.c
diff --git a/Lib/test/test_lazy_import/__init__.py
b/Lib/test/test_lazy_import/__init__.py
index 0a53d2559c91f01..6951a67d309bf99 100644
--- a/Lib/test/test_lazy_import/__init__.py
+++ b/Lib/test/test_lazy_import/__init__.py
@@ -686,17 +686,53 @@ def test_lazy_modules_tracks_lazy_imports(self):
class ErrorHandlingTests(LazyImportTestCase):
"""Tests for error handling during lazy import reification."""
- def test_missing_lazy_submodule_raises_attribute_error(self):
- """Accessing a nonexistent lazy submodule via parent attr raises
AttributeError."""
+ def test_missing_lazy_submodule_raises_module_not_found_error(self):
+ """Accessing a nonexistent lazy submodule via parent attr raises
ModuleNotFoundError."""
code = textwrap.dedent("""
lazy import test.test_lazy_import.data.nonexistent_module
try:
_ = test.test_lazy_import.data.nonexistent_module
- except AttributeError:
+ except ModuleNotFoundError:
pass
else:
- raise AssertionError("AttributeError was not raised")
+ raise AssertionError("ModuleNotFoundError was not raised")
+ """)
+ assert_python_ok("-c", code)
+
+ def test_non_package_lazily_imported(self):
+ """Accessing a nonexistent lazy name via parent attr raises
ModuleNotFoundError."""
+ code = textwrap.dedent("""
+ lazy import math.pi
+
+ try:
+ _ = math.pi
+ except ModuleNotFoundError:
+ pass
+ else:
+ raise AssertionError("ModuleNotFoundError was not raised")
+ """)
+ assert_python_ok("-c", code)
+
+ def test_non_package_lazily_imported_as(self):
+ """Doing a dotted lazy import as still works"""
+ code = textwrap.dedent("""
+ lazy import math.pi as pi
+ pi
+ """)
+ assert_python_ok("-c", code)
+
+ def test_missing_attribute_raises_import_error(self):
+ """Accessing a nonexistent lazy name via from import raises
ImportError."""
+ code = textwrap.dedent("""
+ lazy from sys import doesnotexist
+
+ try:
+ _ = doesnotexist
+ except ImportError:
+ pass
+ else:
+ raise AssertionError("ImportError was not raised")
""")
assert_python_ok("-c", code)
diff --git a/Lib/test/test_lazy_import/data/lazypkg/__init__.py
b/Lib/test/test_lazy_import/data/lazypkg/__init__.py
new file mode 100644
index 000000000000000..276b51823fee32a
--- /dev/null
+++ b/Lib/test/test_lazy_import/data/lazypkg/__init__.py
@@ -0,0 +1 @@
+lazy from . import bar
diff --git a/Lib/test/test_lazy_import/data/lazypkg/bar.py
b/Lib/test/test_lazy_import/data/lazypkg/bar.py
new file mode 100644
index 000000000000000..b8d8b60b886b88a
--- /dev/null
+++ b/Lib/test/test_lazy_import/data/lazypkg/bar.py
@@ -0,0 +1,2 @@
+print("BAR_MODULE_LOADED")
+def f(): pass
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index bb64153b91c92cc..6b4f1ee6de6c518 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -5596,11 +5596,11 @@ class TestLazyImportSuggestions(unittest.TestCase):
def test_attribute_error_does_not_reify_lazy_imports(self):
"""Printing an AttributeError should not trigger lazy import
reification."""
- # pkg.bar prints "BAR_MODULE_LOADED" when imported.
+ # lazypkg.bar prints "BAR_MODULE_LOADED" when imported.
# If lazy import is reified during suggestion computation, we'll see
it.
code = textwrap.dedent("""
- lazy import test.test_lazy_import.data.pkg.bar
- test.test_lazy_import.data.pkg.nonexistent
+ lazy import test.test_lazy_import.data.lazypkg
+ test.test_lazy_import.data.lazypkg.nonexistent
""")
rc, stdout, stderr = assert_python_failure('-c', code)
self.assertNotIn(b"BAR_MODULE_LOADED", stdout)
@@ -5609,9 +5609,9 @@ def
test_traceback_formatting_does_not_reify_lazy_imports(self):
"""Formatting a traceback should not trigger lazy import
reification."""
code = textwrap.dedent("""
import traceback
- lazy import test.test_lazy_import.data.pkg.bar
+ lazy import test.test_lazy_import.data.lazypkg
try:
- test.test_lazy_import.data.pkg.nonexistent
+ test.test_lazy_import.data.lazypkg.nonexistent
except AttributeError:
traceback.format_exc()
print("OK")
@@ -5623,9 +5623,9 @@ def
test_traceback_formatting_does_not_reify_lazy_imports(self):
def test_suggestion_still_works_for_non_lazy_attributes(self):
"""Suggestions should still work for non-lazy module attributes."""
code = textwrap.dedent("""
- lazy import test.test_lazy_import.data.pkg.bar
+ lazy import test.test_lazy_import.data.lazypkg
# Typo for __name__
- test.test_lazy_import.data.pkg.__nme__
+ test.test_lazy_import.data.lazypkg.__nme__
""")
rc, stdout, stderr = assert_python_failure('-c', code)
self.assertIn(b"__name__", stderr)
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 77dde715a4852dc..1f4c366d30c44f9 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -2772,6 +2772,7 @@ 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/lazypkg \
test/test_module \
test/test_multiprocessing_fork \
test/test_multiprocessing_forkserver \
diff --git a/Python/import.c b/Python/import.c
index 287f5f611f55342..95f5c20bf4894a8 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -3937,19 +3937,6 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate,
PyObject *lazy_import)
goto error;
}
- Py_ssize_t dot = -1;
- int full = 0;
- if (lz->lz_attr != NULL) {
- full = 1;
- }
- if (!full) {
- dot = PyUnicode_FindChar(lz->lz_from, '.', 0,
- PyUnicode_GET_LENGTH(lz->lz_from), 1);
- }
- if (dot < 0) {
- full = 1;
- }
-
if (lz->lz_attr != NULL) {
if (PyUnicode_Check(lz->lz_attr)) {
fromlist = PyTuple_New(1);
@@ -3975,23 +3962,10 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate,
PyObject *lazy_import)
PyErr_SetString(PyExc_ImportError, "__import__ not found");
goto error;
}
- if (full) {
- obj = _PyEval_ImportNameWithImport(
- tstate, import_func, globals, globals,
- lz->lz_from, fromlist, _PyLong_GetZero()
- );
- }
- else {
- PyObject *name = PyUnicode_Substring(lz->lz_from, 0, dot);
- if (name == NULL) {
- goto error;
- }
- obj = _PyEval_ImportNameWithImport(
- tstate, import_func, globals, globals,
- name, fromlist, _PyLong_GetZero()
- );
- Py_DECREF(name);
- }
+ obj = _PyEval_ImportNameWithImport(
+ tstate, import_func, globals, globals,
+ lz->lz_from, fromlist, _PyLong_GetZero()
+ );
if (obj == NULL) {
goto error;
}
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]