mirror of
https://github.com/AdaCore/cpython.git
synced 2026-02-12 12:57:15 -08:00
bpo-30876: Relative import from unloaded package now reimports the package (#2639)
instead of failing with SystemError. Relative import from non-package now fails with ImportError rather than SystemError.
This commit is contained in:
@@ -919,10 +919,6 @@ def _sanity_check(name, package, level):
|
||||
elif not package:
|
||||
raise ImportError('attempted relative import with no known parent '
|
||||
'package')
|
||||
elif package not in sys.modules:
|
||||
msg = ('Parent module {!r} not loaded, cannot perform relative '
|
||||
'import')
|
||||
raise SystemError(msg.format(package))
|
||||
if not name and level == 0:
|
||||
raise ValueError('Empty module name')
|
||||
|
||||
|
||||
@@ -23,8 +23,9 @@ from test.support import (
|
||||
EnvironmentVarGuard, TESTFN, check_warnings, forget, is_jython,
|
||||
make_legacy_pyc, rmtree, run_unittest, swap_attr, swap_item, temp_umask,
|
||||
unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE,
|
||||
temp_dir)
|
||||
temp_dir, DirsOnSysPath)
|
||||
from test.support import script_helper
|
||||
from test.test_importlib.util import uncache
|
||||
|
||||
|
||||
skip_if_dont_write_bytecode = unittest.skipIf(
|
||||
@@ -670,11 +671,11 @@ class RelativeImportTests(unittest.TestCase):
|
||||
|
||||
# Check relative import fails with only __package__ wrong
|
||||
ns = dict(__package__='foo', __name__='test.notarealmodule')
|
||||
self.assertRaises(SystemError, check_relative)
|
||||
self.assertRaises(ModuleNotFoundError, check_relative)
|
||||
|
||||
# Check relative import fails with __package__ and __name__ wrong
|
||||
ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule')
|
||||
self.assertRaises(SystemError, check_relative)
|
||||
self.assertRaises(ModuleNotFoundError, check_relative)
|
||||
|
||||
# Check relative import fails with package set to a non-string
|
||||
ns = dict(__package__=object())
|
||||
@@ -689,6 +690,20 @@ class RelativeImportTests(unittest.TestCase):
|
||||
self.fail("explicit relative import triggered an "
|
||||
"implicit absolute import")
|
||||
|
||||
def test_import_from_non_package(self):
|
||||
path = os.path.join(os.path.dirname(__file__), 'data', 'package2')
|
||||
with uncache('submodule1', 'submodule2'), DirsOnSysPath(path):
|
||||
with self.assertRaises(ImportError):
|
||||
import submodule1
|
||||
self.assertNotIn('submodule1', sys.modules)
|
||||
self.assertNotIn('submodule2', sys.modules)
|
||||
|
||||
def test_import_from_unloaded_package(self):
|
||||
with uncache('package2', 'package2.submodule1', 'package2.submodule2'), \
|
||||
DirsOnSysPath(os.path.join(os.path.dirname(__file__), 'data')):
|
||||
import package2.submodule1
|
||||
package2.submodule1.submodule2
|
||||
|
||||
|
||||
class OverridingImportBuiltinTests(unittest.TestCase):
|
||||
def test_override_builtin(self):
|
||||
|
||||
3
Lib/test/test_import/data/package2/submodule1.py
Normal file
3
Lib/test/test_import/data/package2/submodule1.py
Normal file
@@ -0,0 +1,3 @@
|
||||
import sys
|
||||
sys.modules.pop(__package__, None)
|
||||
from . import submodule2
|
||||
0
Lib/test/test_import/data/package2/submodule2.py
Normal file
0
Lib/test/test_import/data/package2/submodule2.py
Normal file
@@ -81,7 +81,7 @@ class Using__package__:
|
||||
|
||||
def test_bad__package__(self):
|
||||
globals = {'__package__': '<not real>'}
|
||||
with self.assertRaises(SystemError):
|
||||
with self.assertRaises(ModuleNotFoundError):
|
||||
self.__import__('', globals, {}, ['relimport'], 1)
|
||||
|
||||
def test_bunk__package__(self):
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Relative import from unloaded package now reimports the package instead of
|
||||
failing with SystemError. Relative import from non-package now fails with
|
||||
ImportError rather than SystemError.
|
||||
@@ -1344,7 +1344,6 @@ resolve_name(PyObject *name, PyObject *globals, int level)
|
||||
PyObject *abs_name;
|
||||
PyObject *package = NULL;
|
||||
PyObject *spec;
|
||||
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
||||
Py_ssize_t last_dot;
|
||||
PyObject *base;
|
||||
int level_up;
|
||||
@@ -1448,12 +1447,6 @@ resolve_name(PyObject *name, PyObject *globals, int level)
|
||||
"attempted relative import with no known parent package");
|
||||
goto error;
|
||||
}
|
||||
else if (PyDict_GetItem(interp->modules, package) == NULL) {
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"Parent module %R not loaded, cannot perform relative "
|
||||
"import", package);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (level_up = 1; level_up < level; level_up += 1) {
|
||||
last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user