mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
Issue #14938: importlib.abc.SourceLoader.is_package() now takes the
module name into consideration when determining whether a module is a package or not. This prevents importing a module's __init__ module directly and having it considered a package, which can lead to duplicate sub-modules. Thanks to Ronan Lamy for reporting the bug.
This commit is contained in:
parent
0450c9ed52
commit
ea0b823940
4 changed files with 14 additions and 5 deletions
|
@ -351,8 +351,10 @@ are also provided to help in implementing the core ABCs.
|
||||||
.. method:: is_package(self, fullname)
|
.. method:: is_package(self, fullname)
|
||||||
|
|
||||||
Concrete implementation of :meth:`InspectLoader.is_package`. A module
|
Concrete implementation of :meth:`InspectLoader.is_package`. A module
|
||||||
is determined to be a package if its file path is a file named
|
is determined to be a package if its file path (as provided by
|
||||||
``__init__`` when the file extension is removed.
|
:meth:`ExecutionLoader.get_filename`) is a file named
|
||||||
|
``__init__`` when the file extension is removed **and** the module name
|
||||||
|
itself does not end in ``__init__``.
|
||||||
|
|
||||||
|
|
||||||
.. class:: PyLoader
|
.. class:: PyLoader
|
||||||
|
|
|
@ -578,7 +578,9 @@ class _LoaderBasics:
|
||||||
"""Concrete implementation of InspectLoader.is_package by checking if
|
"""Concrete implementation of InspectLoader.is_package by checking if
|
||||||
the path returned by get_filename has a filename of '__init__.py'."""
|
the path returned by get_filename has a filename of '__init__.py'."""
|
||||||
filename = _path_split(self.get_filename(fullname))[1]
|
filename = _path_split(self.get_filename(fullname))[1]
|
||||||
return filename.rsplit('.', 1)[0] == '__init__'
|
filename_base = filename.rsplit('.', 1)[0]
|
||||||
|
tail_name = fullname.rpartition('.')[2]
|
||||||
|
return filename_base == '__init__' and tail_name != '__init__'
|
||||||
|
|
||||||
def _bytes_from_bytecode(self, fullname, data, bytecode_path, source_stats):
|
def _bytes_from_bytecode(self, fullname, data, bytecode_path, source_stats):
|
||||||
"""Return the marshalled bytes from bytecode, verifying the magic
|
"""Return the marshalled bytes from bytecode, verifying the magic
|
||||||
|
|
|
@ -602,10 +602,11 @@ class SourceOnlyLoaderTests(SourceLoaderTestHarness):
|
||||||
|
|
||||||
def test_is_package(self):
|
def test_is_package(self):
|
||||||
# Properly detect when loading a package.
|
# Properly detect when loading a package.
|
||||||
self.setUp(is_package=True)
|
|
||||||
self.assertTrue(self.loader.is_package(self.name))
|
|
||||||
self.setUp(is_package=False)
|
self.setUp(is_package=False)
|
||||||
self.assertFalse(self.loader.is_package(self.name))
|
self.assertFalse(self.loader.is_package(self.name))
|
||||||
|
self.setUp(is_package=True)
|
||||||
|
self.assertTrue(self.loader.is_package(self.name))
|
||||||
|
self.assertFalse(self.loader.is_package(self.name + '.__init__'))
|
||||||
|
|
||||||
def test_get_code(self):
|
def test_get_code(self):
|
||||||
# Verify the code object is created.
|
# Verify the code object is created.
|
||||||
|
|
|
@ -24,6 +24,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #14938: importlib.abc.SourceLoader.is_package() will not consider a
|
||||||
|
module whose name ends in '__init__' a package (e.g. importing pkg.__init__
|
||||||
|
directly should be considered a module, not a package).
|
||||||
|
|
||||||
- Issue #14982: Document that pkgutil's iteration functions require the
|
- Issue #14982: Document that pkgutil's iteration functions require the
|
||||||
non-standard iter_modules() method to be defined by an importer (something
|
non-standard iter_modules() method to be defined by an importer (something
|
||||||
the importlib importers do not define).
|
the importlib importers do not define).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue