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
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
name = "dycw-utilities"
readme = "README.md"
requires-python = ">= 3.12"
version = "0.174.17"
version = "0.174.18"

[project.entry-points.pytest11]
pytest-randomly = "utilities.pytest_plugins.pytest_randomly"
Expand Down Expand Up @@ -135,7 +135,7 @@
# bump-my-version
[tool.bumpversion]
allow_dirty = true
current_version = "0.174.17"
current_version = "0.174.18"

[[tool.bumpversion.files]]
filename = "src/utilities/__init__.py"
Expand Down
20 changes: 18 additions & 2 deletions src/tests/test_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
cp_cmd,
echo_cmd,
expand_path,
git_clone,
git_clone_cmd,
git_hard_reset_cmd,
maybe_parent,
Expand Down Expand Up @@ -60,6 +61,7 @@
tee_cmd,
touch_cmd,
uv_run_cmd,
yield_git_repo,
yield_ssh_temp_dir,
)
from utilities.tempfile import TemporaryDirectory, TemporaryFile
Expand Down Expand Up @@ -233,14 +235,21 @@ def test_subs(self) -> None:
assert result == expected


class TestGitClone:
@throttle(delta=5 * MINUTE)
def test_main(self, *, tmp_path: Path) -> None:
git_clone("https://github.com/dycw/template-generic", tmp_path)
assert (tmp_path / ".bumpversion.toml").is_file()


class TestGitCloneCmd:
def test_main(self) -> None:
result = git_clone_cmd("https://github.com/foo/bar", "path")
result = git_clone_cmd("https://github.com/dycw/template-generic", "path")
expected = [
"git",
"clone",
"--recurse-submodules",
"https://github.com/foo/bar",
"https://github.com/dycw/template-generic",
"path",
]
assert result == expected
Expand Down Expand Up @@ -1187,6 +1196,13 @@ def test_args(self) -> None:
assert result == expected


class TestYieldGitRepo:
@throttle(delta=5 * MINUTE)
def test_main(self) -> None:
with yield_git_repo("https://github.com/dycw/template-generic") as temp:
assert (temp / ".bumpversion.toml").is_file()


class TestYieldSSHTempDir:
@skipif_ci
@throttle(delta=5 * MINUTE)
Expand Down
2 changes: 1 addition & 1 deletion src/utilities/__init__.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/utilities/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ def yield_docker_temp_dir(
logger: LoggerLike | None = None,
keep: bool = False,
) -> Iterator[Path]:
"""Yield a temporary directory in a Docker container."""
path = Path( # skipif-ci
docker_exec(
container,
Expand Down
38 changes: 38 additions & 0 deletions src/utilities/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,16 @@ def expand_path(
##


def git_clone(
url: str, path: PathLike, /, *, sudo: bool = False, branch: str | None = None
) -> None:
"""Clone a repository."""
rm(path, sudo=sudo)
run(*maybe_sudo_cmd(*git_clone_cmd(url, path), sudo=sudo))
if branch is not None:
run(*maybe_sudo_cmd(*git_hard_reset_cmd(branch=branch), sudo=sudo), cwd=path)


def git_clone_cmd(url: str, path: PathLike, /) -> list[str]:
"""Command to use 'git clone' to clone a repository."""
return ["git", "clone", "--recurse-submodules", url, str(path)]
Expand Down Expand Up @@ -1089,14 +1099,26 @@ def tee_cmd(path: PathLike, /, *, append: bool = False) -> list[str]:
##


def touch(path: PathLike, /, *, sudo: bool = False) -> None:
"""Change file access and modification times."""
run(*maybe_sudo_cmd(*touch_cmd(path), sudo=sudo))


def touch_cmd(path: PathLike, /) -> list[str]:
"""Command to use 'touch' to change file access and modification times."""
return ["touch", str(path)]


##


def uv_run(module: str, /, *args: str) -> None:
"""Run a command or script."""
run(*uv_run_cmd(module, *args)) # pragma: no cover


def uv_run_cmd(module: str, /, *args: str) -> list[str]:
"""Command to use 'uv' to run a command or script."""
return [
"uv",
"run",
Expand All @@ -1114,6 +1136,17 @@ def uv_run_cmd(module: str, /, *args: str) -> list[str]:
##


@contextmanager
def yield_git_repo(url: str, /, *, branch: str | None = None) -> Iterator[Path]:
"""Yield a temporary git repository."""
with TemporaryDirectory() as temp_dir:
git_clone(url, temp_dir, branch=branch)
yield temp_dir


##


@contextmanager
def yield_ssh_temp_dir(
user: str,
Expand All @@ -1124,6 +1157,7 @@ def yield_ssh_temp_dir(
logger: LoggerLike | None = None,
keep: bool = False,
) -> Iterator[Path]:
"""Yield a temporary directory on a remote machine."""
path = Path( # skipif-ci
ssh(user, hostname, *MKTEMP_DIR_CMD, return_=True, retry=retry, logger=logger)
)
Expand Down Expand Up @@ -1160,6 +1194,7 @@ def yield_ssh_temp_dir(
"cp_cmd",
"echo_cmd",
"expand_path",
"git_clone",
"git_clone_cmd",
"git_hard_reset_cmd",
"maybe_parent",
Expand All @@ -1183,7 +1218,10 @@ def yield_ssh_temp_dir(
"symlink",
"symlink_cmd",
"tee_cmd",
"touch",
"touch_cmd",
"uv_run",
"uv_run_cmd",
"yield_git_repo",
"yield_ssh_temp_dir",
]
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading