Skip to content

Commit c9a1aae

Browse files
committed
Omit sentinel values from a namespace path.
When editable installs create sentinels, as they are not a valid directory, they're unsuitable for constructing a `MultiplexedPath`. Filter them out. Fixes #311
1 parent b06b5fb commit c9a1aae

File tree

3 files changed

+10
-7
lines changed

3 files changed

+10
-7
lines changed

importlib_resources/readers.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import operator
66
import re
77
import warnings
8+
from typing import Optional
89

910
from . import abc
1011

@@ -135,19 +136,23 @@ class NamespaceReader(abc.TraversableResources):
135136
def __init__(self, namespace_path):
136137
if 'NamespacePath' not in str(namespace_path):
137138
raise ValueError('Invalid path')
138-
self.path = MultiplexedPath(*map(self._resolve, namespace_path))
139+
self.path = MultiplexedPath(*filter(bool, map(self._resolve, namespace_path)))
139140

140141
@classmethod
141-
def _resolve(cls, path_str) -> abc.Traversable:
142+
def _resolve(cls, path_str) -> Optional[abc.Traversable]:
142143
r"""
143144
Given an item from a namespace path, resolve it to a Traversable.
144145
145146
path_str might be a directory on the filesystem or a path to a
146147
zipfile plus the path within the zipfile, e.g. ``/foo/bar`` or
147148
``/foo/baz.zip/inner_dir`` or ``foo\baz.zip\inner_dir\sub``.
149+
150+
path_str might also be a sentinel used by editable packages to
151+
trigger other behaviors (see python/importlib_resources#311).
152+
In that case, return None.
148153
"""
149-
(dir,) = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
150-
return dir
154+
dirs = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
155+
return next(dirs, None)
151156

152157
@classmethod
153158
def _candidate_paths(cls, path_str):

importlib_resources/tests/test_files.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import importlib
99
import contextlib
1010

11-
import pytest
12-
1311
import importlib_resources as resources
1412
from ..abc import Traversable
1513
from . import util
@@ -62,7 +60,6 @@ class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase):
6260
class OpenNamespaceTests(FilesTests, util.DiskSetup, unittest.TestCase):
6361
MODULE = 'namespacedata01'
6462

65-
@pytest.mark.xfail(reason="#311")
6663
def test_non_paths_in_dunder_path(self):
6764
"""
6865
Non-path items in a namespace package's ``__path__`` are ignored.

newsfragments/311.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Omit sentinel values from a namespace path.

0 commit comments

Comments
 (0)