Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ea0b823

Browse files
committed
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.
1 parent 0450c9e commit ea0b823

4 files changed

Lines changed: 14 additions & 5 deletions

File tree

Doc/library/importlib.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,10 @@ are also provided to help in implementing the core ABCs.
351351
.. method:: is_package(self, fullname)
352352

353353
Concrete implementation of :meth:`InspectLoader.is_package`. A module
354-
is determined to be a package if its file path is a file named
355-
``__init__`` when the file extension is removed.
354+
is determined to be a package if its file path (as provided by
355+
:meth:`ExecutionLoader.get_filename`) is a file named
356+
``__init__`` when the file extension is removed **and** the module name
357+
itself does not end in ``__init__``.
356358

357359

358360
.. class:: PyLoader

Lib/importlib/_bootstrap.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,9 @@ def is_package(self, fullname):
578578
"""Concrete implementation of InspectLoader.is_package by checking if
579579
the path returned by get_filename has a filename of '__init__.py'."""
580580
filename = _path_split(self.get_filename(fullname))[1]
581-
return filename.rsplit('.', 1)[0] == '__init__'
581+
filename_base = filename.rsplit('.', 1)[0]
582+
tail_name = fullname.rpartition('.')[2]
583+
return filename_base == '__init__' and tail_name != '__init__'
582584

583585
def _bytes_from_bytecode(self, fullname, data, bytecode_path, source_stats):
584586
"""Return the marshalled bytes from bytecode, verifying the magic

Lib/importlib/test/source/test_abc_loader.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,10 +602,11 @@ def raise_IOError(path):
602602

603603
def test_is_package(self):
604604
# Properly detect when loading a package.
605-
self.setUp(is_package=True)
606-
self.assertTrue(self.loader.is_package(self.name))
607605
self.setUp(is_package=False)
608606
self.assertFalse(self.loader.is_package(self.name))
607+
self.setUp(is_package=True)
608+
self.assertTrue(self.loader.is_package(self.name))
609+
self.assertFalse(self.loader.is_package(self.name + '.__init__'))
609610

610611
def test_get_code(self):
611612
# Verify the code object is created.

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ Core and Builtins
2424
Library
2525
-------
2626

27+
- Issue #14938: importlib.abc.SourceLoader.is_package() will not consider a
28+
module whose name ends in '__init__' a package (e.g. importing pkg.__init__
29+
directly should be considered a module, not a package).
30+
2731
- Issue #14982: Document that pkgutil's iteration functions require the
2832
non-standard iter_modules() method to be defined by an importer (something
2933
the importlib importers do not define).

0 commit comments

Comments
 (0)