Skip to content

Commit 463331b

Browse files
committed
When constructing a MultiplexedPath, resolve submodule_search_locations to Traversable objects. Closes #287.
1 parent f23b743 commit 463331b

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

importlib_resources/readers.py

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import collections
2+
import contextlib
23
import itertools
34
import pathlib
45
import operator
6+
import re
57

68
from . import abc
79

@@ -130,7 +132,31 @@ class NamespaceReader(abc.TraversableResources):
130132
def __init__(self, namespace_path):
131133
if 'NamespacePath' not in str(namespace_path):
132134
raise ValueError('Invalid path')
133-
self.path = MultiplexedPath(*list(namespace_path))
135+
self.path = MultiplexedPath(*map(self._resolve, namespace_path))
136+
137+
@classmethod
138+
def _resolve(cls, path_str) -> abc.Traversable:
139+
"""
140+
Given an item from a namespace path, resolve it to a Traversable.
141+
142+
path_str might be a directory on the filesystem or a path to a
143+
zipfile plus the path within the zipfile, e.g. ``/foo/bar`` or
144+
``/foo/baz.zip/inner_dir``.
145+
"""
146+
(dir,) = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
147+
return dir
148+
149+
@classmethod
150+
def _candidate_paths(cls, path_str):
151+
yield pathlib.Path(path_str)
152+
yield from cls._resolve_zip_path(path_str)
153+
154+
@staticmethod
155+
def _resolve_zip_path(path_str):
156+
for match in reversed(list(re.finditer('/', path_str))):
157+
with contextlib.suppress(FileNotFoundError, IsADirectoryError):
158+
inner = path_str[match.end() :]
159+
yield ZipPath(path_str[: match.start()], inner + '/' * len(inner))
134160

135161
def resource_path(self, resource):
136162
"""

importlib_resources/tests/test_resource.py

-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import importlib_resources as resources
44
import pathlib
55

6-
import pytest
7-
86
from . import data01
97
from . import util
108
from importlib import import_module
@@ -211,7 +209,6 @@ def tearDownClass(cls):
211209
sys.path.remove(cls.site_dir)
212210

213211

214-
@pytest.mark.xfail
215212
class ResourceFromNamespaceZipTests(
216213
util.ZipSetupBase,
217214
ResourceFromNamespaceTests,

newsfragments/287.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enabled support for resources in namespace packages in zip files.

0 commit comments

Comments
 (0)