bpo-30436: Raise ModuleNotFoundError for importlib.util.find_spec() when parent isn't a package (GH-1899)
Previously AttributeError was raised, but that's not very reflective of the fact that the requested module can't be found since the specified parent isn't actually a package.
This commit is contained in:
parent
32fd874afe
commit
8c3f05e9f0
@ -1215,6 +1215,11 @@ an :term:`importer`.
|
|||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
.. versionchanged:: 3.7
|
||||||
|
Raises :exc:`ModuleNotFoundError` instead of :exc:`AttributeError` if
|
||||||
|
**package** is in fact not a package (i.e. lacks a :attr:`__path__`
|
||||||
|
attribute).
|
||||||
|
|
||||||
.. function:: module_from_spec(spec)
|
.. function:: module_from_spec(spec)
|
||||||
|
|
||||||
Create a new module based on **spec** and
|
Create a new module based on **spec** and
|
||||||
|
@ -84,11 +84,16 @@ def find_spec(name, package=None):
|
|||||||
if fullname not in sys.modules:
|
if fullname not in sys.modules:
|
||||||
parent_name = fullname.rpartition('.')[0]
|
parent_name = fullname.rpartition('.')[0]
|
||||||
if parent_name:
|
if parent_name:
|
||||||
# Use builtins.__import__() in case someone replaced it.
|
|
||||||
parent = __import__(parent_name, fromlist=['__path__'])
|
parent = __import__(parent_name, fromlist=['__path__'])
|
||||||
return _find_spec(fullname, parent.__path__)
|
try:
|
||||||
|
parent_path = parent.__path__
|
||||||
|
except AttributeError as e:
|
||||||
|
raise ModuleNotFoundError(
|
||||||
|
f"__path__ attribute not found on {parent_name!r}"
|
||||||
|
f"while trying to find {fullname!r}", name=fullname) from e
|
||||||
else:
|
else:
|
||||||
return _find_spec(fullname, None)
|
parent_path = None
|
||||||
|
return _find_spec(fullname, parent_path)
|
||||||
else:
|
else:
|
||||||
module = sys.modules[fullname]
|
module = sys.modules[fullname]
|
||||||
if module is None:
|
if module is None:
|
||||||
|
@ -427,7 +427,7 @@ class CmdLineTest(unittest.TestCase):
|
|||||||
tests = (
|
tests = (
|
||||||
('builtins', br'No code object available'),
|
('builtins', br'No code object available'),
|
||||||
('builtins.x', br'Error while finding module specification.*'
|
('builtins.x', br'Error while finding module specification.*'
|
||||||
br'AttributeError'),
|
br'ModuleNotFoundError'),
|
||||||
('builtins.x.y', br'Error while finding module specification.*'
|
('builtins.x.y', br'Error while finding module specification.*'
|
||||||
br'ModuleNotFoundError.*No module named.*not a package'),
|
br'ModuleNotFoundError.*No module named.*not a package'),
|
||||||
('os.path', br'loader.*cannot handle'),
|
('os.path', br'loader.*cannot handle'),
|
||||||
|
@ -522,6 +522,12 @@ class FindSpecTests:
|
|||||||
self.assertNotIn(name, sorted(sys.modules))
|
self.assertNotIn(name, sorted(sys.modules))
|
||||||
self.assertNotIn(fullname, sorted(sys.modules))
|
self.assertNotIn(fullname, sorted(sys.modules))
|
||||||
|
|
||||||
|
def test_find_submodule_in_module(self):
|
||||||
|
# ModuleNotFoundError raised when a module is specified as
|
||||||
|
# a parent instead of a package.
|
||||||
|
with self.assertRaises(ModuleNotFoundError):
|
||||||
|
self.util.find_spec('module.name')
|
||||||
|
|
||||||
|
|
||||||
(Frozen_FindSpecTests,
|
(Frozen_FindSpecTests,
|
||||||
Source_FindSpecTests
|
Source_FindSpecTests
|
||||||
|
@ -441,6 +441,10 @@ Library
|
|||||||
- bpo-30149: inspect.signature() now supports callables with
|
- bpo-30149: inspect.signature() now supports callables with
|
||||||
variable-argument parameters wrapped with partialmethod.
|
variable-argument parameters wrapped with partialmethod.
|
||||||
Patch by Dong-hee Na.
|
Patch by Dong-hee Na.
|
||||||
|
|
||||||
|
- bpo-30436: importlib.find_spec() raises ModuleNotFoundError instead of
|
||||||
|
AttributeError if the specified parent module is not a package
|
||||||
|
(i.e. lacks a __path__ attribute).
|
||||||
|
|
||||||
- bpo-30301: Fix AttributeError when using SimpleQueue.empty() under
|
- bpo-30301: Fix AttributeError when using SimpleQueue.empty() under
|
||||||
*spawn* and *forkserver* start methods.
|
*spawn* and *forkserver* start methods.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user