[Python-checkins] [3.8] bpo-42531: Teach importlib.resources.path to handle packages without __file__ (GH-23611)

miss-islington webhook-mailer at python.org
Sat Jan 16 12:22:30 EST 2021


https://github.com/python/cpython/commit/f08c66467d56c71f75c6659ede9177449fe9d2e6
commit: f08c66467d56c71f75c6659ede9177449fe9d2e6
branch: 3.8
author: William Schwartz <wkschwartz at gmail.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2021-01-16T09:22:21-08:00
summary:

[3.8] bpo-42531: Teach importlib.resources.path to handle packages without __file__ (GH-23611)



Fixes [bpo-42531]() for Python 3.8.

The issue also applies to 3.7. If this PR looks like it'll be accepted, I can cherry-pick it to the 3.7 branch and submit a follow-up PR.

Automerge-Triggered-By: GH:jaraco

files:
A Misc/NEWS.d/next/Library/2020-12-02-16-28-04.bpo-42531.2sLlFW.rst
M Lib/importlib/resources.py
M Lib/test/test_importlib/test_path.py

diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py
index fc3a1c9cabe63..8d37d52cb8d37 100644
--- a/Lib/importlib/resources.py
+++ b/Lib/importlib/resources.py
@@ -193,9 +193,11 @@ def path(package: Package, resource: Resource) -> Iterator[Path]:
         _check_location(package)
     # Fall-through for both the lack of resource_path() *and* if
     # resource_path() raises FileNotFoundError.
-    package_directory = Path(package.__spec__.origin).parent
-    file_path = package_directory / resource
-    if file_path.exists():
+    file_path = None
+    if package.__spec__.origin is not None:
+        package_directory = Path(package.__spec__.origin).parent
+        file_path = package_directory / resource
+    if file_path is not None and file_path.exists():
         yield file_path
     else:
         with open_binary(package, resource) as fp:
diff --git a/Lib/test/test_importlib/test_path.py b/Lib/test/test_importlib/test_path.py
index 2d3dcda7ed2e7..5c5a8e3d76e79 100644
--- a/Lib/test/test_importlib/test_path.py
+++ b/Lib/test/test_importlib/test_path.py
@@ -1,3 +1,4 @@
+import io
 import unittest
 
 from importlib import resources
@@ -27,6 +28,17 @@ class PathDiskTests(PathTests, unittest.TestCase):
     data = data01
 
 
+class PathMemoryTests(PathTests, unittest.TestCase):
+    def setUp(self):
+        file = io.BytesIO(b'Hello, UTF-8 world!\n')
+        self.addCleanup(file.close)
+        self.data = util.create_package(
+            file=file, path=FileNotFoundError("package exists only in memory")
+        )
+        self.data.__spec__.origin = None
+        self.data.__spec__.has_location = False
+
+
 class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase):
     def test_remove_in_context_manager(self):
         # It is not an error if the file that was temporarily stashed on the
diff --git a/Misc/NEWS.d/next/Library/2020-12-02-16-28-04.bpo-42531.2sLlFW.rst b/Misc/NEWS.d/next/Library/2020-12-02-16-28-04.bpo-42531.2sLlFW.rst
new file mode 100644
index 0000000000000..7927078acda43
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-12-02-16-28-04.bpo-42531.2sLlFW.rst
@@ -0,0 +1 @@
+:func:`importlib.resources.path` now works for :term:`package`\ s missing the optional :attr:`__file__` attribute (more specifically, packages whose :attr:`__spec__`\ ``.``\ :attr:`~importlib.machinery.ModuleSpec.origin` :keyword:`is` :data:`None`).
\ No newline at end of file



More information about the Python-checkins mailing list