]> granicus.if.org Git - python/commitdiff
Issue #14938: importlib.abc.SourceLoader.is_package() now takes the
authorBrett Cannon <brett@python.org>
Sat, 16 Jun 2012 00:00:53 +0000 (20:00 -0400)
committerBrett Cannon <brett@python.org>
Sat, 16 Jun 2012 00:00:53 +0000 (20:00 -0400)
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.

Doc/library/importlib.rst
Lib/importlib/_bootstrap.py
Lib/importlib/test/source/test_abc_loader.py
Misc/NEWS

index 35a99bf0f5e783cdf98d9b18b59465829c00f80c..9dc6ed15ba0ceec19dbc34553fcf72376d03cc4c 100644 (file)
@@ -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
index 6656db3601b23182b7dc182199b060e0e1386c00..117c0f61bd567b565e8a04e674dce8330207e92f 100644 (file)
@@ -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
index b1b1204197fa30024fe2c2377382f2c937cee18a..fc98b93b82b3a11a6a36ad20bd121fa1aff606d2 100644 (file)
@@ -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.
index d45c5b54982e99a97aeca6b7cc22cbb307828b7b..9e7df250d2665b4bb2f60e7366d9902baa9c9ee8 100644 (file)
--- 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).