Skip to content

Commit 7c86669

Browse files
committed
2026-01-16 12:12:07 (Fri) > DW-Mac > derekwan
1 parent 27edf6e commit 7c86669

6 files changed

Lines changed: 102 additions & 10 deletions

File tree

.bumpversion.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.bumpversion]
22
allow_dirty = true
3-
current_version = "0.182.3"
3+
current_version = "0.182.5"
44

55
[[tool.bumpversion.files]]
66
filename = "pyproject.toml"

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"coloredlogs>=15.0.1, <16",
2626
"coverage-conditional-plugin>=0.9.0, <1",
2727
"dycw-pytest-only>=2.1.1, <3",
28-
"dycw-utilities[test]>=0.182.2, <1",
28+
"dycw-utilities[test]>=0.182.4, <1",
2929
"pyright>=1.1.408, <2",
3030
"pytest-cov>=7.0.0, <8",
3131
"pytest-timeout>=2.4.0, <3",
@@ -128,7 +128,7 @@
128128
name = "dycw-utilities"
129129
readme = "README.md"
130130
requires-python = ">= 3.12"
131-
version = "0.182.3"
131+
version = "0.182.5"
132132

133133
[project.entry-points.pytest11]
134134
pytest-randomly = "utilities.pytest_plugins.pytest_randomly"

src/tests/test_subprocess.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
from utilities.pathlib import get_file_group, get_file_owner
1717
from utilities.permissions import Permissions
1818
from utilities.pwd import EFFECTIVE_USER_NAME
19-
from utilities.pytest import skipif_ci, skipif_mac, throttle_test
19+
from utilities.pytest import skipif_ci, skipif_mac, skipif_not_linux, throttle_test
2020
from utilities.shutil import which
2121
from utilities.subprocess import (
2222
BASH_LC,
2323
BASH_LS,
2424
KNOWN_HOSTS,
2525
ChownCmdError,
2626
CpError,
27+
GetEntOutput,
2728
MvFileError,
2829
RsyncCmdNoSourcesError,
2930
RsyncCmdSourcesNotFoundError,
@@ -48,6 +49,9 @@
4849
echo_cmd,
4950
env_cmds,
5051
expand_path,
52+
getent,
53+
getent_cmd,
54+
getent_ssh,
5155
git_branch_current,
5256
git_checkout,
5357
git_checkout_cmd,
@@ -420,6 +424,28 @@ def test_subs(self) -> None:
420424
assert result == expected
421425

422426

427+
class TestGetEnt:
428+
@skipif_not_linux
429+
def test_main(self) -> None:
430+
result = getent("user")
431+
assert isinstance(result, GetEntOutput)
432+
433+
434+
class TestGetEntCmd:
435+
def test_main(self) -> None:
436+
result = getent_cmd("user")
437+
expected = ["getent", "passwd", "user"]
438+
assert result == expected
439+
440+
441+
class TestGetEntSSH:
442+
@skipif_ci
443+
@throttle_test(duration=5 * MINUTE)
444+
def test_main(self, *, ssh_user: str, ssh_hostname: str) -> None:
445+
result = getent_ssh(ssh_user, ssh_hostname)
446+
assert isinstance(result, GetEntOutput)
447+
448+
423449
class TestGitBranchCurrent:
424450
@throttle_test(duration=5 * MINUTE)
425451
def test_main(self, *, git_repo_url: str, tmp_path: Path) -> None:

src/utilities/__init__.py

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/utilities/subprocess.py

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from string import Template
1313
from subprocess import PIPE, CalledProcessError, Popen
1414
from threading import Thread
15-
from typing import IO, TYPE_CHECKING, Literal, assert_never, overload, override
15+
from typing import IO, TYPE_CHECKING, Literal, Self, assert_never, overload, override
1616

1717
from utilities.atomicwrites import (
1818
_CopySourceNotFoundError,
@@ -547,6 +547,66 @@ def expand_path(
547547
##
548548

549549

550+
def getent(user: str, /) -> GetEntOutput:
551+
"""Get an entry from Name Service Switch libraries."""
552+
text = run(*getent_cmd(user), return_=True) # skipif-not-linux
553+
return GetEntOutput.parse(text) # skipif-not-linux
554+
555+
556+
def getent_cmd(user: str, /) -> list[str]:
557+
"""Command to use 'getent' to get entries from Name Service Switch libraries."""
558+
return ["getent", "passwd", user]
559+
560+
561+
def getent_ssh(
562+
ssh_user: str,
563+
hostname: str,
564+
/,
565+
*,
566+
user: str | None = None,
567+
retry: Retry | None = None,
568+
logger: LoggerLike | None = None,
569+
) -> GetEntOutput:
570+
"""Get an entry from Name Service Switch libraries."""
571+
user_use = ssh_user if user is None else user # skipif-ci
572+
text = ssh( # skipif-ci
573+
ssh_user,
574+
hostname,
575+
*getent_cmd(user_use),
576+
return_=True,
577+
retry=retry,
578+
logger=logger,
579+
)
580+
return GetEntOutput.parse(text) # skipif-ci
581+
582+
583+
@dataclass(order=True, unsafe_hash=True, kw_only=True, slots=True)
584+
class GetEntOutput:
585+
username: str
586+
passwd: str
587+
uid: int
588+
gid: int
589+
gecos: str
590+
home: Path
591+
shell: Path
592+
593+
@classmethod
594+
def parse(cls, text: str, /) -> Self:
595+
username, passwd, uid, gid, gecos, home, shell = text.split(":")
596+
return cls(
597+
username=username,
598+
passwd=passwd,
599+
uid=int(uid),
600+
gid=int(gid),
601+
gecos=gecos,
602+
home=Path(home),
603+
shell=Path(shell),
604+
)
605+
606+
607+
##
608+
609+
550610
def git_branch_current(path: PathLike, /) -> str:
551611
"""Show the current a branch."""
552612
return run(*GIT_BRANCH_SHOW_CURRENT, cwd=path, return_=True)
@@ -2316,9 +2376,10 @@ def yield_ssh_temp_dir(
23162376
keep: bool = False,
23172377
) -> Iterator[Path]:
23182378
"""Yield a temporary directory on a remote machine."""
2319-
path = Path( # skipif-ci
2320-
ssh(user, hostname, *MKTEMP_DIR_CMD, return_=True, retry=retry, logger=logger)
2379+
text = ssh( # skipif-ci
2380+
user, hostname, *MKTEMP_DIR_CMD, return_=True, retry=retry, logger=logger
23212381
)
2382+
path = Path(text) # skipif-ci
23222383
try: # skipif-ci
23232384
yield path
23242385
finally: # skipif-ci
@@ -2344,6 +2405,8 @@ def yield_ssh_temp_dir(
23442405
"UPDATE_CA_CERTIFICATES",
23452406
"ChownCmdError",
23462407
"CpError",
2408+
"GetEntOutput",
2409+
"GetEntOutput",
23472410
"MvFileError",
23482411
"RsyncCmdError",
23492412
"RsyncCmdNoSourcesError",
@@ -2371,6 +2434,9 @@ def yield_ssh_temp_dir(
23712434
"echo_cmd",
23722435
"env_cmds",
23732436
"expand_path",
2437+
"getent",
2438+
"getent_cmd",
2439+
"getent_ssh",
23742440
"git_branch_current",
23752441
"git_checkout",
23762442
"git_checkout_cmd",

uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)