Skip to content

bpo-44061: Fix pkgutil.iter_modules regression #25964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Lib/pkgutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
46 changes: 46 additions & 0 deletions Lib/test/test_pkgutil.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -92,6 +93,45 @@ def test_getdata_zipfile(self):

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"
Expand Down Expand Up @@ -574,6 +614,12 @@ def test_get_importer_avoids_emulation(self):
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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix regression in previous release when calling :func:`pkgutil.iter_modules`
with a list of :class:`pathlib.Path` objects