Skip to content

Commit

Permalink
utils: implement path_isin to compare child and parent paths
Browse files Browse the repository at this point in the history
  • Loading branch information
skshetry committed Nov 18, 2019
1 parent 0ac18fb commit 68c7366
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 1 deletion.
11 changes: 11 additions & 0 deletions dvc/utils/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,14 @@ def remove(path):
except OSError as exc:
if exc.errno != errno.ENOENT:
raise


def path_isin(child, parent):
"""Check if given `child` path is inside `parent`."""

def normalize_path(path):
return os.path.normpath(fspath(path))

parent = os.path.join(normalize_path(parent), "")
child = normalize_path(child)
return child != parent and child.startswith(parent)
48 changes: 47 additions & 1 deletion tests/unit/utils/test_fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from dvc.utils.fs import get_inode
from dvc.utils.fs import get_mtime_and_size
from dvc.utils.fs import move
from dvc.utils.fs import remove
from dvc.utils.fs import path_isin, remove
from tests.basic_env import TestDir
from tests.utils import spy

Expand Down Expand Up @@ -164,3 +164,49 @@ def test_remove(repo_dir):

remove(path_info)
assert not os.path.isfile(path_info.fspath)


@pytest.mark.parametrize(
"parent",
[
(os.path.join("path", "to", "")),
(os.path.join("path", "to")),
(os.path.join("path", "")),
(os.path.join("path")),
],
)
def test_path_isin_positive(parent):
child = os.path.join("path", "to", "folder")
assert path_isin(child, parent)


def test_path_isin_on_same_path():
path = os.path.join("path", "to", "folder")
path2 = os.path.join(path, "")

assert not path_isin(path, path)
assert not path_isin(path, path2)
assert not path_isin(path2, path)
assert not path_isin(path2, path2)


def test_path_isin_on_common_substring_path():
path1 = os.path.join("path", "to", "folder1")
path2 = os.path.join("path", "to", "folder")

assert not path_isin(path1, path2)


def test_path_isin_accepts_pathinfo():
child = os.path.join("path", "to", "folder")
parent = PathInfo(child) / ".."

assert path_isin(child, parent)
assert not path_isin(parent, child)


def test_path_isin_with_absolute_path():
parent = os.path.abspath("path")
child = os.path.join(parent, "to", "folder")

assert path_isin(child, parent)

0 comments on commit 68c7366

Please sign in to comment.