mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
refactor: simplify symlink cache invalidation by removing background rescan and noise_mtime in favor of a root-path-only fingerprint.
This commit is contained in:
@@ -63,7 +63,6 @@ def test_symlink_scan_skips_file_links(monkeypatch: pytest.MonkeyPatch, tmp_path
|
||||
|
||||
def test_symlink_cache_reuses_previous_scan(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
loras_dir, settings_dir = _setup_paths(monkeypatch, tmp_path)
|
||||
monkeypatch.setattr(config_module.Config, "_schedule_symlink_rescan", lambda self: None)
|
||||
|
||||
target_dir = loras_dir / "target"
|
||||
target_dir.mkdir()
|
||||
@@ -87,7 +86,6 @@ def test_symlink_cache_reuses_previous_scan(monkeypatch: pytest.MonkeyPatch, tmp
|
||||
|
||||
def test_symlink_cache_survives_noise_mtime(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
loras_dir, settings_dir = _setup_paths(monkeypatch, tmp_path)
|
||||
monkeypatch.setattr(config_module.Config, "_schedule_symlink_rescan", lambda self: None)
|
||||
|
||||
target_dir = loras_dir / "target"
|
||||
target_dir.mkdir()
|
||||
@@ -114,7 +112,7 @@ def test_symlink_cache_survives_noise_mtime(monkeypatch: pytest.MonkeyPatch, tmp
|
||||
assert second_cfg.map_path_to_link(str(target_dir)) == _normalize(str(dir_link))
|
||||
|
||||
|
||||
def test_background_rescan_refreshes_cache(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
def test_manual_rescan_refreshes_cache(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
loras_dir, _ = _setup_paths(monkeypatch, tmp_path)
|
||||
|
||||
target_dir = loras_dir / "target"
|
||||
@@ -135,12 +133,11 @@ def test_background_rescan_refreshes_cache(monkeypatch: pytest.MonkeyPatch, tmp_
|
||||
|
||||
second_cfg = config_module.Config()
|
||||
|
||||
# Cache may still point at the old real path immediately after load
|
||||
initial_mapping = second_cfg.map_path_to_link(str(new_target))
|
||||
assert initial_mapping in {str(new_target), _normalize(str(dir_link))}
|
||||
# Cache still point at the old real path immediately after load
|
||||
assert second_cfg.map_path_to_link(str(new_target)) == _normalize(str(new_target))
|
||||
|
||||
# Background rescan should refresh the mapping to the new target and update the cache file
|
||||
second_cfg._wait_for_rescan(timeout=2.0)
|
||||
# Manual rescan should refresh the mapping to the new target
|
||||
second_cfg.rebuild_symlink_cache()
|
||||
new_real = _normalize(os.path.realpath(new_target))
|
||||
assert second_cfg._path_mappings.get(new_real) == _normalize(str(dir_link))
|
||||
assert second_cfg.map_path_to_link(str(new_target)) == _normalize(str(dir_link))
|
||||
@@ -170,7 +167,6 @@ def test_symlink_roots_are_preserved(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
monkeypatch.setattr(config_module.folder_paths, "get_folder_paths", fake_get_folder_paths)
|
||||
monkeypatch.setattr(config_module, "standalone_mode", True)
|
||||
monkeypatch.setattr(config_module, "get_settings_dir", lambda create=True: str(settings_dir))
|
||||
monkeypatch.setattr(config_module.Config, "_schedule_symlink_rescan", lambda self: None)
|
||||
|
||||
cfg = config_module.Config()
|
||||
|
||||
|
||||
128
tests/config/test_symlink_fingerprint.py
Normal file
128
tests/config/test_symlink_fingerprint.py
Normal file
@@ -0,0 +1,128 @@
|
||||
import os
|
||||
import pytest
|
||||
from py import config as config_module
|
||||
|
||||
def _setup_paths(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
settings_dir = tmp_path / "settings"
|
||||
loras_dir = tmp_path / "loras"
|
||||
loras_dir.mkdir()
|
||||
checkpoint_dir = tmp_path / "checkpoints"
|
||||
checkpoint_dir.mkdir()
|
||||
embedding_dir = tmp_path / "embeddings"
|
||||
embedding_dir.mkdir()
|
||||
|
||||
def fake_get_folder_paths(kind: str):
|
||||
mapping = {
|
||||
"loras": [str(loras_dir)],
|
||||
"checkpoints": [str(checkpoint_dir)],
|
||||
"unet": [],
|
||||
"embeddings": [str(embedding_dir)],
|
||||
}
|
||||
return mapping.get(kind, [])
|
||||
|
||||
monkeypatch.setattr(config_module.folder_paths, "get_folder_paths", fake_get_folder_paths)
|
||||
monkeypatch.setattr(config_module, "standalone_mode", True)
|
||||
monkeypatch.setattr(config_module, "get_settings_dir", lambda create=True: str(settings_dir))
|
||||
|
||||
return loras_dir, settings_dir
|
||||
|
||||
def test_fingerprint_match_skips_rescan(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
loras_dir, settings_dir = _setup_paths(monkeypatch, tmp_path)
|
||||
|
||||
# Track calls to _scan_symbolic_links
|
||||
scan_calls = 0
|
||||
original_scan = config_module.Config._scan_symbolic_links
|
||||
|
||||
def wrapped_scan(self):
|
||||
nonlocal scan_calls
|
||||
scan_calls += 1
|
||||
return original_scan(self)
|
||||
|
||||
monkeypatch.setattr(config_module.Config, "_scan_symbolic_links", wrapped_scan)
|
||||
|
||||
# 1. First initialization: should scan and cache
|
||||
cfg1 = config_module.Config()
|
||||
assert scan_calls == 1
|
||||
|
||||
# 2. Second initialization: should load from cache and skip rescan because fingerprint matches
|
||||
cfg2 = config_module.Config()
|
||||
# scan_calls should still be 1 because it loaded from cache and skipped the rescan
|
||||
assert scan_calls == 1
|
||||
|
||||
def test_mtime_change_does_not_trigger_rescan(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
loras_dir, settings_dir = _setup_paths(monkeypatch, tmp_path)
|
||||
|
||||
# Track calls to _scan_symbolic_links
|
||||
scan_calls = 0
|
||||
original_scan = config_module.Config._scan_symbolic_links
|
||||
|
||||
def wrapped_scan(self):
|
||||
nonlocal scan_calls
|
||||
scan_calls += 1
|
||||
return original_scan(self)
|
||||
|
||||
monkeypatch.setattr(config_module.Config, "_scan_symbolic_links", wrapped_scan)
|
||||
|
||||
# 1. First initialization: should scan and cache
|
||||
cfg1 = config_module.Config()
|
||||
assert scan_calls == 1
|
||||
|
||||
# 2. Modify a root directory (change mtime) - this should NOT trigger a rescan anymore
|
||||
os.utime(loras_dir, (os.path.getatime(loras_dir), os.path.getmtime(loras_dir) + 100))
|
||||
|
||||
# 3. Third initialization: should load from cache and skip rescan despite mtime change
|
||||
cfg3 = config_module.Config()
|
||||
assert scan_calls == 1
|
||||
|
||||
def test_root_path_change_triggers_rescan(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
loras_dir, settings_dir = _setup_paths(monkeypatch, tmp_path)
|
||||
|
||||
# Track calls to _scan_symbolic_links
|
||||
scan_calls = 0
|
||||
original_scan = config_module.Config._scan_symbolic_links
|
||||
|
||||
def wrapped_scan(self):
|
||||
nonlocal scan_calls
|
||||
scan_calls += 1
|
||||
return original_scan(self)
|
||||
|
||||
monkeypatch.setattr(config_module.Config, "_scan_symbolic_links", wrapped_scan)
|
||||
|
||||
# 1. First initialization
|
||||
config_module.Config()
|
||||
assert scan_calls == 1
|
||||
|
||||
# 2. Change root paths
|
||||
new_lora_dir = tmp_path / "new_loras"
|
||||
new_lora_dir.mkdir()
|
||||
|
||||
def fake_get_folder_paths_modified(kind: str):
|
||||
if kind == "loras":
|
||||
return [str(loras_dir), str(new_lora_dir)]
|
||||
return []
|
||||
|
||||
monkeypatch.setattr(config_module.folder_paths, "get_folder_paths", fake_get_folder_paths_modified)
|
||||
|
||||
# 3. Initialization with different roots should trigger rescan
|
||||
config_module.Config()
|
||||
assert scan_calls == 2
|
||||
|
||||
def test_manual_rebuild_symlink_cache(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
||||
loras_dir, settings_dir = _setup_paths(monkeypatch, tmp_path)
|
||||
|
||||
scan_calls = 0
|
||||
original_scan = config_module.Config._scan_symbolic_links
|
||||
|
||||
def wrapped_scan(self):
|
||||
nonlocal scan_calls
|
||||
scan_calls += 1
|
||||
return original_scan(self)
|
||||
|
||||
monkeypatch.setattr(config_module.Config, "_scan_symbolic_links", wrapped_scan)
|
||||
|
||||
cfg = config_module.Config()
|
||||
assert scan_calls == 1
|
||||
|
||||
# Manual trigger
|
||||
cfg.rebuild_symlink_cache()
|
||||
assert scan_calls == 2
|
||||
Reference in New Issue
Block a user