Commit 94987826 authored by Garvit Khatri's avatar Garvit Khatri Committed by Brett Cannon

bpo-29851: Have importlib.reload() raise ImportError if the module's spec is not found (GH-972)

parent 3480ef9d
...@@ -203,6 +203,9 @@ Functions ...@@ -203,6 +203,9 @@ Functions
classes. classes.
.. versionadded:: 3.4 .. versionadded:: 3.4
.. versionchanged:: 3.7
:exc:`ModuleNotFoundError` is raised when the module being reloaded lacks
a :class:`ModuleSpec`.
:mod:`importlib.abc` -- Abstract base classes related to import :mod:`importlib.abc` -- Abstract base classes related to import
......
...@@ -164,6 +164,8 @@ def reload(module): ...@@ -164,6 +164,8 @@ def reload(module):
pkgpath = None pkgpath = None
target = module target = module
spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, target) spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, target)
if spec is None:
raise ModuleNotFoundError(f"spec not found for the module {name!r}", name=name)
_bootstrap._exec(spec, module) _bootstrap._exec(spec, module)
# The module may have replaced itself in sys.modules! # The module may have replaced itself in sys.modules!
return sys.modules[name] return sys.modules[name]
......
...@@ -197,8 +197,6 @@ class FindLoaderPEP302Tests(FindLoaderTests): ...@@ -197,8 +197,6 @@ class FindLoaderPEP302Tests(FindLoaderTests):
class ReloadTests: class ReloadTests:
"""Test module reloading for builtin and extension modules."""
def test_reload_modules(self): def test_reload_modules(self):
for mod in ('tokenize', 'time', 'marshal'): for mod in ('tokenize', 'time', 'marshal'):
with self.subTest(module=mod): with self.subTest(module=mod):
...@@ -361,6 +359,18 @@ class ReloadTests: ...@@ -361,6 +359,18 @@ class ReloadTests:
reloaded = self.init.reload(ham) reloaded = self.init.reload(ham)
self.assertIs(reloaded, ham) self.assertIs(reloaded, ham)
def test_module_missing_spec(self):
#Test that reload() throws ModuleNotFounderror when reloading
# a module who's missing a spec. (bpo-29851)
name = 'spam'
with test_util.uncache(name):
module = sys.modules[name] = types.ModuleType(name)
# Sanity check by attempting an import.
module = self.init.import_module(name)
self.assertIsNone(module.__spec__)
with self.assertRaises(ModuleNotFoundError):
self.init.reload(module)
(Frozen_ReloadTests, (Frozen_ReloadTests,
Source_ReloadTests Source_ReloadTests
......
...@@ -774,6 +774,7 @@ Robert Kern ...@@ -774,6 +774,7 @@ Robert Kern
Jim Kerr Jim Kerr
Magnus Kessler Magnus Kessler
Lawrence Kesteloot Lawrence Kesteloot
Garvit Khatri
Vivek Khera Vivek Khera
Dhiru Kholia Dhiru Kholia
Akshit Khurana Akshit Khurana
......
...@@ -604,6 +604,9 @@ Library ...@@ -604,6 +604,9 @@ Library
- bpo-10379: locale.format_string now supports the 'monetary' keyword argument, - bpo-10379: locale.format_string now supports the 'monetary' keyword argument,
and locale.format is deprecated. and locale.format is deprecated.
- bpo-29851: importlib.reload() now raises ModuleNotFoundError if the
module lacks a spec.
- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap, - Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi, improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
Manuel Krebber, and Łukasz Langa. Manuel Krebber, and Łukasz Langa.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment