]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-121735: Fix module-adjacent references in zip files (gh-123037) (#124011)
authorJason R. Coombs <jaraco@jaraco.com>
Tue, 24 Sep 2024 17:19:43 +0000 (13:19 -0400)
committerGitHub <noreply@github.com>
Tue, 24 Sep 2024 17:19:43 +0000 (10:19 -0700)
Lib/importlib/resources/readers.py
Lib/test/test_importlib/resources/test_files.py
Lib/zipimport.py
Misc/NEWS.d/next/Library/2024-08-15-09-45-34.gh-issue-121735._1q0qf.rst [new file with mode: 0644]

index c3cdf769cbecb00c20da5ae8fad3a60f737a27d1..8e2d8e8250bd7ed3aa914ad4b726277c7d0694aa 100644 (file)
@@ -31,8 +31,10 @@ class FileReader(abc.TraversableResources):
 
 class ZipReader(abc.TraversableResources):
     def __init__(self, loader, module):
-        _, _, name = module.rpartition('.')
-        self.prefix = loader.prefix.replace('\\', '/') + name + '/'
+        self.prefix = loader.prefix.replace('\\', '/')
+        if loader.is_package(module):
+            _, _, name = module.rpartition('.')
+            self.prefix += name + '/'
         self.archive = loader.archive
 
     def open_resource(self, resource):
index 26c8b04e44c3b9b3ef34116419ff4c3ea59d6c00..038aac0a3fe77378f1dda2719fa40c445100e3db 100644 (file)
@@ -108,6 +108,42 @@ class ImplicitContextFilesTests(SiteDir, unittest.TestCase):
         _path.build(spec, self.site_dir)
         assert importlib.import_module('somepkg').val == 'resources are the best'
 
+    def test_implicit_files_zip_submodule(self):
+        """
+        Special test for gh-121735 for Python 3.12.
+        """
+        import os
+        import zipfile
+
+        def create_zip_from_directory(source_dir, zip_filename):
+            with zipfile.ZipFile(zip_filename, 'w') as zipf:
+                for root, _, files in os.walk(source_dir):
+                    for file in files:
+                        file_path = os.path.join(root, file)
+                        # Ensure files are at the root
+                        arcname = os.path.relpath(file_path, source_dir)
+                        zipf.write(file_path, arcname)
+
+        set_val = textwrap.dedent(
+            """
+            import importlib.resources as res
+            val = res.files().joinpath('res.txt').read_text(encoding='utf-8')
+            """
+        )
+        spec = {
+            'somepkg': {
+                '__init__.py': set_val,
+                'submod.py': set_val,
+                'res.txt': 'resources are the best',
+            },
+        }
+        build_dir = self.fixtures.enter_context(os_helper.temp_dir())
+        _path.build(spec, build_dir)
+        zip_file = os.path.join(self.site_dir, 'thepkg.zip')
+        create_zip_from_directory(build_dir, zip_file)
+        self.fixtures.enter_context(import_helper.DirsOnSysPath(zip_file))
+        assert importlib.import_module('somepkg.submod').val == 'resources are the best'
+
 
 if __name__ == '__main__':
     unittest.main()
index a7333a4c4906dea86b88208dffa37becb6b30a45..7669abd6c472e68459e2f55b034d2b6c6821dc28 100644 (file)
@@ -254,17 +254,9 @@ class zipimporter(_bootstrap_external._LoaderBasics):
 
 
     def get_resource_reader(self, fullname):
-        """Return the ResourceReader for a package in a zip file.
-
-        If 'fullname' is a package within the zip file, return the
-        'ResourceReader' object for the package.  Otherwise return None.
-        """
-        try:
-            if not self.is_package(fullname):
-                return None
-        except ZipImportError:
-            return None
+        """Return the ResourceReader for a module in a zip file."""
         from importlib.readers import ZipReader
+
         return ZipReader(self, fullname)
 
 
diff --git a/Misc/NEWS.d/next/Library/2024-08-15-09-45-34.gh-issue-121735._1q0qf.rst b/Misc/NEWS.d/next/Library/2024-08-15-09-45-34.gh-issue-121735._1q0qf.rst
new file mode 100644 (file)
index 0000000..e10b2e7
--- /dev/null
@@ -0,0 +1,3 @@
+When working with zip archives, importlib.resources now properly honors
+module-adjacent references (e.g. ``files(pkg.mod)`` and not just
+``files(pkg)``).