"""Tests for scripts/migrate_local_configs.py (universal example→local merge).""" from __future__ import annotations import importlib.util from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[1] SCRIPT = ROOT / "scripts" / "migrate_local_configs.py" def _load(): spec = importlib.util.spec_from_file_location("migrate_local_configs", SCRIPT) assert spec and spec.loader mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod @pytest.fixture(scope="module") def m(): return _load() def test_example_to_target_mapping(m): root = Path("/tmp/x") assert m.example_to_target(root / "env.example") == root / ".env" assert m.example_to_target(root / "ollama-models.example.yaml") == root / "ollama-models.yaml" assert m.example_to_target(root / "gpu-rent.vars.example") == root / "gpu-rent.vars" assert m.example_to_target(root / ".env.example") == root / ".env" assert m.example_to_target(root / "readme.md") is None def test_deep_fill_dict_adds_missing_keeps_local(m): local = {"a": 1, "nested": {"x": 9}} example = {"a": 99, "b": 2, "nested": {"x": 0, "y": 3}} out, changed = m.deep_fill(local, example) assert changed assert out["a"] == 1 assert out["b"] == 2 assert out["nested"]["x"] == 9 assert out["nested"]["y"] == 3 def test_merge_lists_by_name(m): local = [{"name": "chat-a", "default": True}] example = [ {"name": "chat-a", "use": "chat", "default": False}, {"name": "nomic-embed-text", "use": "memory"}, ] out, changed = m._merge_lists(local, example) assert changed assert out[0]["name"] == "chat-a" assert out[0]["default"] is True # local wins assert out[0]["use"] == "chat" # filled from example assert out[1]["name"] == "nomic-embed-text" def test_merge_env_and_yaml_end_to_end(m, tmp_path): (tmp_path / "env.example").write_text( "OS_PASSWORD=secret\nNEW_FLAG=true\n# DOC_ONLY=1\n", encoding="utf-8" ) (tmp_path / ".env").write_text("OS_PASSWORD=real\nKEEP=1\n", encoding="utf-8") (tmp_path / "models.example.yaml").write_text( "checkpoint:\n - url: https://ex/a\nlora: []\n", encoding="utf-8", ) (tmp_path / "models.yaml").write_text( "checkpoint:\n - url: https://ex/mine\n", encoding="utf-8", ) (tmp_path / "ollama-models.example.yaml").write_text( "models:\n - name: chat:7b\n use: chat\n default: true\n" " - name: nomic-embed-text\n use: memory\n", encoding="utf-8", ) (tmp_path / "ollama-models.yaml").write_text( "models:\n - name: chat:7b\n default: true\n", encoding="utf-8", ) n = m.run(tmp_path, dry=False, create_missing=True, log=lambda *_: None) assert n >= 1 env = (tmp_path / ".env").read_text(encoding="utf-8") assert "OS_PASSWORD=real" in env assert "NEW_FLAG=true" in env assert "DOC_ONLY" not in env # docs off by default assert "KEEP=1" in env m.run(tmp_path, dry=False, create_missing=True, include_docs=True, log=lambda *_: None) env2 = (tmp_path / ".env").read_text(encoding="utf-8") assert "# DOC_ONLY=1" in env2 import yaml models = yaml.safe_load((tmp_path / "models.yaml").read_text(encoding="utf-8")) assert models["checkpoint"][0]["url"] == "https://ex/mine" assert any(x.get("url") == "https://ex/a" for x in models["checkpoint"]) assert "lora" in models ollama = yaml.safe_load((tmp_path / "ollama-models.yaml").read_text(encoding="utf-8")) names = [x["name"] for x in ollama["models"]] assert "chat:7b" in names assert "nomic-embed-text" in names chat = next(x for x in ollama["models"] if x["name"] == "chat:7b") assert chat["use"] == "chat" assert chat["default"] is True