File tree Expand file tree Collapse file tree 5 files changed +24
-4
lines changed Expand file tree Collapse file tree 5 files changed +24
-4
lines changed Original file line number Diff line number Diff line change @@ -1215,6 +1215,11 @@ an :term:`importer`.
1215
1215
1216
1216
.. versionadded :: 3.4
1217
1217
1218
+ .. versionchanged :: 3.7
1219
+ Raises :exc: `ModuleNotFoundError ` instead of :exc: `AttributeError ` if
1220
+ **package ** is in fact not a package (i.e. lacks a :attr: `__path__ `
1221
+ attribute).
1222
+
1218
1223
.. function :: module_from_spec(spec)
1219
1224
1220
1225
Create a new module based on **spec ** and
Original file line number Diff line number Diff line change @@ -84,11 +84,16 @@ def find_spec(name, package=None):
84
84
if fullname not in sys .modules :
85
85
parent_name = fullname .rpartition ('.' )[0 ]
86
86
if parent_name :
87
- # Use builtins.__import__() in case someone replaced it.
88
87
parent = __import__ (parent_name , fromlist = ['__path__' ])
89
- return _find_spec (fullname , parent .__path__ )
88
+ try :
89
+ parent_path = parent .__path__
90
+ except AttributeError as e :
91
+ raise ModuleNotFoundError (
92
+ f"__path__ attribute not found on { parent_name !r} "
93
+ f"while trying to find { fullname !r} " , name = fullname ) from e
90
94
else :
91
- return _find_spec (fullname , None )
95
+ parent_path = None
96
+ return _find_spec (fullname , parent_path )
92
97
else :
93
98
module = sys .modules [fullname ]
94
99
if module is None :
Original file line number Diff line number Diff line change @@ -427,7 +427,7 @@ def test_dash_m_errors(self):
427
427
tests = (
428
428
('builtins' , br'No code object available' ),
429
429
('builtins.x' , br'Error while finding module specification.*'
430
- br'AttributeError ' ),
430
+ br'ModuleNotFoundError ' ),
431
431
('builtins.x.y' , br'Error while finding module specification.*'
432
432
br'ModuleNotFoundError.*No module named.*not a package' ),
433
433
('os.path' , br'loader.*cannot handle' ),
Original file line number Diff line number Diff line change @@ -522,6 +522,12 @@ def test_find_relative_module_missing_package(self):
522
522
self .assertNotIn (name , sorted (sys .modules ))
523
523
self .assertNotIn (fullname , sorted (sys .modules ))
524
524
525
+ def test_find_submodule_in_module (self ):
526
+ # ModuleNotFoundError raised when a module is specified as
527
+ # a parent instead of a package.
528
+ with self .assertRaises (ModuleNotFoundError ):
529
+ self .util .find_spec ('module.name' )
530
+
525
531
526
532
(Frozen_FindSpecTests ,
527
533
Source_FindSpecTests
Original file line number Diff line number Diff line change @@ -441,6 +441,10 @@ Library
441
441
- bpo-30149: inspect.signature() now supports callables with
442
442
variable-argument parameters wrapped with partialmethod.
443
443
Patch by Dong-hee Na.
444
+
445
+ - bpo-30436: importlib.find_spec() raises ModuleNotFoundError instead of
446
+ AttributeError if the specified parent module is not a package
447
+ (i.e. lacks a __path__ attribute).
444
448
445
449
- bpo-30301: Fix AttributeError when using SimpleQueue.empty() under
446
450
*spawn* and *forkserver* start methods.
You can’t perform that action at this time.
0 commit comments