mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Close #20839: pkgutil.find_loader now uses importlib.util.find_spec
This commit is contained in:
parent
c913a7a6f6
commit
dc855b7b1f
4 changed files with 37 additions and 20 deletions
|
@ -74,15 +74,17 @@ support.
|
||||||
|
|
||||||
Retrieve a :pep:`302` module loader for the given *fullname*.
|
Retrieve a :pep:`302` module loader for the given *fullname*.
|
||||||
|
|
||||||
This is a convenience wrapper around :func:`importlib.find_loader` that
|
This is a backwards compatibility wrapper around
|
||||||
sets the *path* argument correctly when searching for submodules, and
|
:func:`importlib.util.find_spec` that converts most failures to
|
||||||
also ensures parent packages (if any) are imported before searching for
|
:exc:`ImportError` and only returns the loader rather than the full
|
||||||
submodules.
|
:class:`ModuleSpec`.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
Updated to be based directly on :mod:`importlib` rather than relying
|
Updated to be based directly on :mod:`importlib` rather than relying
|
||||||
on the package internal PEP 302 import emulation.
|
on the package internal PEP 302 import emulation.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.4
|
||||||
|
Updated to be based on :pep:`451`
|
||||||
|
|
||||||
.. function:: get_importer(path_item)
|
.. function:: get_importer(path_item)
|
||||||
|
|
||||||
|
@ -109,14 +111,13 @@ support.
|
||||||
not already imported, its containing package (if any) is imported, in order
|
not already imported, its containing package (if any) is imported, in order
|
||||||
to establish the package ``__path__``.
|
to establish the package ``__path__``.
|
||||||
|
|
||||||
This function uses :func:`iter_importers`, and is thus subject to the same
|
|
||||||
limitations regarding platform-specific special import locations such as the
|
|
||||||
Windows registry.
|
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
Updated to be based directly on :mod:`importlib` rather than relying
|
Updated to be based directly on :mod:`importlib` rather than relying
|
||||||
on the package internal PEP 302 import emulation.
|
on the package internal PEP 302 import emulation.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.4
|
||||||
|
Updated to be based on :pep:`451`
|
||||||
|
|
||||||
|
|
||||||
.. function:: iter_importers(fullname='')
|
.. function:: iter_importers(fullname='')
|
||||||
|
|
||||||
|
|
|
@ -470,29 +470,22 @@ def get_loader(module_or_name):
|
||||||
def find_loader(fullname):
|
def find_loader(fullname):
|
||||||
"""Find a PEP 302 "loader" object for fullname
|
"""Find a PEP 302 "loader" object for fullname
|
||||||
|
|
||||||
This is s convenience wrapper around :func:`importlib.find_loader` that
|
This is a backwards compatibility wrapper around
|
||||||
sets the *path* argument correctly when searching for submodules, and
|
importlib.util.find_spec that converts most failures to ImportError
|
||||||
also ensures parent packages (if any) are imported before searching for
|
and only returns the loader rather than the full spec
|
||||||
submodules.
|
|
||||||
"""
|
"""
|
||||||
if fullname.startswith('.'):
|
if fullname.startswith('.'):
|
||||||
msg = "Relative module name {!r} not supported".format(fullname)
|
msg = "Relative module name {!r} not supported".format(fullname)
|
||||||
raise ImportError(msg)
|
raise ImportError(msg)
|
||||||
path = None
|
|
||||||
pkg_name = fullname.rpartition(".")[0]
|
|
||||||
if pkg_name:
|
|
||||||
pkg = importlib.import_module(pkg_name)
|
|
||||||
path = getattr(pkg, "__path__", None)
|
|
||||||
if path is None:
|
|
||||||
return None
|
|
||||||
try:
|
try:
|
||||||
return importlib.find_loader(fullname, path)
|
spec = importlib.util.find_spec(fullname)
|
||||||
except (ImportError, AttributeError, TypeError, ValueError) as ex:
|
except (ImportError, AttributeError, TypeError, ValueError) as ex:
|
||||||
# This hack fixes an impedance mismatch between pkgutil and
|
# This hack fixes an impedance mismatch between pkgutil and
|
||||||
# importlib, where the latter raises other errors for cases where
|
# importlib, where the latter raises other errors for cases where
|
||||||
# pkgutil previously raised ImportError
|
# pkgutil previously raised ImportError
|
||||||
msg = "Error while finding loader for {!r} ({}: {})"
|
msg = "Error while finding loader for {!r} ({}: {})"
|
||||||
raise ImportError(msg.format(fullname, type(ex), ex)) from ex
|
raise ImportError(msg.format(fullname, type(ex), ex)) from ex
|
||||||
|
return spec.loader
|
||||||
|
|
||||||
|
|
||||||
def extend_path(path, name):
|
def extend_path(path, name):
|
||||||
|
|
|
@ -334,6 +334,25 @@ class ImportlibMigrationTests(unittest.TestCase):
|
||||||
self.assertIsNotNone(pkgutil.get_loader("test.support"))
|
self.assertIsNotNone(pkgutil.get_loader("test.support"))
|
||||||
self.assertEqual(len(w.warnings), 0)
|
self.assertEqual(len(w.warnings), 0)
|
||||||
|
|
||||||
|
def test_get_loader_handles_missing_loader_attribute(self):
|
||||||
|
global __loader__
|
||||||
|
this_loader = __loader__
|
||||||
|
del __loader__
|
||||||
|
try:
|
||||||
|
with check_warnings() as w:
|
||||||
|
self.assertIsNotNone(pkgutil.get_loader(__name__))
|
||||||
|
self.assertEqual(len(w.warnings), 0)
|
||||||
|
finally:
|
||||||
|
__loader__ = this_loader
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_loader_avoids_emulation(self):
|
||||||
|
with check_warnings() as w:
|
||||||
|
self.assertIsNotNone(pkgutil.find_loader("sys"))
|
||||||
|
self.assertIsNotNone(pkgutil.find_loader("os"))
|
||||||
|
self.assertIsNotNone(pkgutil.find_loader("test.support"))
|
||||||
|
self.assertEqual(len(w.warnings), 0)
|
||||||
|
|
||||||
def test_get_importer_avoids_emulation(self):
|
def test_get_importer_avoids_emulation(self):
|
||||||
# We use an illegal path so *none* of the path hooks should fire
|
# We use an illegal path so *none* of the path hooks should fire
|
||||||
with check_warnings() as w:
|
with check_warnings() as w:
|
||||||
|
|
|
@ -20,6 +20,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #20839: Don't trigger a DeprecationWarning in the still supported
|
||||||
|
pkgutil.get_loader() API when __loader__ isn't set on a module (nor
|
||||||
|
when pkgutil.find_loader() is called directly).
|
||||||
|
|
||||||
- Issue #20778: Fix modulefinder to work with bytecode-only modules.
|
- Issue #20778: Fix modulefinder to work with bytecode-only modules.
|
||||||
|
|
||||||
- Issue #20791: copy.copy() now doesn't make a copy when the input is
|
- Issue #20791: copy.copy() now doesn't make a copy when the input is
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue