mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-05-15 03:27:24 +08:00
feat(extra-paths): introduce extra_paths.yaml with full path configuration
Replace the model-only extra_model_paths.yaml with a more generic
extra_paths.yaml that covers all ComfyUI path configuration in one file.
New schema (nested style):
comfyui:
base_path: /path/to/comfyui/ # install root
output: output/ # → set_output_directory()
input: input/
temp: temp/
user: user/
custom_nodes: custom_nodes/ # explicit only, never auto-scanned
models:
base_path: models/ # model root, relative to parent base_path
is_default: true
checkpoints: checkpoints/ # or omit all categories to auto-scan
Key changes:
- System directory keys (output/input/temp/user) call set_*_directory()
- models: sub-block separates model paths from install-root paths; base_path
at block root = install root; models/base_path = model root
- custom_nodes never auto-registered by implicit scan (fixes CodeRabbit #13560)
- Flat style fully preserved for backward compat with extra_model_paths.yaml
- extra_paths.yaml loaded first; deprecation warning logged if both present
- extra_paths.yaml.example covers all 22 model categories with preset paths
- extra_model_paths.yaml.example gains a deprecation note
This commit is contained in:
parent
5e3f15a830
commit
feee1c7a85
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@ __pycache__/
|
||||
/custom_nodes/
|
||||
!custom_nodes/example_node.py.example
|
||||
extra_model_paths.yaml
|
||||
extra_paths.yaml
|
||||
/.vs
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
@ -1,8 +1,16 @@
|
||||
#Rename this to extra_model_paths.yaml and ComfyUI will load it
|
||||
#
|
||||
# DEPRECATED: extra_model_paths.yaml is superseded by extra_paths.yaml, which supports
|
||||
# all path configuration (system dirs, custom_nodes, and models) in a cleaner format.
|
||||
# See extra_paths.yaml.example. This file continues to work for backward compatibility.
|
||||
|
||||
#config for comfyui
|
||||
#your base path should be either an existing comfy install or a central folder where you store all of your models, loras, etc.
|
||||
|
||||
# When base_path is set, any standard subdirectory that exists on disk is automatically
|
||||
# registered — the explicit paths below are optional and only needed to override a
|
||||
# category or point it to a non-standard location.
|
||||
|
||||
#comfyui:
|
||||
# base_path: path/to/comfyui/
|
||||
# # You can use is_default to mark that these folders should be listed first, and used as the default dirs for eg downloads
|
||||
|
||||
84
extra_paths.yaml.example
Normal file
84
extra_paths.yaml.example
Normal file
@ -0,0 +1,84 @@
|
||||
#Rename this to extra_paths.yaml and ComfyUI will load it
|
||||
#This is the successor to extra_model_paths.yaml and supports all path configuration in one file.
|
||||
|
||||
#config for comfyui
|
||||
#Set base_path to your ComfyUI install root. System directories (output, input, temp, user)
|
||||
#and custom_nodes are resolved relative to base_path.
|
||||
#
|
||||
#Model paths go under the 'models' block. If you only set models/base_path, all standard
|
||||
#subdirectories that exist on disk are automatically registered — no need to list them.
|
||||
#Explicit paths under models/ are optional and only needed to override a specific category
|
||||
#or point it to a non-standard location.
|
||||
|
||||
#comfyui:
|
||||
# base_path: path/to/comfyui/
|
||||
# # System directories (relative to base_path, or absolute)
|
||||
# output: output/
|
||||
# input: input/
|
||||
# temp: temp/
|
||||
# user: user/
|
||||
# # Custom nodes directory (not auto-scanned; explicit only)
|
||||
# custom_nodes: custom_nodes/
|
||||
# models:
|
||||
# base_path: models/
|
||||
# # You can use is_default to mark that these folders should be listed first,
|
||||
# # and used as the default dirs for eg downloads
|
||||
# #is_default: true
|
||||
# checkpoints: checkpoints/
|
||||
# text_encoders: |
|
||||
# text_encoders/
|
||||
# clip/ # legacy location still supported
|
||||
# clip_vision: clip_vision/
|
||||
# configs: configs/
|
||||
# controlnet: |
|
||||
# controlnet/
|
||||
# t2i_adapter/
|
||||
# diffusion_models: |
|
||||
# diffusion_models/
|
||||
# unet/
|
||||
# diffusers: diffusers/
|
||||
# embeddings: embeddings/
|
||||
# frame_interpolation: frame_interpolation/
|
||||
# gligen: gligen/
|
||||
# hypernetworks: hypernetworks/
|
||||
# latent_upscale_models: latent_upscale_models/
|
||||
# loras: loras/
|
||||
# model_patches: model_patches/
|
||||
# photomaker: photomaker/
|
||||
# style_models: style_models/
|
||||
# upscale_models: upscale_models/
|
||||
# vae: vae/
|
||||
# vae_approx: vae_approx/
|
||||
# audio_encoders: audio_encoders/
|
||||
# classifiers: classifiers/
|
||||
|
||||
|
||||
#config for a1111 ui
|
||||
#all you have to do is uncomment this (remove the #) and change the base_path to where yours is installed
|
||||
|
||||
#a111:
|
||||
# models:
|
||||
# base_path: path/to/stable-diffusion-webui/
|
||||
# checkpoints: models/Stable-diffusion
|
||||
# configs: models/Stable-diffusion
|
||||
# vae: models/VAE
|
||||
# loras: |
|
||||
# models/Lora
|
||||
# models/LyCORIS
|
||||
# upscale_models: |
|
||||
# models/ESRGAN
|
||||
# models/RealESRGAN
|
||||
# models/SwinIR
|
||||
# embeddings: embeddings
|
||||
# hypernetworks: models/hypernetworks
|
||||
# controlnet: models/ControlNet
|
||||
|
||||
|
||||
# For a full list of supported model category keys (style_models, vae_approx, hypernetworks,
|
||||
# photomaker, model_patches, audio_encoders, classifiers, etc.) see folder_paths.py.
|
||||
|
||||
#other_ui:
|
||||
# models:
|
||||
# base_path: path/to/ui
|
||||
# checkpoints: models/checkpoints
|
||||
# gligen: models/gligen
|
||||
16
main.py
16
main.py
@ -93,8 +93,20 @@ if args.enable_manager:
|
||||
|
||||
|
||||
def apply_custom_paths():
|
||||
# extra model paths
|
||||
extra_model_paths_config_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "extra_model_paths.yaml")
|
||||
install_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# extra_paths.yaml — primary config (superset of extra_model_paths.yaml)
|
||||
extra_paths_config_path = os.path.join(install_dir, "extra_paths.yaml")
|
||||
extra_model_paths_config_path = os.path.join(install_dir, "extra_model_paths.yaml")
|
||||
|
||||
if os.path.isfile(extra_paths_config_path):
|
||||
utils.extra_config.load_extra_path_config(extra_paths_config_path)
|
||||
if os.path.isfile(extra_model_paths_config_path):
|
||||
logging.warning(
|
||||
"Both extra_paths.yaml and extra_model_paths.yaml found. "
|
||||
"extra_model_paths.yaml is deprecated; please migrate to extra_paths.yaml."
|
||||
)
|
||||
|
||||
if os.path.isfile(extra_model_paths_config_path):
|
||||
utils.extra_config.load_extra_path_config(extra_model_paths_config_path)
|
||||
|
||||
|
||||
@ -301,3 +301,271 @@ def test_load_extra_path_config_no_base_path(
|
||||
actual_diffusion = folder_paths.folder_names_and_paths["diffusion_models"][0]
|
||||
assert len(actual_diffusion) == 1, "Should have one path for 'diffusion_models'."
|
||||
assert actual_diffusion[0] == os.path.abspath(expected_unet)
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_load_extra_path_config_implicit_subdirs(
|
||||
mock_yaml_load, clear_folder_paths, tmp_path
|
||||
):
|
||||
"""
|
||||
When base_path is set and no explicit sub-paths are declared, any subdir
|
||||
whose name matches a known category is auto-registered.
|
||||
"""
|
||||
# Create real subdirs that match known categories
|
||||
(tmp_path / "checkpoints").mkdir()
|
||||
(tmp_path / "loras").mkdir()
|
||||
(tmp_path / "unknown_dir").mkdir() # not a registered category — should be ignored
|
||||
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"base_path": str(tmp_path),
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
|
||||
# Pre-populate only the categories we're testing so clear_folder_paths doesn't hide them
|
||||
folder_paths.folder_names_and_paths["checkpoints"] = ([], set())
|
||||
folder_paths.folder_names_and_paths["loras"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_model_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("") # content ignored; yaml.safe_load is mocked
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
assert str(tmp_path / "checkpoints") in folder_paths.folder_names_and_paths["checkpoints"][0]
|
||||
assert str(tmp_path / "loras") in folder_paths.folder_names_and_paths["loras"][0]
|
||||
assert "unknown_dir" not in folder_paths.folder_names_and_paths
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_implicit_scan_excludes_custom_nodes(
|
||||
mock_yaml_load, clear_folder_paths, tmp_path
|
||||
):
|
||||
"""custom_nodes must never be auto-registered by the implicit scan."""
|
||||
(tmp_path / "custom_nodes").mkdir()
|
||||
(tmp_path / "checkpoints").mkdir()
|
||||
|
||||
config_data = {"comfyui": {"base_path": str(tmp_path)}}
|
||||
mock_yaml_load.return_value = config_data
|
||||
|
||||
folder_paths.folder_names_and_paths["checkpoints"] = ([], set())
|
||||
folder_paths.folder_names_and_paths["custom_nodes"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
assert str(tmp_path / "checkpoints") in folder_paths.folder_names_and_paths["checkpoints"][0]
|
||||
assert str(tmp_path / "custom_nodes") not in folder_paths.folder_names_and_paths["custom_nodes"][0], \
|
||||
"custom_nodes must not be auto-registered by the implicit scan"
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_load_extra_path_config_explicit_overrides_implicit(
|
||||
mock_yaml_load, clear_folder_paths, tmp_path
|
||||
):
|
||||
"""
|
||||
Explicit sub-path declarations take precedence; the implicit scan must not
|
||||
double-register a category that was already declared explicitly.
|
||||
"""
|
||||
(tmp_path / "loras").mkdir()
|
||||
custom_loras = tmp_path / "my_custom_loras"
|
||||
custom_loras.mkdir()
|
||||
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"base_path": str(tmp_path),
|
||||
"loras": "my_custom_loras", # explicit override
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
folder_paths.folder_names_and_paths["loras"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_model_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
registered = folder_paths.folder_names_and_paths["loras"][0]
|
||||
assert str(custom_loras) in registered
|
||||
assert str(tmp_path / "loras") not in registered, "Implicit path must not override explicit"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def save_restore_system_dirs():
|
||||
"""Save and restore folder_paths system directories around a test."""
|
||||
saved = {
|
||||
"output": folder_paths.get_output_directory(),
|
||||
"input": folder_paths.get_input_directory(),
|
||||
"temp": folder_paths.get_temp_directory(),
|
||||
"user": folder_paths.get_user_directory(),
|
||||
}
|
||||
yield
|
||||
folder_paths.set_output_directory(saved["output"])
|
||||
folder_paths.set_input_directory(saved["input"])
|
||||
folder_paths.set_temp_directory(saved["temp"])
|
||||
folder_paths.set_user_directory(saved["user"])
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_system_dir_keys(mock_yaml_load, save_restore_system_dirs, tmp_path):
|
||||
"""System directory keys (output, input, temp, user) call set_*_directory()."""
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"base_path": str(tmp_path),
|
||||
"output": "my_output/",
|
||||
"input": "my_input/",
|
||||
"temp": "my_temp/",
|
||||
"user": "my_user/",
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
|
||||
yaml_path = str(tmp_path / "extra_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
assert folder_paths.get_output_directory() == os.path.normpath(str(tmp_path / "my_output"))
|
||||
assert folder_paths.get_input_directory() == os.path.normpath(str(tmp_path / "my_input"))
|
||||
assert folder_paths.get_temp_directory() == os.path.normpath(str(tmp_path / "my_temp"))
|
||||
assert folder_paths.get_user_directory() == os.path.normpath(str(tmp_path / "my_user"))
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_nested_models_block(mock_yaml_load, clear_folder_paths, tmp_path):
|
||||
"""Nested models: block registers model paths relative to models/base_path."""
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"base_path": str(tmp_path),
|
||||
"models": {
|
||||
"base_path": "models/",
|
||||
"checkpoints": "checkpoints/",
|
||||
"loras": "loras/",
|
||||
},
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
|
||||
folder_paths.folder_names_and_paths["checkpoints"] = ([], set())
|
||||
folder_paths.folder_names_and_paths["loras"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
expected_ckpt = os.path.normpath(str(tmp_path / "models" / "checkpoints"))
|
||||
expected_loras = os.path.normpath(str(tmp_path / "models" / "loras"))
|
||||
assert expected_ckpt in folder_paths.folder_names_and_paths["checkpoints"][0]
|
||||
assert expected_loras in folder_paths.folder_names_and_paths["loras"][0]
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_nested_models_is_default(mock_yaml_load, clear_folder_paths, tmp_path):
|
||||
"""is_default under models: applies to all model paths in that block."""
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"models": {
|
||||
"base_path": str(tmp_path),
|
||||
"is_default": True,
|
||||
"checkpoints": "checkpoints/",
|
||||
},
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
folder_paths.folder_names_and_paths["checkpoints"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
mock_add = Mock()
|
||||
with patch.object(folder_paths, "add_model_folder_path", mock_add):
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
call = mock_add.call_args_list[0]
|
||||
assert call.args[0] == "checkpoints"
|
||||
assert call.args[2] is True, "is_default under models: must be passed as True"
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_nested_models_multipath(mock_yaml_load, clear_folder_paths, tmp_path):
|
||||
"""Multi-line path values inside models: register multiple paths per category."""
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"models": {
|
||||
"base_path": str(tmp_path),
|
||||
"text_encoders": "text_encoders/\nclip/",
|
||||
},
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
folder_paths.folder_names_and_paths["text_encoders"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
registered = folder_paths.folder_names_and_paths["text_encoders"][0]
|
||||
assert os.path.normpath(str(tmp_path / "text_encoders")) in registered
|
||||
assert os.path.normpath(str(tmp_path / "clip")) in registered
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_nested_models_auto_scan(mock_yaml_load, clear_folder_paths, tmp_path):
|
||||
"""models: with only base_path auto-scans for known categories that exist on disk."""
|
||||
(tmp_path / "models" / "checkpoints").mkdir(parents=True)
|
||||
(tmp_path / "models" / "loras").mkdir()
|
||||
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"base_path": str(tmp_path),
|
||||
"models": {"base_path": "models/"},
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
folder_paths.folder_names_and_paths["checkpoints"] = ([], set())
|
||||
folder_paths.folder_names_and_paths["loras"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
assert os.path.normpath(str(tmp_path / "models" / "checkpoints")) in \
|
||||
folder_paths.folder_names_and_paths["checkpoints"][0]
|
||||
assert os.path.normpath(str(tmp_path / "models" / "loras")) in \
|
||||
folder_paths.folder_names_and_paths["loras"][0]
|
||||
|
||||
|
||||
@patch("yaml.safe_load")
|
||||
def test_explicit_custom_nodes_key(mock_yaml_load, clear_folder_paths, tmp_path):
|
||||
"""Explicit custom_nodes key in a block registers the path via add_model_folder_path."""
|
||||
config_data = {
|
||||
"comfyui": {
|
||||
"base_path": str(tmp_path),
|
||||
"custom_nodes": "my_nodes/",
|
||||
}
|
||||
}
|
||||
mock_yaml_load.return_value = config_data
|
||||
folder_paths.folder_names_and_paths["custom_nodes"] = ([], set())
|
||||
|
||||
yaml_path = str(tmp_path / "extra_paths.yaml")
|
||||
with open(yaml_path, "w") as f:
|
||||
f.write("")
|
||||
|
||||
load_extra_path_config(yaml_path)
|
||||
|
||||
assert os.path.normpath(str(tmp_path / "my_nodes")) in \
|
||||
folder_paths.folder_names_and_paths["custom_nodes"][0]
|
||||
|
||||
|
||||
@ -1,34 +1,101 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import yaml
|
||||
import folder_paths
|
||||
import logging
|
||||
|
||||
def load_extra_path_config(yaml_path):
|
||||
_SYSTEM_DIR_KEYS = frozenset({"output", "input", "temp", "user"})
|
||||
|
||||
|
||||
def _resolve_base(raw: str, parent_base: str | None, yaml_dir: str) -> str:
|
||||
"""Resolve a base_path value: expand vars/user, join onto parent_base or yaml_dir if relative."""
|
||||
raw = os.path.expandvars(os.path.expanduser(raw))
|
||||
if not os.path.isabs(raw):
|
||||
anchor = parent_base if parent_base else yaml_dir
|
||||
raw = os.path.abspath(os.path.join(anchor, raw))
|
||||
return os.path.normpath(raw)
|
||||
|
||||
|
||||
def _add_model_paths(category: str, raw_value: str, base: str | None, yaml_dir: str, is_default: bool) -> None:
|
||||
"""Split a (possibly multi-line) path value and register each path as a model folder."""
|
||||
for raw in str(raw_value).split("\n"):
|
||||
raw = raw.strip()
|
||||
if not raw:
|
||||
continue
|
||||
if base and not os.path.isabs(raw):
|
||||
full_path = os.path.join(base, raw)
|
||||
elif not os.path.isabs(raw):
|
||||
full_path = os.path.abspath(os.path.join(yaml_dir, raw))
|
||||
else:
|
||||
full_path = raw
|
||||
normalized = os.path.normpath(full_path)
|
||||
logging.info("Adding extra search path %s %s", category, normalized)
|
||||
folder_paths.add_model_folder_path(category, normalized, is_default)
|
||||
|
||||
|
||||
def _implicit_scan(base: str, exclude: set[str], is_default: bool) -> None:
|
||||
"""Auto-register base/<category>/ for known model categories that exist on disk.
|
||||
|
||||
custom_nodes and system directory keys are always excluded from the scan.
|
||||
"""
|
||||
skip = _SYSTEM_DIR_KEYS | {"custom_nodes"} | exclude
|
||||
for category in folder_paths.folder_names_and_paths:
|
||||
if category in skip:
|
||||
continue
|
||||
path = os.path.normpath(os.path.join(base, category))
|
||||
if os.path.isdir(path):
|
||||
logging.info("Adding extra search path %s %s", category, path)
|
||||
folder_paths.add_model_folder_path(category, path, is_default)
|
||||
|
||||
|
||||
def load_extra_path_config(yaml_path: str) -> None:
|
||||
with open(yaml_path, 'r', encoding='utf-8') as stream:
|
||||
config = yaml.safe_load(stream)
|
||||
yaml_dir = os.path.dirname(os.path.abspath(yaml_path))
|
||||
for c in config:
|
||||
conf = config[c]
|
||||
|
||||
for _block_name, conf in config.items():
|
||||
if conf is None:
|
||||
continue
|
||||
base_path = None
|
||||
|
||||
# Pop block-level meta keys (preserved for flat backward-compat style)
|
||||
block_base = None
|
||||
if "base_path" in conf:
|
||||
base_path = conf.pop("base_path")
|
||||
base_path = os.path.expandvars(os.path.expanduser(base_path))
|
||||
if not os.path.isabs(base_path):
|
||||
base_path = os.path.abspath(os.path.join(yaml_dir, base_path))
|
||||
is_default = False
|
||||
if "is_default" in conf:
|
||||
is_default = conf.pop("is_default")
|
||||
for x in conf:
|
||||
for y in conf[x].split("\n"):
|
||||
if len(y) == 0:
|
||||
continue
|
||||
full_path = y
|
||||
if base_path:
|
||||
full_path = os.path.join(base_path, full_path)
|
||||
elif not os.path.isabs(full_path):
|
||||
full_path = os.path.abspath(os.path.join(yaml_dir, y))
|
||||
normalized_path = os.path.normpath(full_path)
|
||||
logging.info("Adding extra search path {} {}".format(x, normalized_path))
|
||||
folder_paths.add_model_folder_path(x, normalized_path, is_default)
|
||||
block_base = _resolve_base(conf.pop("base_path"), None, yaml_dir)
|
||||
block_is_default = bool(conf.pop("is_default", False))
|
||||
|
||||
has_models_block = False
|
||||
flat_model_keys: set[str] = set()
|
||||
|
||||
for key, value in conf.items():
|
||||
if key in _SYSTEM_DIR_KEYS:
|
||||
# System directory override → set_*_directory()
|
||||
path = _resolve_base(str(value).strip(), block_base, yaml_dir)
|
||||
logging.info("Setting %s directory to %s", key, path)
|
||||
getattr(folder_paths, f"set_{key}_directory")(path)
|
||||
|
||||
elif key == "custom_nodes":
|
||||
_add_model_paths("custom_nodes", value, block_base, yaml_dir, block_is_default)
|
||||
|
||||
elif key == "models" and isinstance(value, dict):
|
||||
# New nested style: models: { base_path, is_default, <categories> }
|
||||
has_models_block = True
|
||||
models_conf = dict(value)
|
||||
models_base = None
|
||||
if "base_path" in models_conf:
|
||||
models_base = _resolve_base(models_conf.pop("base_path"), block_base, yaml_dir)
|
||||
models_is_default = bool(models_conf.pop("is_default", False))
|
||||
explicit: set[str] = set(models_conf.keys())
|
||||
for cat, raw in models_conf.items():
|
||||
_add_model_paths(cat, raw, models_base, yaml_dir, models_is_default)
|
||||
if models_base:
|
||||
_implicit_scan(models_base, explicit, models_is_default)
|
||||
|
||||
else:
|
||||
# Flat model key — backward-compat style
|
||||
_add_model_paths(key, value, block_base, yaml_dir, block_is_default)
|
||||
flat_model_keys.add(key)
|
||||
|
||||
# Flat-style implicit scan (only when no nested models: block)
|
||||
if block_base and not has_models_block:
|
||||
_implicit_scan(block_base, flat_model_keys, block_is_default)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user