Kaydet (Commit) 32799233 authored tarafından Brett Cannon's avatar Brett Cannon

Issue #17099: Have importlib.find_loader() raise ValueError when

__loader__ is not set on a module. This brings the exception in line
with when __loader__ is None (which is equivalent to not having the
attribute defined).
üst 542308ea
...@@ -90,7 +90,7 @@ Functions ...@@ -90,7 +90,7 @@ Functions
Find the loader for a module, optionally within the specified *path*. If the Find the loader for a module, optionally within the specified *path*. If the
module is in :attr:`sys.modules`, then ``sys.modules[name].__loader__`` is module is in :attr:`sys.modules`, then ``sys.modules[name].__loader__`` is
returned (unless the loader would be ``None``, in which case returned (unless the loader would be ``None`` or is not set, in which case
:exc:`ValueError` is raised). Otherwise a search using :attr:`sys.meta_path` :exc:`ValueError` is raised). Otherwise a search using :attr:`sys.meta_path`
is done. ``None`` is returned if no loader is found. is done. ``None`` is returned if no loader is found.
...@@ -99,6 +99,12 @@ Functions ...@@ -99,6 +99,12 @@ Functions
will need to import all parent packages of the submodule and use the correct will need to import all parent packages of the submodule and use the correct
argument to *path*. argument to *path*.
.. versionadded:: 3.3
.. versionchanged:: 3.4
If ``__loader__`` is not set, raise :exc:`ValueError`, just like when the
attribute is set to ``None``.
.. function:: invalidate_caches() .. function:: invalidate_caches()
Invalidate the internal caches of finders stored at Invalidate the internal caches of finders stored at
......
...@@ -68,6 +68,8 @@ def find_loader(name, path=None): ...@@ -68,6 +68,8 @@ def find_loader(name, path=None):
return loader return loader
except KeyError: except KeyError:
pass pass
except AttributeError:
raise ValueError('{}.__loader__ is not set'.format(name))
return _bootstrap._find_module(name, path) return _bootstrap._find_module(name, path)
......
...@@ -116,6 +116,20 @@ class FindLoaderTests(unittest.TestCase): ...@@ -116,6 +116,20 @@ class FindLoaderTests(unittest.TestCase):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
importlib.find_loader(name) importlib.find_loader(name)
def test_sys_modules_loader_is_not_set(self):
# Should raise ValueError
# Issue #17099
name = 'some_mod'
with util.uncache(name):
module = imp.new_module(name)
try:
del module.__loader__
except AttributeError:
pass
sys.modules[name] = module
with self.assertRaises(ValueError):
importlib.find_loader(name)
def test_success(self): def test_success(self):
# Return the loader found on sys.meta_path. # Return the loader found on sys.meta_path.
name = 'some_mod' name = 'some_mod'
......
...@@ -280,6 +280,9 @@ Core and Builtins ...@@ -280,6 +280,9 @@ Core and Builtins
Library Library
------- -------
- Issue #17099: Have importlib.find_loader() raise ValueError when __loader__
is not set, harmonizing with what happens when the attribute is set to None.
- Expose the O_PATH constant in the os module if it is available. - Expose the O_PATH constant in the os module if it is available.
- Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused - Issue #17368: Fix an off-by-one error in the Python JSON decoder that caused
......
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