[New-bugs-announce] [issue42531] importlib.resources.path() raises TypeError for packages without __file__

William Schwartz report at bugs.python.org
Wed Dec 2 01:31:42 EST 2020

New submission from William Schwartz <wkschwartz at gmail.com>:

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 at 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 at 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 at 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 at 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 at 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]:
     # 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
         with open_binary(package, resource) as fp:

components: Library (Lib)
files: path-test.py
messages: 382297
nosy: William.Schwartz, brett.cannon
priority: normal
severity: normal
status: open
title: importlib.resources.path() raises TypeError for packages without __file__
type: behavior
versions: Python 3.7, Python 3.8
Added file: https://bugs.python.org/file49643/path-test.py

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list