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 Aug 20, 2024
1 parent b06b5fb commit ae4b882
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 7 deletions.
14 changes: 10 additions & 4 deletions importlib_resources/readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import operator
import re
import warnings
from typing import Optional

from . import abc

Expand Down Expand Up @@ -135,19 +136,24 @@ 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) -> Optional[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``.
path_str might also be a sentinel used by editable packages to
trigger other behaviors
(https://github.com/python/importlib_resources/issues/311#issuecomment-2298128943).
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):
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 ae4b882

Please sign in to comment.