diff --git a/importlib_resources/_adapters.py b/importlib_resources/_adapters.py index 50688fb..222888b 100644 --- a/importlib_resources/_adapters.py +++ b/importlib_resources/_adapters.py @@ -160,9 +160,9 @@ def files(self): return CompatibilityFiles.SpecPath(self.spec, self._reader) -def wrap_spec(package): +def wrap_spec(spec): """ Construct a package spec with traversable compatibility on the spec/loader/reader. """ - return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) + return SpecLoaderAdapter(spec, TraversableResourcesLoader) diff --git a/importlib_resources/_common.py b/importlib_resources/_common.py index 5f41c26..de6d84f 100644 --- a/importlib_resources/_common.py +++ b/importlib_resources/_common.py @@ -113,7 +113,13 @@ def from_package(package: types.ModuleType): # deferred for performance (python/cpython#109829) from .future.adapters import wrap_spec - spec = wrap_spec(package) + if package.__spec__ is None: + raise TypeError( + f"Cannot access resources for '{package.__name__ or package!r}' " + "as it does not appear to correspond to an importable module (its __spec__ is None)." + ) + + spec = wrap_spec(package.__spec__) reader = spec.loader.get_resource_reader(spec.name) return reader.files() diff --git a/importlib_resources/tests/test_resource.py b/importlib_resources/tests/test_resource.py index c80afdc..c02f0b0 100644 --- a/importlib_resources/tests/test_resource.py +++ b/importlib_resources/tests/test_resource.py @@ -1,3 +1,4 @@ +import types import unittest from importlib import import_module @@ -234,5 +235,17 @@ class ResourceFromNamespaceZipTests( MODULE = 'namespacedata01' +class ResourceFromMainModuleWithNoneSpecTests(unittest.TestCase): + # `__main__.__spec__` can be `None` depending on how it is populated. + # https://docs.python.org/3/reference/import.html#main-spec + def test_main_module_with_none_spec(self): + mainmodule = types.ModuleType("__main__") + + self.assertIsNone(mainmodule.__spec__) + + with self.assertRaises(TypeError, msg="Cannot access resources for '__main__' as it does not appear to correspond to an importable module (its __spec__ is None)."): + resources.files(mainmodule) + + if __name__ == '__main__': unittest.main()