Skip to content

Commit fb03867

Browse files
committed
Define the behavior for package
1 parent 2e19f6a commit fb03867

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

Doc/library/importlib.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,9 @@ an :term:`importer`.
12451245
Load a module from a filename: execute the module and add it to
12461246
:data:`sys.modules`.
12471247

1248+
A package cannot be imported by its directory path, whereas its
1249+
``__init__.py`` file (ex: ``package/__init__.py``) can be imported.
1250+
12481251
.. versionadded:: 3.12
12491252

12501253
.. function:: source_hash(source_bytes)

Lib/test/test_importlib/test_util.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,13 @@ def test_complete_multi_phase_init_module(self):
761761

762762

763763
class LoadSourceTests(unittest.TestCase):
764+
def check_module(self, mod, modname, filename):
765+
self.assertIsInstance(mod, types.ModuleType)
766+
self.assertEqual(mod.__name__, modname)
767+
self.assertEqual(mod.__file__, filename)
768+
self.assertIn(modname, sys.modules)
769+
self.assertIs(sys.modules[modname], mod)
770+
764771
def test_load_source_path(self):
765772
modname = 'test_load_source_path_mod'
766773
filename = 'load_source_path_filename'
@@ -775,13 +782,33 @@ def test_load_source_path(self):
775782

776783
mod = importlib.util.load_source_path(modname, filename)
777784

778-
self.assertIsInstance(mod, types.ModuleType)
779-
self.assertEqual(mod.__name__, modname)
780-
self.assertEqual(mod.__file__, filename)
781-
self.assertIn(modname, sys.modules)
782-
self.assertIs(sys.modules[modname], mod)
785+
self.check_module(mod, modname, filename)
783786
self.assertEqual(mod.attr, 'load_source_path_attr')
784787

788+
def test_package(self):
789+
modname = 'test_load_source_path_package'
790+
dirname = 'load_source_path_dir'
791+
filename = os.path.join('load_source_path_dir', '__init__.py')
792+
793+
self.assertNotIn(modname, sys.modules)
794+
self.addCleanup(import_helper.unload, modname)
795+
796+
# Use a temporary directory to remove __pycache__/ subdirectory
797+
with fixtures.tempdir_as_cwd():
798+
os.mkdir(dirname)
799+
with open(filename, "w", encoding="utf8") as fp:
800+
print("attr = 'load_source_path_pkg'", file=fp)
801+
802+
# Package cannot be imported from a directory
803+
with self.assertRaises(IsADirectoryError):
804+
importlib.util.load_source_path(modname, dirname)
805+
806+
# Loading a package __init__.py file is ok
807+
mod = importlib.util.load_source_path(modname, filename)
808+
809+
self.check_module(mod, modname, filename)
810+
self.assertEqual(mod.attr, 'load_source_path_pkg')
811+
785812

786813
if __name__ == '__main__':
787814
unittest.main()

0 commit comments

Comments
 (0)