1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
"""
utils
"""
from __future__ import annotations
import logging
import subprocess
import textwrap
import warnings
from pathlib import Path
from types import CodeType
from types import FunctionType
from typing import NamedTuple
from typing import Sequence
from typing import TYPE_CHECKING
from . import _run_cmd
if TYPE_CHECKING:
from . import _types as _t
log = logging.getLogger(__name__)
class _CmdResult(NamedTuple):
out: str
err: str
returncode: int
def do_ex(cmd: _t.CMD_TYPE, cwd: _t.PathT = ".") -> _CmdResult:
res = _run_cmd.run(cmd, cwd)
return _CmdResult(res.stdout, res.stderr, res.returncode)
def do(cmd: _t.CMD_TYPE, cwd: _t.PathT = ".") -> str:
out, err, ret = do_ex(cmd, cwd)
if ret and log.getEffectiveLevel() > logging.DEBUG:
print(err)
return out
def data_from_mime(path: _t.PathT) -> dict[str, str]:
content = Path(path).read_text(encoding="utf-8")
log.debug("mime %s content:\n%s", path, textwrap.indent(content, " "))
# the complex conditions come from reading pseudo-mime-messages
data = dict(x.split(": ", 1) for x in content.splitlines() if ": " in x)
log.debug("mime %s data:\n%s", path, data)
return data
def function_has_arg(fn: object | FunctionType, argname: str) -> bool:
assert isinstance(fn, FunctionType)
code: CodeType = fn.__code__
return argname in code.co_varnames
def has_command(name: str, args: Sequence[str] = ["help"], warn: bool = True) -> bool:
try:
p = _run_cmd.run([name, *args], cwd=".", timeout=5)
except OSError as e:
log.exception("command %s missing: %s", name, e)
res = False
except subprocess.TimeoutExpired as e:
log.warning("command %s timed out %s", name, e)
res = False
else:
res = not p.returncode
if not res and warn:
warnings.warn("%r was not found" % name, category=RuntimeWarning)
return res
def require_command(name: str) -> None:
if not has_command(name, warn=False):
raise OSError(f"{name!r} was not found")
|