feat: rewrite snapshot command output, update README

This commit is contained in:
Igor Ovsyannikov
2026-08-07 20:29:30 +03:00
parent 2c6000d56e
commit 4e632b87df
13 changed files with 295 additions and 147 deletions
+64 -52
View File
@@ -1,16 +1,59 @@
from pathlib import Path
import shutil
import pytest
from lohup.app import Lohup
from lohup.config import ConfigError
from lohup.logger import BasicLogger, LogLevel
from lohup.util import DeepValidator, ValidationFailed
import pytest
class RepoEnvironment:
def __init__(self, tmp_path: Path):
self.basepath = tmp_path
self.repo = tmp_path / "repo"
self.pwfile = tmp_path / "password.txt"
self.cfg = tmp_path / "lohup.toml"
self.log = BasicLogger(level=LogLevel.DEBUG)
def write_password(self, value: str = "1") -> Path:
pth = self.basepath / "password.txt"
pth.write_text("1")
return pth
def write_config(self, value: str, vars: dict[str, str]):
kwargs = vars.copy()
kwargs["base"] = str(self.basepath)
kwargs["repo"] = str(self.repo)
kwargs["pwfile"] = str(self.pwfile)
self.cfg.write_text(value.format_map(kwargs))
@pytest.fixture
def repo(tmp_path: Path):
env = RepoEnvironment(tmp_path)
yield env
if env.repo.exists():
shutil.rmtree(env.repo)
toml1 = """
[settings.globals]
"""
def test_error_message(repo):
repo.write_config(toml1, {})
app = Lohup(config_path=str(repo.cfg), logger=repo.log)
msg = "no repositories defined"
with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc:
app.load()
repo.log.error(exc.value)
cause = exc.value.__cause__
assert isinstance(cause, ValidationFailed) and msg in cause.messages
toml2 = """
[[hooks.before-all]]
kind = "???"
@@ -22,6 +65,18 @@ path = "{base}/repo"
repo-key-file = "{pwfile}"
"""
def test_hook_error(repo):
repo.write_config(toml2, {})
app = Lohup(config_path=str(repo.cfg), logger=repo.log)
msg = "hook: before-all: unsupported kind: ???"
with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc:
app.load()
repo.log.error(exc.value)
cause = exc.value.__cause__
assert isinstance(cause, ValidationFailed) and msg in cause.messages
toml_vars = """
[settings.globals]
foo = "$bar"
@@ -34,67 +89,24 @@ repo-key-file = "$unknown"
"""
class RepoEnvironment:
def __init__(self, tmp_path: Path):
self.basepath = tmp_path
self.log = BasicLogger(level=LogLevel.DEBUG)
def write_password(self, value: str = "1") -> Path:
pth = self.basepath / "password.txt"
pth.write_text("1")
return pth
def write_config(self, value: str) -> Path:
pth = self.basepath / "lohup.toml"
pth.write_text(value)
return pth
def test_error_message(tmp_path):
env = RepoEnvironment(tmp_path)
path = tmp_path / "lohup.toml"
path.write_text(toml1)
app = Lohup(config_path=str(path), logger=env.log)
msg = "no repositories defined"
with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc:
app.load()
env.log.error(exc.value)
cause = exc.value.__cause__
assert isinstance(cause, ValidationFailed) and msg in cause.messages
def test_hook_error(tmp_path):
env = RepoEnvironment(tmp_path)
pwfile = env.write_password()
tmp_path.joinpath("repo").mkdir()
path = tmp_path / "lohup.toml"
path.write_text(toml2.format(base=tmp_path, pwfile=pwfile))
app = Lohup(config_path=path, logger=env.log)
msg = "hook: before-all: unsupported kind: ???"
with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc:
app.load()
env.log.error(exc.value)
cause = exc.value.__cause__
assert isinstance(cause, ValidationFailed) and msg in cause.messages
def test_invalid_vars(tmp_path):
env = RepoEnvironment(tmp_path)
path = env.write_config(toml_vars)
app = Lohup(config_path=str(path), logger=env.log)
def test_invalid_vars(repo):
repo.write_config(toml_vars, {})
app = Lohup(config_path=str(repo.cfg), logger=repo.log)
lines = [
"settings: variable 'foo': nested variables in globals are not allowed",
"settings: variable 'bag': invalid type: int, expected string",
"repo 'local': read repo-key-file: variable 'unknown' is not defined"
"repo 'local': read repo-key-file: variable 'unknown' is not defined",
]
with pytest.raises(ConfigError, match="Failed to parse TOML config") as exc:
with pytest.raises(ConfigError) as exc:
app.load()
env.log.error(exc.value)
repo.log.error(exc.value)
cause = exc.value.__cause__
assert isinstance(cause, ValidationFailed)
for exc in cause.exceptions:
env.log.error(exc.value)
repo.log.error(exc.value)
assert set(lines) == set(cause.messages)
def test_validator():
validator = DeepValidator("testing")
with validator.inner("read config") as inner: