mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-10-09 02:52:12 -03:00
chore(libraries): deprecate multi-library support ahead of removal
Warn at startup (log + dismissible startup message) when settings.json contains more than one library, marking the feature as deprecated while keeping it fully functional. Removal is planned for one of the next releases, at which point all libraries' folder paths will be merged into a single library. Multiple folder roots within one library remain fully supported and unaffected. - SettingsManager: add _warn_if_multi_library() invoked from _migrate_to_library_registry - Settings UI: label the Active Library selector as deprecated and note the removal plan in its help text (en.json) - Docs: add deprecation banners to multi_library_design.md and library-switching.md - Remove dead code: SettingsManager.update_active_library_paths had no call sites
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
# Multi-Library Management for Standalone Mode
|
||||
|
||||
> **Deprecated:** Multi-library support is deprecated and will be removed in an
|
||||
> upcoming release. Multiple folder roots within a single library
|
||||
> (`folder_paths` / `extra_folder_paths`) remain fully supported. This document
|
||||
> is kept for historical reference only.
|
||||
|
||||
## Requirements Summary
|
||||
- **Independent libraries**: In standalone mode, users can maintain multiple libraries, where each library represents a distinct set of model folders (LoRAs, checkpoints, embeddings, etc.). Only one library is active at any given time, but users need a fast way to switch between them.
|
||||
- **Library-specific settings**: The fields that vary per library are `folder_paths`, `default_lora_root`, `default_checkpoint_root`, and `default_embedding_root` inside `settings.json`.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Library Switching and Preview Routes
|
||||
|
||||
> **Deprecated:** Multi-library support (and therefore library switching) is
|
||||
> deprecated and will be removed in an upcoming release. The dynamic preview
|
||||
> route described here will remain — it also serves single-library
|
||||
> installations.
|
||||
|
||||
Library switching no longer requires restarting the backend. The preview
|
||||
thumbnails shown in the UI are now served through a dynamic endpoint that
|
||||
resolves files against the folders registered for the active library at request
|
||||
|
||||
+2
-2
@@ -555,8 +555,8 @@
|
||||
"cardBlurAmountHelp": "Adjust the blur intensity of the header and footer overlays on model and recipe cards (0 = no blur, 20 = maximum blur)."
|
||||
},
|
||||
"folderSettings": {
|
||||
"activeLibrary": "Active Library",
|
||||
"activeLibraryHelp": "Switch between configured libraries to update default folders. Changing the selection reloads the page.",
|
||||
"activeLibrary": "Active Library (Deprecated)",
|
||||
"activeLibraryHelp": "Switch between configured libraries to update default folders. Changing the selection reloads the page. Deprecated: multi-library support will be removed in an upcoming release. Multiple folder roots within a single library remain fully supported.",
|
||||
"loadingLibraries": "Loading libraries...",
|
||||
"noLibraries": "No libraries configured",
|
||||
"defaultLoraRoot": "LoRA Root",
|
||||
|
||||
@@ -583,6 +583,39 @@ class SettingsManager:
|
||||
if changed and initial_bootstrap:
|
||||
self._needs_initial_save = True
|
||||
|
||||
self._warn_if_multi_library()
|
||||
|
||||
def _warn_if_multi_library(self) -> None:
|
||||
"""Surface a deprecation notice when more than one library is configured."""
|
||||
libraries = self.settings.get("libraries", {})
|
||||
if not isinstance(libraries, Mapping) or len(libraries) <= 1:
|
||||
return
|
||||
|
||||
names = ", ".join(sorted(str(name) for name in libraries))
|
||||
logger.warning(
|
||||
"Multi-library support is deprecated and will be removed in an "
|
||||
"upcoming release. Detected %d libraries in settings.json (%s). "
|
||||
"Multiple folder roots within a single library remain fully "
|
||||
"supported; please consolidate your libraries into one.",
|
||||
len(libraries),
|
||||
names,
|
||||
)
|
||||
self._add_startup_message(
|
||||
code="multi-library-deprecated",
|
||||
title="Multi-library support is deprecated",
|
||||
message=(
|
||||
f"This installation has {len(libraries)} libraries configured in "
|
||||
f"settings.json ({names}). Multi-library support is deprecated and "
|
||||
"will be removed in an upcoming release; at that point all "
|
||||
"libraries' folder paths will be merged into a single library. "
|
||||
"Multiple folder roots within a single library remain fully "
|
||||
"supported, so consider consolidating into one library now."
|
||||
),
|
||||
severity="warning",
|
||||
actions=self._default_settings_actions(),
|
||||
dismissible=True,
|
||||
)
|
||||
|
||||
def _sync_active_library_to_root(self, *, save: bool = False) -> None:
|
||||
"""Update top-level folder path settings to mirror the active library."""
|
||||
libraries = self.settings.get("libraries", {})
|
||||
@@ -2382,34 +2415,6 @@ class SettingsManager:
|
||||
if was_active:
|
||||
self._notify_library_change(self.settings["active_library"])
|
||||
|
||||
def update_active_library_paths(
|
||||
self,
|
||||
folder_paths: Mapping[str, Iterable[str]],
|
||||
*,
|
||||
extra_folder_paths: Optional[Mapping[str, Iterable[str]]] = None,
|
||||
default_lora_root: Optional[str] = None,
|
||||
default_checkpoint_root: Optional[str] = None,
|
||||
default_unet_root: Optional[str] = None,
|
||||
default_embedding_root: Optional[str] = None,
|
||||
default_other_roots: Optional[Mapping[str, str]] = None,
|
||||
recipes_path: Optional[str] = None,
|
||||
) -> None:
|
||||
"""Update folder paths for the active library."""
|
||||
|
||||
active_name = self.get_active_library_name()
|
||||
self.upsert_library(
|
||||
active_name,
|
||||
folder_paths=folder_paths,
|
||||
extra_folder_paths=extra_folder_paths,
|
||||
default_lora_root=default_lora_root,
|
||||
default_checkpoint_root=default_checkpoint_root,
|
||||
default_unet_root=default_unet_root,
|
||||
default_embedding_root=default_embedding_root,
|
||||
default_other_roots=default_other_roots,
|
||||
recipes_path=recipes_path,
|
||||
activate=True,
|
||||
)
|
||||
|
||||
def _notify_library_change(self, library_name: str) -> None:
|
||||
"""Notify dependent services that the active library changed."""
|
||||
libraries = self.settings.get("libraries", {})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from concurrent.futures import Future
|
||||
|
||||
@@ -133,6 +134,58 @@ def test_existing_folder_paths_seed_default_library(tmp_path, monkeypatch):
|
||||
assert manager.get_startup_messages() == []
|
||||
|
||||
|
||||
def test_multi_library_configuration_triggers_deprecation_warning(
|
||||
tmp_path, monkeypatch, caplog
|
||||
):
|
||||
initial = {
|
||||
"libraries": {
|
||||
"default": {"folder_paths": {"loras": ["/loras-a"]}},
|
||||
"archive": {"folder_paths": {"loras": ["/loras-b"]}},
|
||||
},
|
||||
"active_library": "default",
|
||||
}
|
||||
|
||||
with caplog.at_level(logging.WARNING, logger="py.services.settings_manager"):
|
||||
manager = _create_manager_with_settings(tmp_path, monkeypatch, initial)
|
||||
|
||||
assert any(
|
||||
"Multi-library support is deprecated" in record.getMessage()
|
||||
for record in caplog.records
|
||||
)
|
||||
deprecation = [
|
||||
message
|
||||
for message in manager.get_startup_messages()
|
||||
if message["code"] == "multi-library-deprecated"
|
||||
]
|
||||
assert len(deprecation) == 1
|
||||
assert deprecation[0]["severity"] == "warning"
|
||||
assert deprecation[0]["dismissible"] is True
|
||||
assert "archive" in deprecation[0]["message"]
|
||||
|
||||
|
||||
def test_single_library_configuration_has_no_deprecation_warning(
|
||||
tmp_path, monkeypatch, caplog
|
||||
):
|
||||
initial = {
|
||||
"libraries": {
|
||||
"default": {"folder_paths": {"loras": ["/loras-a"]}},
|
||||
},
|
||||
"active_library": "default",
|
||||
}
|
||||
|
||||
with caplog.at_level(logging.WARNING, logger="py.services.settings_manager"):
|
||||
manager = _create_manager_with_settings(tmp_path, monkeypatch, initial)
|
||||
|
||||
assert not any(
|
||||
"Multi-library support is deprecated" in record.getMessage()
|
||||
for record in caplog.records
|
||||
)
|
||||
assert not any(
|
||||
message["code"] == "multi-library-deprecated"
|
||||
for message in manager.get_startup_messages()
|
||||
)
|
||||
|
||||
|
||||
def test_environment_variable_overrides_settings(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(SettingsManager, "_save_settings", lambda self: None)
|
||||
monkeypatch.setenv("CIVITAI_API_KEY", "secret")
|
||||
|
||||
Reference in New Issue
Block a user