Skip to content

Commit

Permalink
Merge pull request #290 from python/bugfix/namespace-packages-in-zip
Browse files Browse the repository at this point in the history
Fixed handling of namespace packages in zip files
  • Loading branch information
jaraco authored Sep 20, 2023
2 parents fe9dbf6 + a9b0c92 commit cb4bbdd
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 4 deletions.
30 changes: 29 additions & 1 deletion importlib_resources/readers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import collections
import contextlib
import itertools
import pathlib
import operator
import re

from . import abc

Expand Down Expand Up @@ -130,7 +132,33 @@ class NamespaceReader(abc.TraversableResources):
def __init__(self, namespace_path):
if 'NamespacePath' not in str(namespace_path):
raise ValueError('Invalid path')
self.path = MultiplexedPath(*list(namespace_path))
self.path = MultiplexedPath(*map(self._resolve, namespace_path))

@classmethod
def _resolve(cls, path_str) -> abc.Traversable:
r"""
Given an item from a namespace path, resolve it to a Traversable.
path_str might be a directory on the filesystem or a path to a
zipfile plus the path within the zipfile, e.g. ``/foo/bar`` or
``/foo/baz.zip/inner_dir`` or ``foo\baz.zip\inner_dir\sub``.
"""
(dir,) = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
return dir

@classmethod
def _candidate_paths(cls, path_str):
yield pathlib.Path(path_str)
yield from cls._resolve_zip_path(path_str)

@staticmethod
def _resolve_zip_path(path_str):
for match in reversed(list(re.finditer(r'[\\/]', path_str))):
with contextlib.suppress(
FileNotFoundError, IsADirectoryError, PermissionError
):
inner = path_str[match.end() :].replace('\\', '/') + '/'
yield ZipPath(path_str[: match.start()], inner.lstrip('/'))

def resource_path(self, resource):
"""
Expand Down
3 changes: 0 additions & 3 deletions importlib_resources/tests/test_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import importlib_resources as resources
import pathlib

import pytest

from . import data01
from . import util
from importlib import import_module
Expand Down Expand Up @@ -211,7 +209,6 @@ def tearDownClass(cls):
sys.path.remove(cls.site_dir)


@pytest.mark.xfail
class ResourceFromNamespaceZipTests(
util.ZipSetupBase,
ResourceFromNamespaceTests,
Expand Down
1 change: 1 addition & 0 deletions newsfragments/287.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enabled support for resources in namespace packages in zip files.

0 comments on commit cb4bbdd

Please sign in to comment.