Skip to content

Commit

Permalink
Omit sentinel values from a namespace path.
Browse files Browse the repository at this point in the history
When editable installs create sentinels, as they are not a valid directory, they're unsuitable for constructing a `MultiplexedPath`. Filter them out.

Fixes #311
  • Loading branch information
jaraco committed Sep 9, 2024
1 parent 47d73b1 commit 2c145c5
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 7 deletions.
12 changes: 8 additions & 4 deletions importlib_resources/readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,23 @@ class NamespaceReader(abc.TraversableResources):
def __init__(self, namespace_path):
if 'NamespacePath' not in str(namespace_path):
raise ValueError('Invalid path')
self.path = MultiplexedPath(*map(self._resolve, namespace_path))
self.path = MultiplexedPath(*filter(bool, map(self._resolve, namespace_path)))

@classmethod
def _resolve(cls, path_str) -> abc.Traversable:
def _resolve(cls, path_str) -> abc.Traversable | None:
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``.
path_str might also be a sentinel used by editable packages to
trigger other behaviors (see python/importlib_resources#311).
In that case, return None.
"""
(dir,) = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
return dir
dirs = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
return next(dirs, None)

@classmethod
def _candidate_paths(cls, path_str: str) -> Iterator[abc.Traversable]:
Expand Down
3 changes: 0 additions & 3 deletions importlib_resources/tests/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import importlib
import contextlib

import pytest

import importlib_resources as resources
from ..abc import Traversable
from . import util
Expand Down Expand Up @@ -62,7 +60,6 @@ class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
class OpenNamespaceTests(FilesTests, util.DiskSetup, unittest.TestCase):
MODULE = 'namespacedata01'

@pytest.mark.xfail(reason="#311")
def test_non_paths_in_dunder_path(self):
"""
Non-path items in a namespace package's ``__path__`` are ignored.
Expand Down
1 change: 1 addition & 0 deletions newsfragments/311.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Omit sentinel values from a namespace path.

0 comments on commit 2c145c5

Please sign in to comment.