Skip to content

Commit 078c801

Browse files
committed
Raise an exception with a better message from importlib.resources.files() when module spec is not available
1 parent e9c2a35 commit 078c801

3 files changed

Lines changed: 24 additions & 4 deletions

File tree

Lib/importlib/resources/_adapters.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33

44
from . import abc
55

6+
TYPE_CHECKING = False
7+
if TYPE_CHECKING:
8+
from ..machinery import ModuleSpec
9+
610

711
class SpecLoaderAdapter:
812
"""
913
Adapt a package spec to adapt the underlying loader.
1014
"""
1115

12-
def __init__(self, spec, adapter=lambda spec: spec.loader):
16+
def __init__(self, spec: ModuleSpec, adapter):
1317
self.spec = spec
1418
self.loader = adapter(spec)
1519

@@ -160,9 +164,9 @@ def files(self):
160164
return CompatibilityFiles.SpecPath(self.spec, self._reader)
161165

162166

163-
def wrap_spec(package):
167+
def wrap_spec(spec: ModuleSpec):
164168
"""
165169
Construct a package spec with traversable compatibility
166170
on the spec/loader/reader.
167171
"""
168-
return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader)
172+
return SpecLoaderAdapter(spec, TraversableResourcesLoader)

Lib/importlib/resources/_common.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ def from_package(package: types.ModuleType):
113113
# deferred for performance (python/cpython#109829)
114114
from ._adapters import wrap_spec
115115

116-
spec = wrap_spec(package)
116+
if package.__spec__ is None:
117+
raise TypeError(f"Can't access resources on a module with no spec: {package}")
118+
119+
spec = wrap_spec(package.__spec__)
117120
reader = spec.loader.get_resource_reader(spec.name)
118121
return reader.files()
119122

Lib/test/test_importlib/resources/test_resource.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import unittest
2+
import types
23

34
from . import util
45
from importlib import resources, import_module
@@ -232,5 +233,17 @@ class ResourceFromNamespaceZipTests(
232233
MODULE = 'namespacedata01'
233234

234235

236+
class ResourceFromMainModuleWithNoneSpecTests(unittest.TestCase):
237+
# `__main__.__spec__` can be `None` depending on how it is populated.
238+
# https://docs.python.org/3/reference/import.html#main-spec
239+
def test_main_module_with_none_spec(self):
240+
mainmodule = types.ModuleType("__main__")
241+
242+
self.assertIsNone(mainmodule.__spec__)
243+
244+
with self.assertRaises(TypeError):
245+
resources.files(mainmodule)
246+
247+
235248
if __name__ == '__main__':
236249
unittest.main()

0 commit comments

Comments
 (0)