From e9d7f88d5643f7e6387bf994c130503766d7eb92 Mon Sep 17 00:00:00 2001 From: Miguel Brito <5544985+miguendes@users.noreply.github.com> Date: Wed, 12 May 2021 00:27:22 +0100 Subject: [PATCH] bpo-44061: Fix pkgutil.iter_modules regression when passed a pathlib.Path object (GH-25964) --- Lib/pkgutil.py | 1 + Lib/test/test_pkgutil.py | 46 +++++++++++++++++++ .../2021-05-07-08-39-23.bpo-44061.MvElG6.rst | 2 + 3 files changed, 49 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-05-07-08-39-23.bpo-44061.MvElG6.rst diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py index 2c3429856be..48c1479ee6c 100644 --- a/Lib/pkgutil.py +++ b/Lib/pkgutil.py @@ -413,6 +413,7 @@ def get_importer(path_item): The cache (or part of it) can be cleared manually if a rescan of sys.path_hooks is necessary. """ + path_item = os.fsdecode(path_item) try: importer = sys.path_importer_cache[path_item] except KeyError: diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 6e3618f6b0f..3c29080f205 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -1,3 +1,4 @@ +from pathlib import Path from test.support import run_unittest from test.support.import_helper import unload, CleanImport from test.support.warnings_helper import check_warnings @@ -92,6 +93,45 @@ class PkgutilTests(unittest.TestCase): del sys.modules[pkg] + def test_issue44061_iter_modules(self): + #see: issue44061 + zip = 'test_getdata_zipfile.zip' + pkg = 'test_getdata_zipfile' + + # Include a LF and a CRLF, to test that binary data is read back + RESOURCE_DATA = b'Hello, world!\nSecond line\r\nThird line' + + # Make a package with some resources + zip_file = os.path.join(self.dirname, zip) + z = zipfile.ZipFile(zip_file, 'w') + + # Empty init.py + z.writestr(pkg + '/__init__.py', "") + # Resource files, res.txt + z.writestr(pkg + '/res.txt', RESOURCE_DATA) + z.close() + + # Check we can read the resources + sys.path.insert(0, zip_file) + try: + res = pkgutil.get_data(pkg, 'res.txt') + self.assertEqual(res, RESOURCE_DATA) + + # make sure iter_modules accepts Path objects + names = [] + for moduleinfo in pkgutil.iter_modules([Path(zip_file)]): + self.assertIsInstance(moduleinfo, pkgutil.ModuleInfo) + names.append(moduleinfo.name) + self.assertEqual(names, [pkg]) + finally: + del sys.path[0] + sys.modules.pop(pkg, None) + + # assert path must be None or list of paths + expected_msg = "path must be None or list of paths to look for modules in" + with self.assertRaisesRegex(ValueError, expected_msg): + list(pkgutil.iter_modules("invalid_path")) + def test_unreadable_dir_on_syspath(self): # issue7367 - walk_packages failed if unreadable dir on sys.path package_name = "unreadable_package" @@ -574,6 +614,12 @@ class ImportlibMigrationTests(unittest.TestCase): self.assertIsNone(pkgutil.get_importer("*??")) self.assertEqual(len(w.warnings), 0) + def test_issue44061(self): + try: + pkgutil.get_importer(Path("/home")) + except AttributeError: + self.fail("Unexpected AttributeError when calling get_importer") + def test_iter_importers_avoids_emulation(self): with check_warnings() as w: for importer in pkgutil.iter_importers(): pass diff --git a/Misc/NEWS.d/next/Library/2021-05-07-08-39-23.bpo-44061.MvElG6.rst b/Misc/NEWS.d/next/Library/2021-05-07-08-39-23.bpo-44061.MvElG6.rst new file mode 100644 index 00000000000..e41f285fae9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-05-07-08-39-23.bpo-44061.MvElG6.rst @@ -0,0 +1,2 @@ +Fix regression in previous release when calling :func:`pkgutil.iter_modules` +with a list of :class:`pathlib.Path` objects