Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions tuber/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from pathlib import Path
from typing import Optional, Union
from typing import Iterable, Optional, Union

# This covers 99% of Python projects. For simplicity, stop at the first one
# found.

ROOT_INDICATORS = {
DEFAULT_ROOT_INDICATORS = {
".git",
".hg",
"pyproject.toml",
Expand All @@ -17,7 +17,10 @@ class RootException(ValueError):
pass


def get_root(path: Optional[Union[Path, str]] = None) -> Path:
def get_root(
path: Optional[Union[Path, str]] = None,
root_indicators: Iterable[str] = DEFAULT_ROOT_INDICATORS,
) -> Path:
if path is None:
path = Path(".")
if not isinstance(path, Path):
Expand All @@ -30,7 +33,7 @@ def get_root(path: Optional[Union[Path, str]] = None) -> Path:
raise RootException(f"{path} is not a directory")

while True:
if any((path / x).exists() for x in ROOT_INDICATORS):
if any((path / x).exists() for x in root_indicators):
return path
parent = path.parent

Expand Down
17 changes: 16 additions & 1 deletion tuber/tests/get_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_invalid_dir_raises(self) -> None:
):
get_root(Path("/"))

def test_various_indicators(self) -> None:
def test_default_root_indicators(self) -> None:
for ind in (".git", "pyproject.toml"):
with volatile.dir() as d:
dp = Path(d).resolve()
Expand All @@ -41,6 +41,21 @@ def test_various_indicators(self) -> None:
(dp / "x").mkdir()
self.assertEqual(dp, get_root(dp / "x"))

def test_custom_root_indicators(self) -> None:
for iterable_type in [list, set, tuple]:
with volatile.dir() as d:
dp = Path(d).resolve()

# doesn't matter if it's a dir or file currently
(dp / ".git").write_text("")
self.assertEqual(
dp, get_root(dp, root_indicators=iterable_type([".git"]))
)
(dp / "x").mkdir()
self.assertEqual(
dp, get_root(dp / "x", root_indicators=iterable_type([".git"]))
)

def test_optional_value(self) -> None:
with volatile.dir() as d:
dp = Path(d).resolve()
Expand Down