Author William.Schwartz
Recipients William.Schwartz, brett.cannon
Date 2020-12-02.06:31:40
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1606890702.39.0.177441013455.issue42531@roundup.psfhosted.org>
In-reply-to
Content
Suppose pkg is a package, it contains a resource r, pkg.__spec__.origin is None, and p = importlib.resources.path(pkg, r). Then p.__enter__() raises a TypeError in Python 3.7 and 3.8. (The problem has been fixed in 3.9). The error can be demonstrated by running the attached path-test.py. The tracebacks in 3.7 and 3.8 are nearly identical, so I'll just show the 3.8 traceback.

3.8.6 (default, Nov 20 2020, 18:29:40) 
[Clang 12.0.0 (clang-1200.0.32.27)]
Traceback (most recent call last):
  File "path-test.py", line 19, in <module>
    p.__enter__()  # Kaboom
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/importlib/resources.py", line 196, in path
    package_directory = Path(package.__spec__.origin).parent
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pathlib.py", line 1041, in __new__
    self = cls._from_parts(args, init=False)
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pathlib.py", line 682, in _from_parts
    drv, root, parts = self._parse_args(args)
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pathlib.py", line 666, in _parse_args
    a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not NoneType

The fix is super simple, as shown below. I'll submit this as a PR as well.

diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py
index fc3a1c9cab..8d37d52cb8 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:
History
Date User Action Args
2020-12-02 06:31:42William.Schwartzsetrecipients: + William.Schwartz, brett.cannon
2020-12-02 06:31:42William.Schwartzsetmessageid: <1606890702.39.0.177441013455.issue42531@roundup.psfhosted.org>
2020-12-02 06:31:42William.Schwartzlinkissue42531 messages
2020-12-02 06:31:41William.Schwartzcreate