comfy_backup / custom_nodes /ComfyUI_HuggingFace_Downloader /HuggingFaceDownloadFolder.py
saik0s's picture
Add files using upload-large-folder tool
8d5e143 verified
Raw
History Blame Contribute Delete
4.61 kB
import os
import threading
class AnyType(str):
def __ne__(self, __value: object) -> bool:
return False
any_typ = AnyType("*")
def _make_target_folder_list():
from .file_manager import get_model_subfolders
subfolders = get_model_subfolders()
return ["custom"] + subfolders
class HuggingFaceDownloadFolder:
CATEGORY = "Hugging Face Downloaders 🤗"
OUTPUT_NODE = True
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"target_folder": (_make_target_folder_list(), {"default": "loras"}),
"link": ("STRING", {"default": ""}),
},
"optional": {
"custom_path": ("STRING", {
"default": "",
"visible_if": {"target_folder": "custom"}
}),
# "download_in_background": ("BOOLEAN", {"default": False, "label": "Download in background"}),
}
}
@staticmethod
def update_link_field(new_value, old_value):
"""
Update the link field to show the parsed view (repo+/+subfolder).
"""
from .parse_link import parse_link
try:
parsed = parse_link(new_value)
repo = parsed.get("repo", "")
subfolder = parsed.get("subfolder", "").strip("/")
updated_value = "/".join(filter(None, [repo, subfolder]))
return updated_value
except Exception as e:
print(f"[ERROR] Failed to parse link: {e}")
return new_value
RETURN_TYPES = (any_typ,)
RETURN_NAMES = ("folder name",)
FUNCTION = "download_folder"
def download_folder(self, target_folder, link, custom_path="", download_in_background=False):
"""
1) If user picks 'custom', final_folder= custom_path, else final_folder= target_folder
2) parse link => subfolder path => last_segment
if subfolder empty => use second half of the repo => "clip-vit-large-patch14"
3) call run_download_folder
4) final node output => leftover from custom path minus first segment + last_segment
"""
from .parse_link import parse_link
from .downloader import run_download_folder
# Step 1: final_folder logic
if target_folder == "custom":
final_folder = custom_path.strip().rstrip("/\\")
else:
final_folder = target_folder.strip().rstrip("/\\")
# Step 2: parse link
try:
parsed = parse_link(link)
except Exception as e:
return (f"Error parsing link: {e}",)
remote_subfolder_path = parsed.get("subfolder", "").strip("/")
if not remote_subfolder_path:
# if empty => last_segment = second half of repo => e.g. "openai/clip-vit-large-patch14" => "clip-vit-large-patch14"
splitted = parsed["repo"].split("/",1)
if len(splitted)>1:
last_segment = splitted[1]
else:
last_segment = splitted[0]
else:
last_segment = os.path.basename(remote_subfolder_path)
# Step 3: run in background or sync
if download_in_background:
threading.Thread(
target=run_download_folder,
args=(parsed, final_folder),
kwargs={"remote_subfolder_path": remote_subfolder_path, "last_segment": last_segment},
daemon=True
).start()
else:
run_download_folder(
parsed,
final_folder,
remote_subfolder_path=remote_subfolder_path,
last_segment=last_segment,
sync=True
)
# node output => leftover + last_segment if custom
if target_folder=="custom":
segments=custom_path.strip("/\\").split("/")
if len(segments)>1:
leftover_segments=segments[1:]
leftover="/".join(leftover_segments).strip("/")
if leftover and last_segment:
return (leftover + "/" + last_segment,)
elif leftover:
return (leftover,)
elif last_segment:
return (last_segment,)
else:
return ("",)
else:
if last_segment:
return (last_segment,)
else:
return ("",)
else:
if last_segment:
return (last_segment + "/",)
else:
return ("",)