Skip to content

Commit 5a2bffc

Browse files
authored
A better error message from importlib.resources.files() when module spec is None
Pull request #331
2 parents c6773a1 + d80822a commit 5a2bffc

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

importlib_resources/_common.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ def is_wrapper(frame_info):
7171
return next(callers).frame
7272

7373

74+
def _assert_spec(package: types.ModuleType) -> None:
75+
"""
76+
Provide a nicer error message when package is ``__main__``
77+
and its ``__spec__`` is ``None``
78+
(https://docs.python.org/3/reference/import.html#main-spec).
79+
"""
80+
if package.__spec__ is None:
81+
raise TypeError(
82+
f"Cannot access resources for '{package.__name__}' "
83+
"as it does not appear to correspond to an importable module (its __spec__ is None)."
84+
)
85+
86+
7487
def from_package(package: types.ModuleType):
7588
"""
7689
Return a Traversable object for the given package.
@@ -79,6 +92,7 @@ def from_package(package: types.ModuleType):
7992
# deferred for performance (python/cpython#109829)
8093
from .future.adapters import wrap_spec
8194

95+
_assert_spec(package)
8296
spec = wrap_spec(package)
8397
reader = spec.loader.get_resource_reader(spec.name)
8498
return reader.files()

importlib_resources/tests/test_resource.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import types
12
import unittest
23
from importlib import import_module
34

@@ -219,5 +220,24 @@ class ResourceFromNamespaceZipTests(
219220
MODULE = 'namespacedata01'
220221

221222

223+
class MainModuleTests(unittest.TestCase):
224+
def test_main_module_with_none_spec(self):
225+
"""
226+
__main__ module with no spec should raise TypeError (for clarity).
227+
228+
See python/cpython#138531 for details.
229+
"""
230+
# construct a __main__ module with no __spec__.
231+
mainmodule = types.ModuleType("__main__")
232+
233+
assert mainmodule.__spec__ is None
234+
235+
with self.assertRaises(
236+
TypeError,
237+
msg="Cannot access resources for '__main__' as it does not appear to correspond to an importable module (its __spec__ is None).",
238+
):
239+
resources.files(mainmodule)
240+
241+
222242
if __name__ == '__main__':
223243
unittest.main()

newsfragments/331.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``files()`` now provides a nicer error when __main__.__spec__ is None.

0 commit comments

Comments
 (0)