mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-01-11 23:00:51 +08:00
Fix issues with paths
This commit is contained in:
parent
a811336e58
commit
f8a00af0d2
@ -77,11 +77,11 @@ def init_default_paths(folder_names_and_paths: FolderNames, configuration: Optio
|
|||||||
hf_cache_paths = ModelPaths(["huggingface_cache"], supported_extensions=set())
|
hf_cache_paths = ModelPaths(["huggingface_cache"], supported_extensions=set())
|
||||||
# TODO: explore if there is a better way to do this
|
# TODO: explore if there is a better way to do this
|
||||||
if "HF_HUB_CACHE" in os.environ:
|
if "HF_HUB_CACHE" in os.environ:
|
||||||
hf_cache_paths.additional_absolute_directory_paths.add(os.environ.get("HF_HUB_CACHE"))
|
hf_cache_paths.additional_absolute_directory_paths.append(os.environ.get("HF_HUB_CACHE"))
|
||||||
|
|
||||||
model_paths_to_add = [
|
model_paths_to_add = [
|
||||||
ModelPaths(["checkpoints"], supported_extensions=set(supported_pt_extensions)),
|
ModelPaths(["checkpoints"], supported_extensions=set(supported_pt_extensions)),
|
||||||
ModelPaths(["configs"], additional_absolute_directory_paths={get_package_as_path("comfy.configs")}, supported_extensions={".yaml"}),
|
ModelPaths(["configs"], additional_absolute_directory_paths=[get_package_as_path("comfy.configs")], supported_extensions={".yaml"}),
|
||||||
ModelPaths(["vae"], supported_extensions=set(supported_pt_extensions)),
|
ModelPaths(["vae"], supported_extensions=set(supported_pt_extensions)),
|
||||||
ModelPaths(folder_names=["clip", "text_encoders"], supported_extensions=set(supported_pt_extensions)),
|
ModelPaths(folder_names=["clip", "text_encoders"], supported_extensions=set(supported_pt_extensions)),
|
||||||
ModelPaths(["loras"], supported_extensions=set(supported_pt_extensions)),
|
ModelPaths(["loras"], supported_extensions=set(supported_pt_extensions)),
|
||||||
@ -271,6 +271,17 @@ def add_model_folder_path(folder_name, full_folder_path: Optional[str] = None, e
|
|||||||
folder_path.paths.insert(0, full_folder_path)
|
folder_path.paths.insert(0, full_folder_path)
|
||||||
else:
|
else:
|
||||||
folder_path.paths.append(full_folder_path)
|
folder_path.paths.append(full_folder_path)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
current_default = folder_path.paths.index(full_folder_path) == 0
|
||||||
|
except ValueError:
|
||||||
|
current_default = False
|
||||||
|
if current_default != is_default:
|
||||||
|
folder_path.paths.remove(full_folder_path)
|
||||||
|
if is_default:
|
||||||
|
folder_path.paths.insert(0, full_folder_path)
|
||||||
|
else:
|
||||||
|
folder_path.paths.append(full_folder_path)
|
||||||
|
|
||||||
if extensions is not None:
|
if extensions is not None:
|
||||||
folder_path.supported_extensions |= extensions
|
folder_path.supported_extensions |= extensions
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import copy
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import itertools
|
import itertools
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import typing
|
import typing
|
||||||
import weakref
|
import weakref
|
||||||
@ -16,6 +18,8 @@ extension_mimetypes_cache = {
|
|||||||
"webp": "image",
|
"webp": "image",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def do_add(collection: list | set, index: int | None, item: Any):
|
def do_add(collection: list | set, index: int | None, item: Any):
|
||||||
if isinstance(collection, list) and index == 0:
|
if isinstance(collection, list) and index == 0:
|
||||||
@ -101,10 +105,18 @@ class PathsList:
|
|||||||
p: FolderNames = self.parent()
|
p: FolderNames = self.parent()
|
||||||
p.add_paths(self.folder_name, [path_str])
|
p.add_paths(self.folder_name, [path_str])
|
||||||
|
|
||||||
def insert(self, path_str: str, index: int):
|
def insert(self, index: int, path_str: str | Path):
|
||||||
p: FolderNames = self.parent()
|
p: FolderNames = self.parent()
|
||||||
p.add_paths(self.folder_name, [path_str], index=index)
|
p.add_paths(self.folder_name, [path_str], index=index)
|
||||||
|
|
||||||
|
def index(self, value: str | Path):
|
||||||
|
value = construct_path(value)
|
||||||
|
p: FolderNames = self.parent()
|
||||||
|
return [path for path in p.directory_paths(self.folder_name)].index(value)
|
||||||
|
|
||||||
|
def remove(self, value: str | Path):
|
||||||
|
p: FolderNames = self.parent()
|
||||||
|
p.remove_paths(self.folder_name, [value])
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class SupportedExtensions:
|
class SupportedExtensions:
|
||||||
@ -168,12 +180,21 @@ class AbstractPaths(ABC):
|
|||||||
"""Check if the given folder name is in folder_names."""
|
"""Check if the given folder name is in folder_names."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def remove_path(self, path: str | Path) -> int:
|
||||||
|
"""
|
||||||
|
removes a path
|
||||||
|
:param path: the path
|
||||||
|
:return: the number of paths removed
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class ModelPaths(AbstractPaths):
|
class ModelPaths(AbstractPaths):
|
||||||
folder_name_base_path_subdir: Path = dataclasses.field(default_factory=lambda: construct_path("models"))
|
folder_name_base_path_subdir: Path = dataclasses.field(default_factory=lambda: construct_path("models"))
|
||||||
additional_relative_directory_paths: set[Path] = dataclasses.field(default_factory=set)
|
additional_relative_directory_paths: list[Path] = dataclasses.field(default_factory=list)
|
||||||
additional_absolute_directory_paths: set[str | Path] = dataclasses.field(default_factory=set)
|
additional_absolute_directory_paths: list[str | Path] = dataclasses.field(default_factory=list)
|
||||||
folder_names_are_relative_directory_paths_too: bool = dataclasses.field(default_factory=lambda: True)
|
folder_names_are_relative_directory_paths_too: bool = dataclasses.field(default_factory=lambda: True)
|
||||||
|
|
||||||
def directory_paths(self, base_paths: Iterable[Path]) -> typing.Generator[Path]:
|
def directory_paths(self, base_paths: Iterable[Path]) -> typing.Generator[Path]:
|
||||||
@ -220,12 +241,26 @@ class ModelPaths(AbstractPaths):
|
|||||||
def has_folder_name(self, folder_name: str) -> bool:
|
def has_folder_name(self, folder_name: str) -> bool:
|
||||||
return folder_name in self.folder_names
|
return folder_name in self.folder_names
|
||||||
|
|
||||||
|
def remove_path(self, path: str | Path) -> int:
|
||||||
|
total = 0
|
||||||
|
path = construct_path(path)
|
||||||
|
for paths_list in (self.additional_absolute_directory_paths, self.additional_relative_directory_paths):
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
paths_list.remove(path)
|
||||||
|
total += 1
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return total
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class FolderNames:
|
class FolderNames:
|
||||||
application_paths: typing.Optional[ApplicationPaths] = dataclasses.field(default_factory=ApplicationPaths)
|
application_paths: typing.Optional[ApplicationPaths] = dataclasses.field(default_factory=ApplicationPaths)
|
||||||
contents: list[AbstractPaths] = dataclasses.field(default_factory=list)
|
contents: list[AbstractPaths] = dataclasses.field(default_factory=list)
|
||||||
base_paths: list[Path] = dataclasses.field(default_factory=list)
|
base_paths: list[Path] = dataclasses.field(default_factory=list)
|
||||||
|
is_root: bool = dataclasses.field(default=lambda: False)
|
||||||
|
|
||||||
def supported_extensions(self, folder_name: str) -> typing.Generator[str]:
|
def supported_extensions(self, folder_name: str) -> typing.Generator[str]:
|
||||||
for candidate in self.contents:
|
for candidate in self.contents:
|
||||||
@ -298,8 +333,8 @@ class FolderNames:
|
|||||||
fn.add(
|
fn.add(
|
||||||
ModelPaths(folder_names=[folder_name],
|
ModelPaths(folder_names=[folder_name],
|
||||||
supported_extensions=set(extensions),
|
supported_extensions=set(extensions),
|
||||||
additional_relative_directory_paths=set(path for path in paths if not Path(path).is_absolute()),
|
additional_relative_directory_paths=[path for path in paths if not Path(path).is_absolute()],
|
||||||
additional_absolute_directory_paths=set(path for path in paths if Path(path).is_absolute()), folder_names_are_relative_directory_paths_too=False
|
additional_absolute_directory_paths=[path for path in paths if Path(path).is_absolute()], folder_names_are_relative_directory_paths_too=False
|
||||||
))
|
))
|
||||||
return fn
|
return fn
|
||||||
|
|
||||||
@ -329,6 +364,12 @@ class FolderNames:
|
|||||||
if candidate.has_folder_name(folder_name):
|
if candidate.has_folder_name(folder_name):
|
||||||
self._modify_model_paths(folder_name, paths, set(), candidate, index=index)
|
self._modify_model_paths(folder_name, paths, set(), candidate, index=index)
|
||||||
|
|
||||||
|
def remove_paths(self, folder_name: str, paths: list[Path | str]):
|
||||||
|
for candidate in self.contents:
|
||||||
|
if candidate.has_folder_name(folder_name):
|
||||||
|
for path in paths:
|
||||||
|
candidate.remove_path(path)
|
||||||
|
|
||||||
def get_paths(self, folder_name: str) -> typing.Generator[AbstractPaths]:
|
def get_paths(self, folder_name: str) -> typing.Generator[AbstractPaths]:
|
||||||
for candidate in self.contents:
|
for candidate in self.contents:
|
||||||
if candidate.has_folder_name(folder_name):
|
if candidate.has_folder_name(folder_name):
|
||||||
@ -341,6 +382,7 @@ class FolderNames:
|
|||||||
if index is not None and index != 0:
|
if index is not None and index != 0:
|
||||||
raise ValueError(f"index was {index} but only 0 or None is supported")
|
raise ValueError(f"index was {index} but only 0 or None is supported")
|
||||||
|
|
||||||
|
did_add = False
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if isinstance(path, str):
|
if isinstance(path, str):
|
||||||
path = construct_path(path)
|
path = construct_path(path)
|
||||||
@ -374,9 +416,9 @@ class FolderNames:
|
|||||||
do_add(model_paths.additional_relative_directory_paths, index, relative_to_basepath)
|
do_add(model_paths.additional_relative_directory_paths, index, relative_to_basepath)
|
||||||
did_add = True
|
did_add = True
|
||||||
else:
|
else:
|
||||||
model_paths.additional_relative_directory_paths.add(relative_to_basepath)
|
do_add(model_paths.additional_relative_directory_paths, index, relative_to_basepath)
|
||||||
for resolve_folder_name in model_paths.folder_names:
|
for resolve_folder_name in model_paths.folder_names:
|
||||||
model_paths.additional_relative_directory_paths.add(model_paths.folder_name_base_path_subdir / resolve_folder_name)
|
do_add(model_paths.additional_relative_directory_paths, index, model_paths.folder_name_base_path_subdir / resolve_folder_name)
|
||||||
did_add = True
|
did_add = True
|
||||||
|
|
||||||
# since this was an absolute path that was a subdirectory of one of the base paths,
|
# since this was an absolute path that was a subdirectory of one of the base paths,
|
||||||
@ -389,7 +431,7 @@ class FolderNames:
|
|||||||
# if we got this far, none of the absolute paths were subdirectories of any base paths
|
# if we got this far, none of the absolute paths were subdirectories of any base paths
|
||||||
# add it to our absolute paths
|
# add it to our absolute paths
|
||||||
if not did_add:
|
if not did_add:
|
||||||
model_paths.additional_absolute_directory_paths.add(path)
|
do_add(model_paths.additional_absolute_directory_paths, index, path)
|
||||||
else:
|
else:
|
||||||
# since this is a relative path, peacefully add it to model_paths
|
# since this is a relative path, peacefully add it to model_paths
|
||||||
potential_folder_name = path.stem
|
potential_folder_name = path.stem
|
||||||
@ -405,7 +447,7 @@ class FolderNames:
|
|||||||
# if there already exists a folder_name by this name, do not add it, and switch to all relative paths
|
# if there already exists a folder_name by this name, do not add it, and switch to all relative paths
|
||||||
if any(candidate.has_folder_name(potential_folder_name) for candidate in self.contents):
|
if any(candidate.has_folder_name(potential_folder_name) for candidate in self.contents):
|
||||||
model_paths.folder_names_are_relative_directory_paths_too = False
|
model_paths.folder_names_are_relative_directory_paths_too = False
|
||||||
model_paths.additional_relative_directory_paths.add(path)
|
do_add(model_paths.additional_relative_directory_paths, index, path)
|
||||||
model_paths.folder_name_base_path_subdir = construct_path()
|
model_paths.folder_name_base_path_subdir = construct_path()
|
||||||
else:
|
else:
|
||||||
do_add(model_paths.folder_names, index, potential_folder_name)
|
do_add(model_paths.folder_names, index, potential_folder_name)
|
||||||
@ -418,7 +460,7 @@ class FolderNames:
|
|||||||
else:
|
else:
|
||||||
if any(candidate.has_folder_name(potential_folder_name) for candidate in self.contents):
|
if any(candidate.has_folder_name(potential_folder_name) for candidate in self.contents):
|
||||||
model_paths.folder_names_are_relative_directory_paths_too = False
|
model_paths.folder_names_are_relative_directory_paths_too = False
|
||||||
model_paths.additional_relative_directory_paths.add(path)
|
do_add(model_paths.additional_relative_directory_paths, index, path)
|
||||||
model_paths.folder_name_base_path_subdir = construct_path()
|
model_paths.folder_name_base_path_subdir = construct_path()
|
||||||
else:
|
else:
|
||||||
do_add(model_paths.folder_names, index, potential_folder_name)
|
do_add(model_paths.folder_names, index, potential_folder_name)
|
||||||
@ -488,6 +530,14 @@ class FolderNames:
|
|||||||
if __default is not None:
|
if __default is not None:
|
||||||
raise ValueError("get with default is not supported")
|
raise ValueError("get with default is not supported")
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
return copy.deepcopy(self)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
if self.is_root:
|
||||||
|
logger.warning(f"trying to clear the root folder names and paths instance, this will cause unexpected behavior")
|
||||||
|
self.contents = []
|
||||||
|
|
||||||
|
|
||||||
class SaveImagePathTuple(NamedTuple):
|
class SaveImagePathTuple(NamedTuple):
|
||||||
full_output_folder: str
|
full_output_folder: str
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class ExecutionContext:
|
|||||||
inference_mode: bool = True
|
inference_mode: bool = True
|
||||||
|
|
||||||
|
|
||||||
_current_context.set(ExecutionContext(server=ServerStub(), folder_names_and_paths=FolderNames()))
|
_current_context.set(ExecutionContext(server=ServerStub(), folder_names_and_paths=FolderNames(is_root=True)))
|
||||||
|
|
||||||
|
|
||||||
def current_execution_context() -> ExecutionContext:
|
def current_execution_context() -> ExecutionContext:
|
||||||
|
|||||||
@ -16,10 +16,8 @@ from comfy.execution_context import context_folder_names_and_paths
|
|||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def clear_folder_paths():
|
def clear_folder_paths():
|
||||||
# Clear the global dictionary before each test to ensure isolation
|
# Clear the global dictionary before each test to ensure isolation
|
||||||
original = folder_paths.folder_names_and_paths.copy()
|
with context_folder_names_and_paths(FolderNames()):
|
||||||
folder_paths.folder_names_and_paths.clear()
|
yield
|
||||||
yield
|
|
||||||
folder_paths.folder_names_and_paths = original
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def temp_dir():
|
def temp_dir():
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user