mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-10-12 04:22:13 -03:00
Second pass over the informational Windows job (91 failures -> 11 -> 0):
* `_identity`/`_fold` now wrap the assertions my first sweep skipped: the
parenthesised and multi-line ones, and the ones whose token list was
incomplete (`base_models_roots`, `embeddings_roots`).
* The reconciler's `current_name` and `active_roots` carry the drive-prefixed
label on Windows ("C: loras"), so the last direct comparison goes through
`_root_label_names` too.
* `open_settings_location` reveals the settings *file* with
`explorer /select,` on Windows instead of opening the containing folder, so
that test asserts the platform's call instead of the POSIX one.
* Three more expectations are written in the business form the code returns
(metadata payload, extracted download paths, hydrated preview URL).
1184 lines
44 KiB
Python
1184 lines
44 KiB
Python
import logging
|
|
from typing import Any, Dict, Iterable, List, Mapping
|
|
|
|
import pytest
|
|
|
|
from py import config as config_module
|
|
from py.utils.root_paths import normalize_root_identity
|
|
from py.services import settings_manager as settings_manager_module
|
|
|
|
|
|
def _identity(value):
|
|
"""Fold path spelling so an assertion is about paths, not separators.
|
|
|
|
LM keeps the host's own spelling for the paths it is configured with
|
|
(backslashes on Windows) while the ones it derives itself are forward-slashed,
|
|
so two values naming the same directory can differ as strings. Compare
|
|
identities wherever a test asserts *which* paths survived.
|
|
"""
|
|
|
|
if isinstance(value, str):
|
|
return normalize_root_identity(value)
|
|
if isinstance(value, Mapping):
|
|
return {key: _identity(item) for key, item in value.items()}
|
|
if isinstance(value, (list, tuple)):
|
|
return [_identity(item) for item in value]
|
|
if isinstance(value, set):
|
|
return {_identity(item) for item in value}
|
|
return value
|
|
|
|
|
|
def _setup_config_environment(monkeypatch: pytest.MonkeyPatch, tmp_path) -> Dict[str, List[str]]:
|
|
loras_dir = tmp_path / "loras"
|
|
checkpoints_dir = tmp_path / "checkpoints"
|
|
embeddings_dir = tmp_path / "embeddings"
|
|
|
|
for directory in (loras_dir, checkpoints_dir, embeddings_dir):
|
|
directory.mkdir()
|
|
|
|
folder_paths: Dict[str, List[str]] = {
|
|
"loras": [str(loras_dir)],
|
|
"checkpoints": [str(checkpoints_dir)],
|
|
"unet": [],
|
|
"embeddings": [str(embeddings_dir)],
|
|
}
|
|
|
|
def fake_get_folder_paths(kind: str) -> Iterable[str]:
|
|
return folder_paths.get(kind, [])
|
|
|
|
monkeypatch.setattr(config_module.folder_paths, "get_folder_paths", fake_get_folder_paths)
|
|
monkeypatch.setattr(config_module, "standalone_mode", False)
|
|
monkeypatch.setattr(
|
|
config_module,
|
|
"ensure_settings_file",
|
|
lambda logger=None: str(tmp_path / "settings.json"),
|
|
)
|
|
|
|
return folder_paths
|
|
|
|
|
|
def test_save_paths_renames_default_library(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class FakeSettingsService:
|
|
def __init__(self, default_paths: Dict[str, List[str]]):
|
|
self._default_paths = default_paths
|
|
self.rename_calls = []
|
|
self.delete_calls = []
|
|
self.upsert_calls = []
|
|
self._renamed = False
|
|
self.active_library = "default"
|
|
|
|
def get_libraries(self):
|
|
if self._renamed:
|
|
return {"comfyui": {}}
|
|
return {
|
|
"default": {
|
|
"folder_paths": {key: list(value) for key, value in self._default_paths.items()},
|
|
"default_lora_root": "",
|
|
"default_checkpoint_root": "",
|
|
"default_embedding_root": "",
|
|
}
|
|
}
|
|
|
|
def rename_library(self, old_name: str, new_name: str):
|
|
self.rename_calls.append((old_name, new_name))
|
|
self._renamed = True
|
|
if self.active_library == old_name:
|
|
self.active_library = new_name
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def delete_library(self, name: str): # pragma: no cover - defensive guard
|
|
self.delete_calls.append(name)
|
|
raise AssertionError("delete_library should not be invoked in this scenario")
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.upsert_calls.append((name, payload))
|
|
|
|
fake_settings = FakeSettingsService(folder_paths)
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_instance = config_module.Config()
|
|
|
|
assert isinstance(config_instance, config_module.Config)
|
|
assert fake_settings.rename_calls == [("default", "comfyui")]
|
|
assert len(fake_settings.upsert_calls) == 1
|
|
|
|
name, payload = fake_settings.upsert_calls[0]
|
|
assert name == "comfyui"
|
|
|
|
# The Config class normalizes paths to use forward slashes for cross-platform compatibility
|
|
# Convert expected paths to the same format for comparison
|
|
expected_folder_paths = {
|
|
key: [path.replace("\\", "/") for path in paths]
|
|
for key, paths in folder_paths.items()
|
|
}
|
|
assert _identity(payload["folder_paths"]) == _identity(expected_folder_paths)
|
|
assert _identity(payload["default_lora_root"]) == _identity(folder_paths["loras"][0].replace("\\", "/"))
|
|
assert _identity(payload["default_checkpoint_root"]) == _identity(folder_paths["checkpoints"][0].replace("\\", "/"))
|
|
assert _identity(payload["default_embedding_root"]) == _identity(folder_paths["embeddings"][0].replace("\\", "/"))
|
|
assert _identity(payload["metadata"]) == _identity({"display_name": "ComfyUI", "source": "comfyui"})
|
|
assert payload["activate"] is True
|
|
|
|
|
|
def test_save_paths_logs_warning_when_upsert_fails(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path, caplog
|
|
):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class RaisingSettingsService:
|
|
def __init__(self):
|
|
self.upsert_attempts = []
|
|
self.active_library = "comfyui"
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"default_lora_root": "existing",
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.upsert_attempts.append((name, payload))
|
|
raise RuntimeError("boom")
|
|
|
|
fake_settings = RaisingSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
with caplog.at_level(logging.WARNING, logger=config_module.logger.name):
|
|
config_instance = config_module.Config()
|
|
|
|
assert isinstance(config_instance, config_module.Config)
|
|
assert fake_settings.upsert_attempts and fake_settings.upsert_attempts[0][0] == "comfyui"
|
|
assert "Failed to save folder paths: boom" in caplog.text
|
|
|
|
|
|
def test_save_paths_repairs_empty_default_roots(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class FakeSettingsService:
|
|
active_library = "comfyui"
|
|
name: str = ""
|
|
payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"default_lora_root": "",
|
|
"default_checkpoint_root": "",
|
|
"default_embedding_root": "",
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.name = name
|
|
self.payload = payload
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert fake_settings.name == "comfyui"
|
|
assert _identity(fake_settings.payload["default_lora_root"]) == _identity(folder_paths["loras"][0].replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_checkpoint_root"]) == _identity(folder_paths["checkpoints"][0].replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_embedding_root"]) == _identity(folder_paths["embeddings"][0].replace("\\", "/"))
|
|
|
|
|
|
def test_save_paths_repairs_stale_default_roots(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class FakeSettingsService:
|
|
active_library = "comfyui"
|
|
name: str = ""
|
|
payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"default_lora_root": "/stale/loras",
|
|
"default_checkpoint_root": "/stale/checkpoints",
|
|
"default_embedding_root": "/stale/embeddings",
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.name = name
|
|
self.payload = payload
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert fake_settings.name == "comfyui"
|
|
assert _identity(fake_settings.payload["default_lora_root"]) == _identity(folder_paths["loras"][0].replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_checkpoint_root"]) == _identity(folder_paths["checkpoints"][0].replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_embedding_root"]) == _identity(folder_paths["embeddings"][0].replace("\\", "/"))
|
|
|
|
|
|
def test_save_paths_keeps_valid_default_roots(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class FakeSettingsService:
|
|
active_library = "comfyui"
|
|
name: str = ""
|
|
payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"default_lora_root": folder_paths["loras"][0],
|
|
"default_checkpoint_root": folder_paths["checkpoints"][0],
|
|
"default_embedding_root": folder_paths["embeddings"][0],
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.name = name
|
|
self.payload = payload
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert fake_settings.name == "comfyui"
|
|
assert _identity(fake_settings.payload["default_lora_root"]) == _identity(folder_paths["loras"][0].replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_checkpoint_root"]) == _identity(folder_paths["checkpoints"][0].replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_embedding_root"]) == _identity(folder_paths["embeddings"][0].replace("\\", "/"))
|
|
|
|
|
|
def test_save_paths_removes_template_default_library(monkeypatch, tmp_path):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
placeholder_paths = {
|
|
"loras": [
|
|
"C:/path/to/your/loras_folder",
|
|
"C:/path/to/another/loras_folder",
|
|
],
|
|
"checkpoints": [
|
|
"C:/path/to/your/checkpoints_folder",
|
|
"C:/path/to/another/checkpoints_folder",
|
|
],
|
|
"embeddings": [
|
|
"C:/path/to/your/embeddings_folder",
|
|
"C:/path/to/another/embeddings_folder",
|
|
],
|
|
}
|
|
|
|
class FakeSettingsService:
|
|
def __init__(self):
|
|
self.libraries = {
|
|
"default": {
|
|
"folder_paths": placeholder_paths,
|
|
"default_lora_root": "",
|
|
"default_checkpoint_root": "",
|
|
"default_embedding_root": "",
|
|
}
|
|
}
|
|
self.rename_calls = []
|
|
self.delete_calls = []
|
|
self.upsert_calls = []
|
|
self.active_library = "default"
|
|
|
|
def get_libraries(self):
|
|
return self.libraries
|
|
|
|
def rename_library(self, old_name: str, new_name: str):
|
|
self.rename_calls.append((old_name, new_name))
|
|
self.libraries[new_name] = self.libraries.pop(old_name)
|
|
if self.active_library == old_name:
|
|
self.active_library = new_name
|
|
|
|
def delete_library(self, name: str):
|
|
self.delete_calls.append(name)
|
|
self.libraries.pop(name, None)
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.upsert_calls.append((name, payload))
|
|
self.libraries[name] = {**payload}
|
|
if payload.get("activate"):
|
|
self.active_library = name
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
monkeypatch.setattr(
|
|
config_module,
|
|
"load_settings_template",
|
|
lambda: {"folder_paths": placeholder_paths},
|
|
)
|
|
|
|
config_instance = config_module.Config()
|
|
|
|
assert isinstance(config_instance, config_module.Config)
|
|
assert fake_settings.rename_calls == [("default", "comfyui")]
|
|
assert not fake_settings.delete_calls
|
|
assert len(fake_settings.upsert_calls) == 1
|
|
assert "default" not in fake_settings.libraries
|
|
assert set(fake_settings.libraries.keys()) == {"comfyui"}
|
|
|
|
name, payload = fake_settings.upsert_calls[0]
|
|
assert name == "comfyui"
|
|
|
|
expected_folder_paths = {
|
|
key: [path.replace("\\", "/") for path in paths]
|
|
for key, paths in folder_paths.items()
|
|
}
|
|
assert _identity(payload["folder_paths"]) == _identity(expected_folder_paths)
|
|
assert _identity(payload["default_lora_root"]) == _identity(folder_paths["loras"][0].replace("\\", "/"))
|
|
assert _identity(payload["default_checkpoint_root"]) == _identity(
|
|
folder_paths["checkpoints"][0].replace("\\", "/")
|
|
)
|
|
assert _identity(payload["default_embedding_root"]) == _identity(
|
|
folder_paths["embeddings"][0].replace("\\", "/")
|
|
)
|
|
assert _identity(payload["metadata"]) == _identity({"display_name": "ComfyUI", "source": "comfyui"})
|
|
assert payload["activate"] is True
|
|
|
|
|
|
def test_save_paths_keeps_default_roots_in_extra_paths(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
extra_lora_dir = tmp_path / "extra_loras"
|
|
extra_checkpoint_dir = tmp_path / "extra_checkpoints"
|
|
extra_embedding_dir = tmp_path / "extra_embeddings"
|
|
|
|
for directory in (extra_lora_dir, extra_checkpoint_dir, extra_embedding_dir):
|
|
directory.mkdir()
|
|
|
|
class FakeSettingsService:
|
|
active_library = "comfyui"
|
|
name: str = ""
|
|
payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"extra_folder_paths": {
|
|
"loras": [str(extra_lora_dir)],
|
|
"checkpoints": [str(extra_checkpoint_dir)],
|
|
"embeddings": [str(extra_embedding_dir)],
|
|
},
|
|
"default_lora_root": str(extra_lora_dir),
|
|
"default_checkpoint_root": str(extra_checkpoint_dir),
|
|
"default_embedding_root": str(extra_embedding_dir),
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.name = name
|
|
self.payload = payload
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert fake_settings.name == "comfyui"
|
|
assert _identity(fake_settings.payload["extra_folder_paths"]["loras"]) == _identity([str(extra_lora_dir).replace("\\", "/")])
|
|
assert _identity(fake_settings.payload["extra_folder_paths"]["checkpoints"]) == _identity([
|
|
str(extra_checkpoint_dir).replace("\\", "/")
|
|
])
|
|
assert _identity(fake_settings.payload["extra_folder_paths"]["embeddings"]) == _identity([
|
|
str(extra_embedding_dir).replace("\\", "/")
|
|
])
|
|
assert _identity(fake_settings.payload["default_lora_root"]) == _identity(str(extra_lora_dir).replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_checkpoint_root"]) == _identity(str(extra_checkpoint_dir).replace("\\", "/"))
|
|
assert _identity(fake_settings.payload["default_embedding_root"]) == _identity(str(extra_embedding_dir).replace("\\", "/"))
|
|
assert fake_settings.payload["activate"] is True
|
|
|
|
|
|
def test_save_paths_keeps_default_roots_in_extra_paths_with_windows_slash_mismatch(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class FakeSettingsService:
|
|
active_library = "comfyui"
|
|
name: str = ""
|
|
payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"extra_folder_paths": {
|
|
"loras": ["U:\\Lora7\\Loras"],
|
|
"checkpoints": ["U:\\Lora7\\Models"],
|
|
"embeddings": [],
|
|
},
|
|
"default_lora_root": "U:/Lora7/Loras",
|
|
"default_checkpoint_root": "U:/Lora7/Models",
|
|
"default_embedding_root": folder_paths["embeddings"][0],
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.name = name
|
|
self.payload = payload
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert fake_settings.name == "comfyui"
|
|
assert _identity(fake_settings.payload["default_lora_root"]) == _identity("U:/Lora7/Loras")
|
|
assert _identity(fake_settings.payload["default_checkpoint_root"]) == _identity("U:/Lora7/Models")
|
|
|
|
|
|
def test_save_paths_repairs_empty_default_roots_to_extra_paths_when_primary_missing(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
_setup_config_environment(monkeypatch, tmp_path)
|
|
extra_lora_dir = tmp_path / "extra_loras"
|
|
extra_lora_dir.mkdir()
|
|
|
|
monkeypatch.setattr(
|
|
config_module.folder_paths,
|
|
"get_folder_paths",
|
|
lambda kind: [] if kind == "loras" else [],
|
|
)
|
|
|
|
class FakeSettingsService:
|
|
active_library = "comfyui"
|
|
name: str = ""
|
|
payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {
|
|
"loras": [],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
"extra_folder_paths": {
|
|
"loras": [str(extra_lora_dir)],
|
|
},
|
|
"default_lora_root": "",
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.name = name
|
|
self.payload = payload
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert fake_settings.name == "comfyui"
|
|
assert _identity(fake_settings.payload["default_lora_root"]) == _identity(str(extra_lora_dir).replace("\\", "/"))
|
|
|
|
|
|
def test_save_paths_does_not_activate_comfyui_library_when_another_library_is_active(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class FakeSettingsService:
|
|
def __init__(self):
|
|
self.active_library = "studio"
|
|
self.upsert_calls = []
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"studio": {
|
|
"folder_paths": {"loras": ["/studio/loras"]},
|
|
},
|
|
"comfyui": {
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"default_lora_root": folder_paths["loras"][0],
|
|
"default_checkpoint_root": folder_paths["checkpoints"][0],
|
|
"default_embedding_root": folder_paths["embeddings"][0],
|
|
},
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.upsert_calls.append((name, payload))
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert len(fake_settings.upsert_calls) == 1
|
|
name, payload = fake_settings.upsert_calls[0]
|
|
assert name == "comfyui"
|
|
assert payload["activate"] is False
|
|
|
|
|
|
def test_apply_library_settings_merges_extra_paths(monkeypatch, tmp_path):
|
|
"""Test that apply_library_settings correctly merges folder_paths with extra_folder_paths."""
|
|
loras_dir = tmp_path / "loras"
|
|
extra_loras_dir = tmp_path / "extra_loras"
|
|
checkpoints_dir = tmp_path / "checkpoints"
|
|
extra_checkpoints_dir = tmp_path / "extra_checkpoints"
|
|
embeddings_dir = tmp_path / "embeddings"
|
|
extra_embeddings_dir = tmp_path / "extra_embeddings"
|
|
|
|
for directory in (loras_dir, extra_loras_dir, checkpoints_dir, extra_checkpoints_dir, embeddings_dir, extra_embeddings_dir):
|
|
directory.mkdir()
|
|
|
|
config_instance = config_module.Config()
|
|
|
|
folder_paths = {
|
|
"loras": [str(loras_dir)],
|
|
"checkpoints": [str(checkpoints_dir)],
|
|
"unet": [],
|
|
"embeddings": [str(embeddings_dir)],
|
|
}
|
|
extra_folder_paths = {
|
|
"loras": [str(extra_loras_dir)],
|
|
"checkpoints": [str(extra_checkpoints_dir)],
|
|
"unet": [],
|
|
"embeddings": [str(extra_embeddings_dir)],
|
|
}
|
|
|
|
library_config = {
|
|
"folder_paths": folder_paths,
|
|
"extra_folder_paths": extra_folder_paths,
|
|
}
|
|
|
|
config_instance.apply_library_settings(library_config)
|
|
|
|
assert _identity(str(loras_dir)) in _identity(config_instance.loras_roots)
|
|
assert _identity(str(extra_loras_dir)) in _identity(config_instance.extra_loras_roots)
|
|
assert _identity(str(checkpoints_dir)) in _identity(config_instance.base_models_roots)
|
|
assert _identity(str(extra_checkpoints_dir)) in _identity(config_instance.extra_checkpoints_roots)
|
|
assert _identity(str(embeddings_dir)) in _identity((config_instance.embeddings_roots or []))
|
|
assert _identity(str(extra_embeddings_dir)) in _identity(config_instance.extra_embeddings_roots)
|
|
|
|
|
|
def test_apply_library_settings_without_extra_paths(monkeypatch, tmp_path):
|
|
"""Test that apply_library_settings works when extra_folder_paths is not provided."""
|
|
loras_dir = tmp_path / "loras"
|
|
checkpoints_dir = tmp_path / "checkpoints"
|
|
embeddings_dir = tmp_path / "embeddings"
|
|
|
|
for directory in (loras_dir, checkpoints_dir, embeddings_dir):
|
|
directory.mkdir()
|
|
|
|
config_instance = config_module.Config()
|
|
|
|
folder_paths = {
|
|
"loras": [str(loras_dir)],
|
|
"checkpoints": [str(checkpoints_dir)],
|
|
"unet": [],
|
|
"embeddings": [str(embeddings_dir)],
|
|
}
|
|
|
|
library_config = {
|
|
"folder_paths": folder_paths,
|
|
}
|
|
|
|
config_instance.apply_library_settings(library_config)
|
|
|
|
assert _identity(str(loras_dir)) in _identity(config_instance.loras_roots)
|
|
assert _identity(config_instance.extra_loras_roots) == _identity([])
|
|
assert _identity(str(checkpoints_dir)) in _identity(config_instance.base_models_roots)
|
|
assert _identity(config_instance.extra_checkpoints_roots) == _identity([])
|
|
assert _identity(str(embeddings_dir)) in _identity((config_instance.embeddings_roots or []))
|
|
assert _identity(config_instance.extra_embeddings_roots) == _identity([])
|
|
|
|
|
|
def test_extra_paths_deduplication(monkeypatch, tmp_path):
|
|
"""Test that extra paths are stored separately from main paths in Config."""
|
|
loras_dir = tmp_path / "loras"
|
|
extra_loras_dir = tmp_path / "extra_loras"
|
|
loras_dir.mkdir()
|
|
extra_loras_dir.mkdir()
|
|
|
|
config_instance = config_module.Config()
|
|
|
|
folder_paths = {
|
|
"loras": [str(loras_dir)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
}
|
|
extra_folder_paths = {
|
|
"loras": [str(extra_loras_dir)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
}
|
|
|
|
library_config = {
|
|
"folder_paths": folder_paths,
|
|
"extra_folder_paths": extra_folder_paths,
|
|
}
|
|
|
|
config_instance.apply_library_settings(library_config)
|
|
|
|
assert _identity(config_instance.loras_roots) == _identity([str(loras_dir)])
|
|
assert _identity(config_instance.extra_loras_roots) == _identity([str(extra_loras_dir)])
|
|
|
|
|
|
def test_apply_library_settings_ignores_extra_lora_path_overlapping_primary_symlink(
|
|
monkeypatch, tmp_path, caplog
|
|
):
|
|
"""Extra LoRA paths should be ignored when they resolve to the same target as a primary root."""
|
|
real_loras_dir = tmp_path / "loras_real"
|
|
real_loras_dir.mkdir()
|
|
loras_link = tmp_path / "loras_link"
|
|
loras_link.symlink_to(real_loras_dir, target_is_directory=True)
|
|
|
|
config_instance = config_module.Config()
|
|
|
|
library_config = {
|
|
"folder_paths": {
|
|
"loras": [str(loras_link)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
"extra_folder_paths": {
|
|
"loras": [str(real_loras_dir)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
}
|
|
|
|
with caplog.at_level("WARNING", logger=config_module.logger.name):
|
|
config_instance.apply_library_settings(library_config)
|
|
|
|
assert _identity(config_instance.loras_roots) == _identity([str(loras_link)])
|
|
assert _identity(config_instance.extra_loras_roots) == _identity([])
|
|
|
|
warning_messages = [
|
|
record.message
|
|
for record in caplog.records
|
|
if record.levelname == "WARNING"
|
|
and "same lora folder" in record.message.lower()
|
|
]
|
|
assert len(warning_messages) == 1
|
|
assert "comfyui model paths" in warning_messages[0].lower()
|
|
assert "extra folder paths" in warning_messages[0].lower()
|
|
assert "duplicate items" in warning_messages[0].lower()
|
|
|
|
|
|
def test_apply_library_settings_detects_overlap_case_insensitively(
|
|
monkeypatch, tmp_path, caplog
|
|
):
|
|
"""Overlap detection should use case-insensitive comparison on Windows-like paths."""
|
|
real_loras_dir = tmp_path / "loras_real"
|
|
real_loras_dir.mkdir()
|
|
loras_link = tmp_path / "loras_link"
|
|
loras_link.symlink_to(real_loras_dir, target_is_directory=True)
|
|
|
|
original_exists = config_module.os.path.exists
|
|
original_realpath = config_module.os.path.realpath
|
|
original_normcase = config_module.os.path.normcase
|
|
|
|
def fake_exists(path):
|
|
if isinstance(path, str) and path.lower() in {
|
|
str(loras_link).lower(),
|
|
str(real_loras_dir).lower(),
|
|
str(loras_link).upper().lower(),
|
|
str(real_loras_dir).upper().lower(),
|
|
}:
|
|
return True
|
|
return original_exists(path)
|
|
|
|
def fake_realpath(path, *args, **kwargs):
|
|
if isinstance(path, str):
|
|
lowered = path.lower()
|
|
if lowered == str(loras_link).lower():
|
|
return str(real_loras_dir)
|
|
if lowered == str(real_loras_dir).lower():
|
|
return str(real_loras_dir)
|
|
return original_realpath(path, *args, **kwargs)
|
|
|
|
monkeypatch.setattr(config_module.os.path, "exists", fake_exists)
|
|
monkeypatch.setattr(config_module.os.path, "realpath", fake_realpath)
|
|
monkeypatch.setattr(
|
|
config_module.os.path,
|
|
"normcase",
|
|
lambda value: original_normcase(value).lower(),
|
|
)
|
|
|
|
config_instance = config_module.Config()
|
|
primary_path = str(loras_link).replace("loras_link", "LORAS_LINK")
|
|
extra_path = str(real_loras_dir).replace("loras_real", "loras_real")
|
|
|
|
library_config = {
|
|
"folder_paths": {
|
|
"loras": [primary_path],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
"extra_folder_paths": {
|
|
"loras": [extra_path.upper()],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
}
|
|
|
|
with caplog.at_level("WARNING", logger=config_module.logger.name):
|
|
config_instance.apply_library_settings(library_config)
|
|
|
|
assert _identity(config_instance.loras_roots) == _identity([primary_path])
|
|
assert _identity(config_instance.extra_loras_roots) == _identity([])
|
|
assert any("same lora folder" in record.message.lower() for record in caplog.records)
|
|
|
|
|
|
def test_apply_library_settings_ignores_missing_extra_lora_paths(monkeypatch, tmp_path, caplog):
|
|
"""Missing extra paths should be ignored without overlap warnings."""
|
|
loras_dir = tmp_path / "loras"
|
|
loras_dir.mkdir()
|
|
missing_extra = tmp_path / "missing_loras"
|
|
|
|
config_instance = config_module.Config()
|
|
library_config = {
|
|
"folder_paths": {
|
|
"loras": [str(loras_dir)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
"extra_folder_paths": {
|
|
"loras": [str(missing_extra)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
}
|
|
|
|
with caplog.at_level("WARNING", logger=config_module.logger.name):
|
|
config_instance.apply_library_settings(library_config)
|
|
|
|
assert _identity(config_instance.loras_roots) == _identity([str(loras_dir)])
|
|
assert _identity(config_instance.extra_loras_roots) == _identity([])
|
|
assert not any("same lora folder" in record.message.lower() for record in caplog.records)
|
|
|
|
|
|
def test_apply_library_settings_ignores_extra_lora_path_overlapping_primary_root_symlink(
|
|
tmp_path, caplog
|
|
):
|
|
"""Extra LoRA paths should be ignored when already reachable via a first-level symlink under the primary root."""
|
|
loras_dir = tmp_path / "loras"
|
|
loras_dir.mkdir()
|
|
external_dir = tmp_path / "external_loras"
|
|
external_dir.mkdir()
|
|
link_dir = loras_dir / "link"
|
|
link_dir.symlink_to(external_dir, target_is_directory=True)
|
|
|
|
config_instance = config_module.Config()
|
|
library_config = {
|
|
"folder_paths": {
|
|
"loras": [str(loras_dir)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
"extra_folder_paths": {
|
|
"loras": [str(external_dir)],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
}
|
|
|
|
with caplog.at_level("WARNING", logger=config_module.logger.name):
|
|
config_instance.apply_library_settings(library_config)
|
|
|
|
assert _identity(config_instance.loras_roots) == _identity([str(loras_dir)])
|
|
assert _identity(config_instance.extra_loras_roots) == _identity([])
|
|
assert any(
|
|
"same lora folder" in record.message.lower()
|
|
for record in caplog.records
|
|
)
|
|
|
|
|
|
def test_save_paths_removes_stale_empty_default_when_comfyui_exists(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path,
|
|
):
|
|
"""When an empty-shell 'default' library coexists with 'comfyui', the
|
|
stale 'default' entry should be removed and 'comfyui' activated."""
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
|
|
class FakeSettingsService:
|
|
def __init__(self):
|
|
# Replicate the user's settings.json: empty default + populated comfyui
|
|
self.libraries = {
|
|
"default": {
|
|
"folder_paths": {},
|
|
"extra_folder_paths": {},
|
|
"default_lora_root": "",
|
|
"default_checkpoint_root": "",
|
|
"default_unet_root": "",
|
|
"default_embedding_root": "",
|
|
"recipes_path": "",
|
|
},
|
|
"comfyui": {
|
|
"folder_paths": {
|
|
key: list(value) for key, value in folder_paths.items()
|
|
},
|
|
"default_lora_root": folder_paths["loras"][0],
|
|
"default_checkpoint_root": folder_paths["checkpoints"][0],
|
|
"default_embedding_root": folder_paths["embeddings"][0],
|
|
},
|
|
}
|
|
# No active_library key — get_active_library_name() falls back to
|
|
# dict order, returning "default".
|
|
self.active_library = "default"
|
|
self.delete_calls: list[str] = []
|
|
self.upsert_calls: list[tuple[str, dict[str, Any]]] = []
|
|
|
|
def get_libraries(self):
|
|
return dict(self.libraries)
|
|
|
|
def delete_library(self, name: str):
|
|
self.delete_calls.append(name)
|
|
self.libraries.pop(name, None)
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.upsert_calls.append((name, payload))
|
|
self.libraries[name] = {**payload}
|
|
if payload.get("activate"):
|
|
self.active_library = name
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_module.Config()
|
|
|
|
assert fake_settings.delete_calls == ["default"]
|
|
assert "default" not in fake_settings.libraries
|
|
assert set(fake_settings.libraries.keys()) == {"comfyui"}
|
|
|
|
assert len(fake_settings.upsert_calls) == 1
|
|
name, payload = fake_settings.upsert_calls[0]
|
|
assert name == "comfyui"
|
|
assert payload["activate"] is True
|
|
assert fake_settings.active_library == "comfyui"
|
|
|
|
|
|
def test_save_paths_keeps_configured_root_of_a_switched_off_drive(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
"""A root whose directory is missing right now must stay in the library.
|
|
|
|
`upsert_library(folder_paths=...)` replaces the stored paths, so persisting
|
|
the existence-filtered live list would erase a drive that happened to be
|
|
switched off when ComfyUI started. A path the host no longer configures must
|
|
still be dropped.
|
|
"""
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
readable = folder_paths["loras"][0]
|
|
switched_off = str(tmp_path / "drive-Z" / "loras")
|
|
removed_by_user = str(tmp_path / "old-location" / "loras")
|
|
# The host still configures the switched-off drive; it no longer configures
|
|
# the old location (that one only survives in the stored library paths).
|
|
folder_paths["loras"] = [switched_off, readable]
|
|
|
|
class FakeSettingsService:
|
|
active_library = "comfyui"
|
|
name: str = ""
|
|
payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {
|
|
"comfyui": {
|
|
"folder_paths": {
|
|
"loras": [removed_by_user, readable],
|
|
"checkpoints": [],
|
|
"unet": [],
|
|
"embeddings": [],
|
|
},
|
|
"default_lora_root": switched_off,
|
|
}
|
|
}
|
|
|
|
def rename_library(self, *_):
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.name = name
|
|
self.payload = payload
|
|
|
|
fake_settings = FakeSettingsService()
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
|
|
config_instance = config_module.Config()
|
|
|
|
persisted = fake_settings.payload["folder_paths"]["loras"]
|
|
# The switched-off drive keeps its configured path...
|
|
assert _identity(switched_off.replace("\\", "/")) in _identity(persisted)
|
|
assert _identity(readable.replace("\\", "/")) in _identity(persisted)
|
|
# ...the path the host really dropped is gone...
|
|
assert _identity(removed_by_user.replace("\\", "/")) not in _identity(persisted)
|
|
# ...and the live list still only holds what is readable right now.
|
|
assert _identity(config_instance.loras_roots) == _identity([readable.replace("\\", "/")])
|
|
# The user's default root survives because it is merely unavailable.
|
|
assert _identity(fake_settings.payload["default_lora_root"]) == _identity(switched_off.replace("\\", "/"))
|
|
|
|
|
|
# --- roots the host registered but never created (issue #1146) --------------
|
|
|
|
|
|
class _FakePersistentCache:
|
|
"""Stand-in for PersistentModelCache in the startup sync."""
|
|
|
|
def __init__(self, cached_roots=None, error: Exception | None = None):
|
|
self._cached_roots = cached_roots or {}
|
|
self._error = error
|
|
self.queries: List[tuple] = []
|
|
|
|
def roots_with_cached_entries(self, model_type: str, roots):
|
|
self.queries.append((model_type, list(roots)))
|
|
if self._error is not None:
|
|
raise self._error
|
|
known = {path.replace("\\", "/") for path in self._cached_roots.get(model_type, [])}
|
|
return {
|
|
root for root in roots if root.replace("\\", "/") in known
|
|
}
|
|
|
|
|
|
def _stub_persistent_cache(monkeypatch: pytest.MonkeyPatch, cache) -> None:
|
|
from py.services import persistent_model_cache as persistent_model_cache_module
|
|
|
|
monkeypatch.setattr(
|
|
persistent_model_cache_module, "get_persistent_cache", lambda: cache
|
|
)
|
|
|
|
|
|
class _LibrarySettingsService:
|
|
"""Minimal settings service recording what the startup sync persists."""
|
|
|
|
active_library = "comfyui"
|
|
|
|
def __init__(self, library: Dict[str, Any]):
|
|
self._library = library
|
|
self.payload: Dict[str, Any] = {}
|
|
|
|
def get_libraries(self):
|
|
return {"comfyui": self._library}
|
|
|
|
def rename_library(self, *_): # pragma: no cover - defensive guard
|
|
raise AssertionError("rename_library should not be invoked")
|
|
|
|
def delete_library(self, *_): # pragma: no cover - defensive guard
|
|
raise AssertionError("delete_library should not be invoked")
|
|
|
|
def get_active_library_name(self):
|
|
return self.active_library
|
|
|
|
def upsert_library(self, name: str, **payload):
|
|
self.payload = payload
|
|
|
|
|
|
def test_save_paths_drops_registered_directories_that_never_existed(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
"""ComfyUI registers `<output>/<type>` for its save nodes unconditionally.
|
|
|
|
Those directories are not library paths when they do not exist and hold no
|
|
cached models: persisting them brings them back as "unavailable" roots on
|
|
every boot.
|
|
"""
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
unet_dir = tmp_path / "unet"
|
|
unet_dir.mkdir()
|
|
folder_paths["unet"] = [str(unet_dir)]
|
|
output_loras = str(tmp_path / "output" / "loras")
|
|
output_checkpoints = str(tmp_path / "output" / "checkpoints")
|
|
output_unet = str(tmp_path / "output" / "diffusion_models")
|
|
output_embeddings = str(tmp_path / "output" / "embeddings")
|
|
folder_paths["loras"].append(output_loras)
|
|
folder_paths["checkpoints"].append(output_checkpoints)
|
|
folder_paths["unet"].append(output_unet)
|
|
folder_paths["embeddings"].append(output_embeddings)
|
|
|
|
fake_settings = _LibrarySettingsService(
|
|
{
|
|
"folder_paths": {key: list(value) for key, value in folder_paths.items()},
|
|
"default_lora_root": folder_paths["loras"][0],
|
|
"default_checkpoint_root": folder_paths["checkpoints"][0],
|
|
"default_embedding_root": folder_paths["embeddings"][0],
|
|
}
|
|
)
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
cache = _FakePersistentCache()
|
|
_stub_persistent_cache(monkeypatch, cache)
|
|
|
|
config_module.Config()
|
|
|
|
persisted = fake_settings.payload["folder_paths"]
|
|
for key, never_created in (
|
|
("loras", output_loras),
|
|
("checkpoints", output_checkpoints),
|
|
("unet", output_unet),
|
|
("embeddings", output_embeddings),
|
|
):
|
|
assert _identity(never_created.replace("\\", "/")) not in _identity(persisted[key]), key
|
|
# The real root of that key is untouched.
|
|
assert _identity(folder_paths[key][0].replace("\\", "/")) in _identity(persisted[key]), key
|
|
# Lora and checkpoint roots are looked up in their own model type.
|
|
assert [model_type for model_type, _roots in cache.queries] == [
|
|
"lora",
|
|
"checkpoint",
|
|
"checkpoint",
|
|
"embedding",
|
|
]
|
|
|
|
|
|
def test_save_paths_keeps_an_unavailable_root_that_has_cached_models(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
"""A switched-off drive keeps its path: its models are still cached."""
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
readable = folder_paths["loras"][0]
|
|
switched_off = str(tmp_path / "drive-Z" / "loras")
|
|
folder_paths["loras"] = [readable, switched_off]
|
|
|
|
fake_settings = _LibrarySettingsService(
|
|
{
|
|
"folder_paths": {"loras": [readable]},
|
|
"default_lora_root": readable,
|
|
}
|
|
)
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
_stub_persistent_cache(
|
|
monkeypatch, _FakePersistentCache({"lora": [switched_off]})
|
|
)
|
|
|
|
config_module.Config()
|
|
|
|
persisted = fake_settings.payload["folder_paths"]["loras"]
|
|
assert _identity(switched_off.replace("\\", "/")) in _identity(persisted)
|
|
assert _identity(readable.replace("\\", "/")) in _identity(persisted)
|
|
|
|
|
|
def test_save_paths_keeps_every_root_when_the_cache_cannot_be_read(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
"""No answer from the cache means no root is dropped."""
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
readable = folder_paths["loras"][0]
|
|
unknown = str(tmp_path / "drive-Z" / "loras")
|
|
folder_paths["loras"] = [readable, unknown]
|
|
|
|
fake_settings = _LibrarySettingsService(
|
|
{
|
|
"folder_paths": {"loras": [readable]},
|
|
"default_lora_root": readable,
|
|
}
|
|
)
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
_stub_persistent_cache(
|
|
monkeypatch, _FakePersistentCache(error=FileNotFoundError("no cache"))
|
|
)
|
|
|
|
config_module.Config()
|
|
|
|
persisted = fake_settings.payload["folder_paths"]["loras"]
|
|
assert _identity(unknown.replace("\\", "/")) in _identity(persisted)
|
|
|
|
|
|
def test_save_paths_keeps_the_root_a_default_setting_points_at(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
):
|
|
"""An empty unavailable default root must not be dropped.
|
|
|
|
Dropping it would let the next boot "repair" the default onto another root and
|
|
silently retarget downloads. ``default_unet_root`` is only known from the
|
|
stored library (the sync resolves the lora/checkpoint/embedding ones itself),
|
|
so this covers the fallback to the stored value.
|
|
"""
|
|
folder_paths = _setup_config_environment(monkeypatch, tmp_path)
|
|
unet_dir = tmp_path / "unet"
|
|
unet_dir.mkdir()
|
|
default_target = str(tmp_path / "drive-Z" / "unet")
|
|
folder_paths["unet"] = [str(unet_dir), default_target]
|
|
|
|
fake_settings = _LibrarySettingsService(
|
|
{
|
|
"folder_paths": {"unet": [str(unet_dir)]},
|
|
"default_unet_root": default_target,
|
|
}
|
|
)
|
|
monkeypatch.setattr(settings_manager_module, "settings", fake_settings)
|
|
_stub_persistent_cache(monkeypatch, _FakePersistentCache())
|
|
|
|
config_module.Config()
|
|
|
|
persisted = fake_settings.payload["folder_paths"]["unet"]
|
|
assert _identity(default_target.replace("\\", "/")) in _identity(persisted)
|
|
assert _identity(str(unet_dir).replace("\\", "/")) in _identity(persisted)
|