summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2012-06-16 00:00:53 (GMT)
committerBrett Cannon <brett@python.org>2012-06-16 00:00:53 (GMT)
commitea0b8239401123fa7f41c74f6fc9ded1cf74088a (patch)
tree6d5afa0b55c1c5e1e39770d062b25d81a231535b
parent0450c9ed52deccd087c56b4da36f02c800c604a5 (diff)
downloadcpython-ea0b8239401123fa7f41c74f6fc9ded1cf74088a.zip
cpython-ea0b8239401123fa7f41c74f6fc9ded1cf74088a.tar.gz
cpython-ea0b8239401123fa7f41c74f6fc9ded1cf74088a.tar.bz2
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.
-rw-r--r--Doc/library/importlib.rst6
-rw-r--r--Lib/importlib/_bootstrap.py4
-rw-r--r--Lib/importlib/test/source/test_abc_loader.py5
-rw-r--r--Misc/NEWS4
4 files changed, 14 insertions, 5 deletions
diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst
index 35a99bf..9dc6ed1 100644
--- a/Doc/library/importlib.rst
+++ b/Doc/library/importlib.rst
@@ -351,8 +351,10 @@ are also provided to help in implementing the core ABCs.
.. method:: is_package(self, fullname)
Concrete implementation of :meth:`InspectLoader.is_package`. A module
- is determined to be a package if its file path is a file named
- ``__init__`` when the file extension is removed.
+ is determined to be a package if its file path (as provided by
+ :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
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index 6656db3..117c0f6 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -578,7 +578,9 @@ class _LoaderBasics:
"""Concrete implementation of InspectLoader.is_package by checking if
the path returned by get_filename has a filename of '__init__.py'."""
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):
"""Return the marshalled bytes from bytecode, verifying the magic
diff --git a/Lib/importlib/test/source/test_abc_loader.py b/Lib/importlib/test/source/test_abc_loader.py
index b1b1204..fc98b93 100644
--- a/Lib/importlib/test/source/test_abc_loader.py
+++ b/Lib/importlib/test/source/test_abc_loader.py
@@ -602,10 +602,11 @@ class SourceOnlyLoaderTests(SourceLoaderTestHarness):
def test_is_package(self):
# 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.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):
# Verify the code object is created.
diff --git a/Misc/NEWS b/Misc/NEWS
index d45c5b5..9e7df25 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,10 @@ Core and Builtins
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
non-standard iter_modules() method to be defined by an importer (something
the importlib importers do not define).